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

Попов Захар #235

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

Conversation

BlizPerfect
Copy link

@Folleach

Проведено начальное проектирование архитектуры программы.

Идея:
Сначала входная строка разбивается на упорядоченный список токенов. Токен - сущность, хранящая в себе часть строки и соответствующий этой части тег.
Есть три типа токенов:

  1. Простой токен. Хранит в себе строку без какого-либо форматирования.
  2. Токен с разметкой. Хранит в себе строку с форматированием без вложений других токенов.
  3. Составной токен. Хранит в себе строку с форматированием и вложением других токенов.

Затем, в списке токенов подменяются теги из markdown разметки на теги HTML разметки и список токенов собирается обратно в строку. В Program.cs привёл 4 примера токенов для разных ситуаций, что бы было наглядней.

Пара мыслей:

  1. Хочется отдельно сказать про переопределённый в ComplexSringToken метод ToString().
    Не отпускает идея того, что бы токен в ToString() сам возвращал своё строковое представление. Я понимаю, что это как раз работа Writer'a, но я сам как-то зациклился на этой идее. В черновой реализации каждый раз, когда составной токен возвращает своё строковое представление, создаётся новый экземпляр StringBuilder(), что расточительно. Может быть просто использовать один статический StringBuilder() для всех ToString() в ComplexSringToken, который по концу ToString() будет очищаться?
  2. Хочется услышать мнение о целесообразности приведения конкретных реализаций парсера, конвертера и врайтера в статические, а не динамические классы. Тут больше вопрос в том, как их тогда обязать реализовывать интерфейсы?
  3. При написании черновой архитектуры попробовал сделать особый упор на минимизацию действий при создании новых тегов. Например, для создания заголовков второго уровня (##), не потребуется создавать новый кодовый файл.
  4. Помню про включение опции невозможности компиляции программы при предупреждениях, подключу её уже при написании внутренностей методов.

Copy link

@Folleach Folleach left a comment

Choose a reason for hiding this comment

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

Итого
Здорово, что теперь ветка заведена специально под задачу!

Сейчас нужно чуть улучшить декомпозицию, конкретно к сущности "Токен" у меня есть некоторые вопросы, которые написаны ниже.
А также реализовать оставшиеся методы и написать к ним тесты. То есть довести задачу до её финального вида и не забыть про предупреждения от IDE, хех :)

Кстати, некоторые комментарии ниже хоть и оставлены к конкретным строчкам, но от них ожидаются исправления во всём коде.

cs/Markdown/Tags/Tag.cs Outdated Show resolved Hide resolved
cs/Markdown/Tags/MdTags/SingleMdTag.cs Outdated Show resolved Hide resolved
Comment on lines 5 to 7
namespace Markdown
{
internal class Md(IParser parser, IConverter converter, IWriter writer)

Choose a reason for hiding this comment

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

Это хорошо, что класс Md конфигурируется.
Но некоторые части лучше реализовать внутри. Например, точно ли класс для markdown должен обязывать пользователя создавать для него правила?

Нужно оставить только минимально необходимый набор параметров, которые должны быть получены извне.

Copy link

@Folleach Folleach Dec 2, 2024

Choose a reason for hiding this comment

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

Могу ли я создать класс Md и передать в него не Markdown парсер?
image

Получается класс Md это какая-то абстрактная машина конвертации форматов? Правильное ли тогда название Md?

cs/Markdown/Md.cs Outdated Show resolved Hide resolved
cs/Markdown/Tokens/ComplexSringToken.cs Outdated Show resolved Hide resolved
cs/Markdown/Writers/IWriter.cs Outdated Show resolved Hide resolved
Comment on lines 5 to 8
internal interface IConverter
{
IList<Token> Convert(IList<Token> tokensToConvert);
}

Choose a reason for hiding this comment

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

Добавлю тут про второй пункт из описания.

Хочется услышать мнение о целесообразности приведения конкретных реализаций парсера, конвертера и врайтера в статические, а не динамические классы. Тут больше вопрос в том, как их тогда обязать реализовывать интерфейсы?

Если реализация у метода/класса одна, и в будущем не предвидится появление новых реализаций - то это можно реализовать статическим классом без дополнительного интерфейса.
Если же реализаций точно будет несколько, то в таком случае статика подойдёт тут в меньшей степени.
Нормально сделать интерфейс, который объявляет какие-либо методы и иметь динамические классы для него.

Что касается конкретно IConverter, IWriter и IParser, то наверное вопрос к тебе, что по твоему мнению никогда не потребует дополнительной реализации? А что может потребовать?

cs/Markdown/Parsers/MdParsers/ParserMD.cs Outdated Show resolved Hide resolved
cs/Markdown/Tokens/ComplexSringToken.cs Outdated Show resolved Hide resolved
@BlizPerfect BlizPerfect changed the title Проведено начальное проектирование. Попов Захар Nov 25, 2024
1. Выполнен рефакторинг тестов. В связи с тем, что одно и тоже визуальное представление переданного текста можно получить из разных комбинаций токенов, я решил оставить в ParserMdTests только тривиальные ситуации, а в MdTests перенести все тесты, какие были раньше, но проверять именно корректность получения визуального представления. В связи с этим из ParserMd был убран избыточный функционал.
namespace Markdown.Tests.ParsersTests
{
[TestFixture]
public class ParserMdTests
Copy link

Choose a reason for hiding this comment

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

Напишу сюда, так как теста на случай с пересечением тегов нету

В случае __пересечения _двойных__ и одинарных_ подчерков ни один из них не считается выделением.

Сейчас выделением считается первое попадание. Что нарушает спецификацию.
image

Choose a reason for hiding this comment

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

Вроде проблема осталась
image

Тест __Hello_ __world_ не совсем релевантен, потому что по спецификации __hello __ не может быть превращён в <strong>hello </strong> из-за пробела.

За подчерками, начинающими выделение, должен следовать непробельный символ. Иначе эти_ подчерки_ не считаются выделением и остаются просто символами подчерка.

1. Тест Md_ShouldWorkInLinearTime теперь работает исходя из такой логики:
Если мы увеличим длину входной строки в 2 раза, то и время выполнения работы, по сравнению с прошлой длиной входной строки, увеличится в 2 раза (+ погрешность).
2. Рефакторинг тестов.
Действительно, поскольку у нас конкретный класс Md, то он должен принимать только соответсвующий себе типа парсера. К renderer это не относится.
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