-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Зайцев ДА #28
base: master
Are you sure you want to change the base?
Зайцев ДА #28
Conversation
|
||
public void Generate(IEnumerable<Rectangle> items, string directory) | ||
{ | ||
var image = new Bitmap(Width, Height); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
namespace TagsCloudContainer.Visualizers | ||
{ | ||
public class ImageCreater |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Скорее Creator
using System.Drawing.Imaging; | ||
|
||
namespace TagsCloudContainer.Visualizers | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Для чистоты кода можно использовать file-scoped namespace
public IDictionary<string, int> Parse(string text) | ||
{ | ||
var dict = new Dictionary<string, int>(); | ||
string pattern = @"\b[а-яА-ЯёЁa-zA-Z]+\b"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Если заранее компилировать regex, то он будет работать сильно быстрее)
var words = Regex.Matches(text, pattern); | ||
|
||
var wordArray = new List<string>(); | ||
for (int i = 0; i < words.Count; i++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Где-то используются явные типы, а где-то var. Предлагаю писать единообразно
using System.Data; | ||
using TagsCloudContainer.FileReaders; | ||
|
||
namespace TagCloudContainerTests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Тестов меньше, чем в требованиях по домашнему заданию
-
В облаке не должно быть повторяющихся слов, размер слова должен быть тем больше, чем чаще встречается слово, не должно быть "скучных" слов (предлогов, местоимений, ...).
-
Все нетривиальные части покрой модульными тестами. Добавь несколько более крупных тестов, проверяющих работу всей программы в сборе.
@@ -0,0 +1,50 @@ | |||
using FluentAssertions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Также не нашел всех точек расширения:
Даже если требование из перспективы не выполнено, соответствующая точка расширения в вашем коде уже должна быть.
using System.Linq; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace TagsCloudContainer.Clients |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Консольный клиент стоит разместить в отдельном проекте, т.к. у него домен ответственности - взаимодействие с пользователем, тогда как у логики - быть логикой) И дальше логику можно переиспользовать в разные клиенты (например, GUI), а к ним подключать еще и консольного - точно не хорошо
{ | ||
words = new HashSet<string>(); | ||
|
||
var projectDirectory = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Давай эти настройки вынесем в отдельный класс/рекорд, и будем получать через DI
Потому что сам класс фильтрации не должен ничего знать про захардкоженные места нахождения файлов. Например, с ними ты не сможешь написать тесты корректно
Даже возможно стоит сделать отдельный класс, который будет читать файлы, а конкретно сюда через DI получать уже прочитанный контент
public void Generate(IEnumerable<Rectangle> items, string directory) | ||
{ | ||
var image = new Bitmap(Width, Height); | ||
var g = Graphics.FromImage(image); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Это disposable объект
ConsoleClient/ConsoleClient.cs
Outdated
PictureColors is null ? Constants.PictureColors : PictureColors | ||
); | ||
|
||
TagsCloudContainer.Program.Main(config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Исполняемым проектом должен быть только проект консольного клиента. Также он должен быть точкой сборки всего DI, при этом какие-то заготовки по тому, как наполнять DI могут быть в самих либах (проектов с только логикой)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CloudContainer все еще <OutputType>Exe</OutputType>
|
||
public static int Main(string[] args) | ||
{ | ||
return CommandLineApplication.Execute<ConsoleClient>(args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Стоит разделить ответственности: ответственность запуска и ответственность логики работы консольного клиента
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Тут нужно было разделить класс на два:
- Метод Main - про запуск приложения, отдельный класс, что-то типо EntryPoint.cs
- ConsoleClient - про настройки и свойства (InputDirectory и остальные), а также метод запуски консольного клиента
В целом, можно было вынести только настройки и свойства в отдельный класс и уже было бы сильно хорошо
Зачем это делать? Две ответственности: про запуск приложения и про логику непосредственно приложения. Например, на консольный клиент может захотеться написать тест. В текущем виде он неразрывен от метода Main, что будет неправильно затаскивать в тесты
ConsoleClient/ConsoleClient.cs
Outdated
@@ -0,0 +1,53 @@ | |||
using McMaster.Extensions.CommandLineUtils; | |||
using System.Drawing; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не используется
ConsoleClient/ConsoleClient.cs
Outdated
private void OnExecute() | ||
{ | ||
var config = new Config( | ||
InputDirectory is null ? Constants.InputDirectory : InputDirectory, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Как объект может быть null, если на проекте включено <Nullable>enable</Nullable>
?
{ | ||
Reader = new TxtFileReader(); | ||
var filePath = Path.Combine(FolderPath, "wordsTXT.txt"); | ||
var actual = Reader.Read(filePath); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Давай разделять пустыми строками блоки AAA
public class WordsFilter : IFilter | ||
{ | ||
private HashSet<string> words; | ||
private Config config; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не используется
|
||
public void AddStopWord(string word) | ||
{ | ||
words.Add(word); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Лишние отступы
return new Point(center.X - size.Width / 2, center.Y - size.Height / 2); | ||
} | ||
|
||
public static Point GetCenterPoint(Rectangle rect) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не используется
existingRectangle.Bounds.IntersectsWith(rectangle)); | ||
} | ||
|
||
public static Point GetCornerPoint(Point center, Size size) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Можно сделать приватным
using System.Drawing; | ||
|
||
namespace TagsCloudContainer.WordClasses; | ||
public record SizeWord(string Value, Size Size, Font font); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
После namespace стоит оставлять пустую строку)
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Folder Include="Pictures\" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Лишнее
using TagsCloudContainer.Visualizers; | ||
using TagsCloudContainer.WordSizer; | ||
|
||
public class ApplicationRunner : IApplicationRunner |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Кажется, это не Runner, а некоторый некоторый генератор изображения
); | ||
} | ||
|
||
public static IContainer BuildContainer(Config config) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ответственность наполнения контейнера не зависит от ответственности генерации изображения
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не исправлено
{ | ||
var sizeList = new List<SizeWord>(); | ||
|
||
for (int i = 10; i < 100; i += 10) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Снова про явные типы и var
for (int j = 5; j < 50; j += 5) | ||
sizeList.Add(GetDefaultSizeWord(new Size(i, j))); | ||
|
||
var rectangles = layouter.GetLayout(sizeList); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не используется
|
||
public IEnumerable<SizeWord> GetSizes(IDictionary<string, int> words) | ||
{ | ||
var screeenSize = config.PictureHeight * config.PictureWidth; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не используется
@@ -0,0 +1,64 @@ | |||
using McMaster.Extensions.CommandLineUtils; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Хочется в репозитории иметь примеры генерации изображений твоим кодом. Чтобы наглядно видеть про изменения размеров и так далее. Хотя бы тестах
var filter = new WordsFilter(config); | ||
var reader = new TxtFileReader(); | ||
|
||
var filterWords = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Если мы проверяем фильтр, то наполнение фильтра и должно быть в блоке Act
namespace TagCloudContainerTests; | ||
|
||
[TestFixture] | ||
public class FilterTests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Хочется увидеть работу фильтрации в рамках всей генерации изображения
{ | ||
var heavierWord = GetSizeSquare(sized[i].Size); | ||
var lighterWord = GetSizeSquare(sized[i + 1].Size); | ||
heavierWord.Should().BeGreaterThan(lighterWord); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А это точно будет зависеть от частотности слова, а не от длины слова? По тесту не понятно
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Для каждого слова в зависимости от его веса вычисляется максимальный занимаемы размер. Для слова с меньшим весом этот размер будет меньше, чем для слова с большим. Поэтому здесь и проверяется размер
|
||
public static int Main(string[] args) | ||
{ | ||
return CommandLineApplication.Execute<ConsoleClient>(args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Тут нужно было разделить класс на два:
- Метод Main - про запуск приложения, отдельный класс, что-то типо EntryPoint.cs
- ConsoleClient - про настройки и свойства (InputDirectory и остальные), а также метод запуски консольного клиента
В целом, можно было вынести только настройки и свойства в отдельный класс и уже было бы сильно хорошо
Зачем это делать? Две ответственности: про запуск приложения и про логику непосредственно приложения. Например, на консольный клиент может захотеться написать тест. В текущем виде он неразрывен от метода Main, что будет неправильно затаскивать в тесты
sizeList.Add(GetDefaultSizeWord(new (20, 30))); | ||
|
||
var rectangles = layouter.GetLayout(sizeList); | ||
var firstRectangle = rectangles.First(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не исправлено
{ | ||
config = new Config(); | ||
config.InputDirectory = @"C:\Users\dima0\source\repos\di-updated\TagsCloudContainer\Files\General.txt"; | ||
config.OutputDirectory = @"C:\Users\dima0\source\repos\di-updated\TagsCloudContainer\Pictures\general.jpg"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Из-за захардкоженного пути тест CircularCloudContainer_GeneralTest
не запускается
stopWords.All(x => filter.Contains(x)).Should().BeTrue(); | ||
filter.Contains("я").Should().BeFalse(); | ||
|
||
wordSizes.All(x => filter.Contains(x.Value)).Should().BeFalse(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
layout.All(x => x.font.Name == "Impact").Should().BeTrue(); | ||
layout.Any(x => x.Value == "я").Should().BeTrue(); | ||
|
||
using Image image = Image.FromFile(config.OutputDirectory); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Сейчас этот тест проверяет какие-то отдельные части, которые можно унести на юнит-тесты (размер изображения, размеры слов и тд)
Для комплексного теста могла бы подойти следующая логика: сгенерировать картинку по некоторым исходным данным. И дальше в тесте, используя те же исходные данные, генерить изображение и сверять его с изначально полученным
); | ||
} | ||
|
||
public static IContainer BuildContainer(Config config) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Не исправлено
@@ -0,0 +1,7 @@ | |||
namespace TagsCloudContainer; | |||
public static class Program |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Уже лишнее
@dmitgaranin