Skip to content
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

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open

Conversation

Emi1337-ops
Copy link

@Emi1337-ops Emi1337-ops commented Dec 23, 2024


public void Generate(IEnumerable<Rectangle> items, string directory)
{
var image = new Bitmap(Width, Height);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Странная ошибка
image


namespace TagsCloudContainer.Visualizers
{
public class ImageCreater

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
{

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";

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++)

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тестов меньше, чем в требованиях по домашнему заданию

  1. В облаке не должно быть повторяющихся слов, размер слова должен быть тем больше, чем чаще встречается слово, не должно быть "скучных" слов (предлогов, местоимений, ...).

  2. Все нетривиальные части покрой модульными тестами. Добавь несколько более крупных тестов, проверяющих работу всей программы в сборе.

@@ -0,0 +1,50 @@
using FluentAssertions;

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

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 =

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);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это disposable объект

PictureColors is null ? Constants.PictureColors : PictureColors
);

TagsCloudContainer.Program.Main(config);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Исполняемым проектом должен быть только проект консольного клиента. Также он должен быть точкой сборки всего DI, при этом какие-то заготовки по тому, как наполнять DI могут быть в самих либах (проектов с только логикой)

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);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Стоит разделить ответственности: ответственность запуска и ответственность логики работы консольного клиента

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут нужно было разделить класс на два:

  1. Метод Main - про запуск приложения, отдельный класс, что-то типо EntryPoint.cs
  2. ConsoleClient - про настройки и свойства (InputDirectory и остальные), а также метод запуски консольного клиента

В целом, можно было вынести только настройки и свойства в отдельный класс и уже было бы сильно хорошо

Зачем это делать? Две ответственности: про запуск приложения и про логику непосредственно приложения. Например, на консольный клиент может захотеться написать тест. В текущем виде он неразрывен от метода Main, что будет неправильно затаскивать в тесты

@@ -0,0 +1,53 @@
using McMaster.Extensions.CommandLineUtils;
using System.Drawing;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не используется

private void OnExecute()
{
var config = new Config(
InputDirectory is null ? Constants.InputDirectory : InputDirectory,

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);

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;

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);

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)

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)

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);

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\" />

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

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)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ответственность наполнения контейнера не зависит от ответственности генерации изображения

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)

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);

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;

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;

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 =

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

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);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А это точно будет зависеть от частотности слова, а не от длины слова? По тесту не понятно

Copy link
Author

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);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут нужно было разделить класс на два:

  1. Метод Main - про запуск приложения, отдельный класс, что-то типо EntryPoint.cs
  2. ConsoleClient - про настройки и свойства (InputDirectory и остальные), а также метод запуски консольного клиента

В целом, можно было вынести только настройки и свойства в отдельный класс и уже было бы сильно хорошо

Зачем это делать? Две ответственности: про запуск приложения и про логику непосредственно приложения. Например, на консольный клиент может захотеться написать тест. В текущем виде он неразрывен от метода Main, что будет неправильно затаскивать в тесты

sizeList.Add(GetDefaultSizeWord(new (20, 30)));

var rectangles = layouter.GetLayout(sizeList);
var firstRectangle = rectangles.First();

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";

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();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Появились еще
image

layout.All(x => x.font.Name == "Impact").Should().BeTrue();
layout.Any(x => x.Value == "я").Should().BeTrue();

using Image image = Image.FromFile(config.OutputDirectory);

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)

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Уже лишнее

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants