-
Notifications
You must be signed in to change notification settings - Fork 319
Русинов Матвей #261
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
base: master
Are you sure you want to change the base?
Русинов Матвей #261
Conversation
|
Давай тут отвечу для истории. Сначала непосредственно по твоим вопросам.
Отрезать лишнее всегда легче, чем пришить необходимое. Если этот участок кода не мешает препятствует выполнению задачи, то ничего такого в том, чтобы он пока был. Но сдается мне, что этот класс в том или ином виде тебе может пригодиться.
Не вижу здесь проблемы. У тебя каждый класс отвечает за определенный тэг в разметке - можно сказать это естественно, что их такое количество. |
TokenizerCharStreamИспользование Stream в имени как бы наталкивает на мысль о том, что объект должен освобождать какие-то ресурсы (как минимум реализовывать IDisposable). В действительности нам здесь не нужно ничего освобождать. Я бы предложил поменять имя на CharCursor или TextCursor. TokenTypeКакие значения будут представлены в перечислении TokenType? TokenPositionТекст можно рассматривать с разных сторон в зависимости от текущего контекста и задачи. К примеру:
В рамках этой задачи нам может быть удобнее рассматривать текст именно во втором варианте, ведь каждый отдельный символ для нас может иметь значение ParsingДекомпозиция выглядит неплохо. Вижу, что учтены не только отдельные теги, но и область их действия (тег может / не может входить в другой тег). Один момент:
В целом по декомпозицииИз текущего скелета видно, как оно может прийти к итоговому решению. Над декомпозицией хорошо поработал.
Предпроверку засчитываю. В итоговом решении обязательно покрой код тестами (тут действительно отличная практика для TDD) |
…code, token class and tokenize method
…ucture, finished ParserCursor.cs and Parser.cs with all logic
SquirrelLeonid
left a comment
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.
Оставил множество замечаний по стилистике кода, именованию переменных и т.д.
Ключевых момента три:
- Постараться упростить UnderscoreHandler
- Аналогично для LinkHandler
- Сделать рефакторинг в классе HtmlRenderer. Я бы сказал, что у этого наивысший приоритет.
В остальном решение весьма неплохое на мой взгляд, но шлифануть код надо.
| using Parsing; | ||
| using Rendering; | ||
|
|
||
| public class Md |
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.
При текущей реализации класс в целом может быть статичным. В тестах можно опустить методы SetUp по его созданию.
Хотя можно оставить некоторый прогрев, перед использованием
|
|
||
| public static class EscapeHandler | ||
| { | ||
| public static void HandleEscape(List<InlineTypeNode> children, ParserCursor cursor, IList<Token> tokens) |
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 void HandleLink(List<InlineTypeNode> children, ParserCursor cursor, IList<Token> tokens) | ||
| { | ||
| var link = TryParseLink(cursor, tokens); | ||
| if (link != null) children.Add(link); |
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.
Не ошибка, но я предпочитаю размещать if и строку кода в отдельных строках. Тут на твое усмотрение.
В других таких ситуациях аналогично.
| } | ||
| } | ||
|
|
||
| private static LinkNode? TryParseLink(ParserCursor cursor, IList<Token> tokens) |
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.
Если не ошибаюсь, то знак вопроса в LinkNode? можно вообще опустить. Это и так ссылочный тип.
Попробуй в .csproj убрать строку с добавлением nullable.
|
|
||
| private static LinkNode? TryParseLink(ParserCursor cursor, IList<Token> tokens) | ||
| { | ||
| var rightBracket = FindTokenBeforeEol(tokens, cursor.Index + 1, TokenType.RightBracket); |
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.
Если переменная хранит индекс, то в имени это тоже стоит отразить. Т.е. будет лучше rightBracketIndex, например. Другие переменные тоже посмотри на такое проявление
| { | ||
| ArgumentNullException.ThrowIfNull(text); | ||
|
|
||
| var cursor = new CharCursor(text); |
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.
тоже можно уточнить имя до charCursor. Упрощаем чтение кода, когда уйдем далеко от этой строчки
|
|
||
| while (!cursor.End) | ||
| { | ||
| var c = cursor.Current; |
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 tokens; | ||
| } | ||
|
|
||
| private static void ReadText(List<Token> tokens, CharCursor cursor) |
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.
Лучше избегать Side-эффектов, в частности наполнения листа. Будет лучше сменить сигнатуру метода так, чтобы он возвращал полученный токен. Ну и соответственно название поменять согласованно с новой сигнатурой.
| tokens.Add(new Token(TokenType.Text, sb.ToString())); | ||
| } | ||
|
|
||
| private static bool IsTextChar(char c) |
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.
Могу предложить написать альтернативный подход, записав значения один раз в словарь или HashSet.
Тогда в месте вызова этого метода можно будет перейти на вызов Contains
| @@ -0,0 +1,17 @@ | |||
| namespace Markdown.Tokenizing; | |||
|
|
|||
| public enum TokenType | |||
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.
Тут подсвечу два момента.
- Полезной практикой является явная нумерация значений в перечислении.
Это полезно несколькими вещами:
а) Явный контроль над числовым представлением того или иного значения (enum по сути - набор целочисленных констант)
б) Существенно сокращает вероятность ошибки в случаях, когда ты пишешь маппинг из сущностей одного уровня (транспортный), в сущности другого уровня (бизнес-логика). Напиши мне отдельно, если нужен пример - Всегда полезно в качестве первого значения резервировать Unknown, со значением 0. Это способствует обратной совместимости
…nder method to INode, so nodes now implementing it, depending on render way they need
…uge logic between new functions, it also works with a cursor now, so no -1, 0, and 1 semantic in UnderscoreHandler.cs needed now. some fields now renamed
|
В свежих правках увидел то, что хотел. HtmlRenderer стал попроще и теперь логика рендера конкретного блока - это ответственность самого блока. Если подумать, то идею можно развить и дальше с точки зрения добавления рендеров в другие форматы разметки. Но считаю это за рамками этой задачи. UnderscoreHandler тоже стало намного приятнее читать. На методы хорошо разбил. Семантика с -1 0 1 в каком то виде осталась, но теперь это вполне конкретная операция по поиску индекса, что гуд. Задачу на максимальный балл засчитываю, но посмотри и другие комментарии. |
@SquirrelLeonid