Ты начал свою карьеру как разработчик программного обеспечения. Выучил основы и продолжаешь учиться новому по мере продвижения. Как ответственный разработчик, который хочет стать мастером своего дела, ты читаешь рекомендованные многими книги, такие как “Чистый код”, “Рефакторинг” и т.д.

Ты также стараешься улучшить свои навыки, изучая TDD (Test Driven Development), DDD (Domain Driven Design), архитектуру Clean/Hexagonal/Onion/Ports&Adapter. Ты определенно чувствуешь, что становишься лучше в разработке программного обеспечения. 

Хотя ты ясно видишь преимущества некоторых из этих техник, ты все еще не очень уверен в некоторых из них. Ты думаешь, что, возможно, в этом виновато твое недопонимание, что ты еще недостаточно созрел, чтобы осознать эти великие идеи. Но ты не сдаешься. Каждые несколько недель/месяцев ты снова пробуешь применить эти идеи, чтобы увидеть, понимаешь ли ты их теперь. Но ты всё еще не уверен в полезности некоторых из этих практик или техник.

И ты снова думаешь, что всему виной твое отсутствие навыков, из-за которого ты не можешь увидеть преимуществ этих практик. Проходят годы... ты все ещё пытаешься понять и снова терпишь неудачу... проходят десятилетия, ты пытаешься понять, но снова терпишь неудачу. 

Ты спрашиваешь у экспертов, и они отвечают: "Ваш вопрос неверный" или "Ваш пет-проект недостаточно сложный, чтобы увидеть преимущества". Ты удивляешься, ведь хоть это и пет-проект, случаи использования такие же, как и в реальных проектах, над которыми ты уже работал! 

И в один прекрасный день ты осознаешь, что, возможно, некоторые из этих практик на самом деле не были такими уж грандиозными либо были неприменимы к твоей работе. Затем ты начинаешь внимательнее присматриваться к ним и понимаешь, что многие энтузиасты предусмотрительно “забыли” сказать о том, когда эти практики следует применять, а когда нет. 

К тому же некоторые идеалисты доводят эти идеи до абсурда, заявляя, что есть только один “верный способ” сделать что-либо и что, если ты не придерживаешься упомянутых ранее практик, ты не являешься профессиональным разработчиком.

Но ты слишком боишься сказать это вслух, ведь люди могут счесть тебя глупцом. Однако, всему есть предел, и однажды ты говоришь, “мне не нравятся некоторые из этих практик”. Я не собираюсь винить себя в том, что не вижу преимуществ в использовании некоторых из них, если я этих преимуществ так и не увидел даже после многолетних попыток. 

Знакомо? Это мое текущее состояние. 

И знаешь что? Не только ты так себя чувствуешь. Многие другие испытывают те же чувства, но слишком боятся сказать об этом, потому что люди слишком склонны осуждать тебя, если ты не принадлежишь к их “элите”. Но опять-таки, ты достиг той точки, когда тебе глубоко все равно, будут ли люди осуждать тебя на основании их “глубоких убеждений” и их узкого мышления по принципу “есть только один правильный путь”. 


Давайте посмотрим на то, о чем именно я говорю. 

Поговорим о TDD 

Я люблю автоматизированное тестирование. Я предпочитаю запустить автоматический тест, чтобы убедиться в том, что определенная функциональность работает (или не работает) вместо того, чтобы запускать приложение, искать нужный мне путь через многочисленные экраны и отправлять форму, предварительно заполнив вручную кучу полей, каждый раз.

Но утверждение, что “ты должен всегда сначала писать тест, прежде чем писать код для продакшена, потому что в противном случае ты не соблюдаешь TDD” — это то, с чем я не согласен.

Когда я реализую некую функциональность, я читаю задачу, анализирую ее, глубоко продумываю, как я собираюсь её реализовывать и затем начинаю писать код. Я создаю класс (сразу в продакшен коде), пишу метод с аргументами, основанный на моем текущем понимании, затем реализую очень базовую функциональность. Это обычно занимает от 30 секунд до пары минут. Затем я использую комбинацию Cmd + Shift+ T в IDE, чтобы создать тест. Наконец, я пишу базовый тест. Затем я усложняю реализацию большим количеством кода и параллельно расширяю тест или просто пишу больше тестов. 

Через час или около того у меня появляется реализованная функциональность с набором тестов. 

Моя цель состоит в реализации функциональности, хорошо протестированной набором автоматических тестов. 

Сначала создать экземпляр класса, которого не существует, потом вызывать метод, которого не существует, и затем использовать шорткаты для создания этих классов или методов — если это ваш путь, прекрасно. 

Но сначала создать класс или метод и потом использовать шорткаты для создания теста или тестов — это то, что подходит мне больше. Стандартный аргумент против такого подхода состоит в том, что если сначала написать продакшен код, то тесты будут зависеть от деталей реализации. 

Если я пишу юнит тест, требующий настройки mock, тогда каким бы подходом я не пользовался, мои тесты будут зависеть от деталей реализации. Если я пишу интеграционный тест, тогда, независимо от подхода, я могу написать этот тест никак не зависящим от деталей реализации. 

Я не пишу весь продакшен код за несколько часов, чтобы протестировать его вручную и зачем написать тесты только ради покрытия. Продакшен код и тесты эволюционируют параллельно друг другу, шаг за шагом, инкрементально. Этот подход отлично работает в моём случае. 

Могу ли я сказать, что следую TDD? Многие TDD-энтузиасты категорически не согласятся с этим. 

В соц.сетях можно часто увидеть посты в стиле “Очень жаль, что даже в 20XX году все еще приходится напоминать, что, следуя TDD надо сначала писать тесты!”. Когда так называемые “лидеры мнений” говорят такое, создается впечатление, что “все согласны, что это единственный правильный способ следовать принципам TDD”. Подобное допущение не позволяет людям задавать вопросы об использовании немного изменённых версий TDD. 

Тем не менее, как я уже сказал ранее, мой стиль следования TDD мне нравится больше. И мне не надо никого ни в чем убеждать. Так что все в порядке. 

А как насчет архитектуры Clean/Hexagonal/Onion/Ports&Adapters? 

Я много раз пытался полюбить эти архитектурные стили. Но я так и не увидел от них никакой пользы. После преобразования модуля, следующего моему любимому подходу к разработке к этим стилям, код становился неоправданно сложным. 

На протяжении всей своей карьеры я в основном работал с приложениями, ориентированными на данные. Я не большой поклонник архитектур Clean/Hexagonal/Onion/Ports&Adapters, особенно для приложений, ориентированных на данные. Основное рекламируемое преимущество этих архитектурных стилей состоит в их способности изолировать инфраструктуру от центральной доменной логики. 

В большинстве бизнес-приложений будет низкая или средняя сложность бизнес-логики, которая в бóльшей степени будет зависеть от инфраструктуры баз данных, брокеров сообщений, интеграций с внешними API и т.д. Для таких приложений возможность тестировать центральную логику домена в отрыве от инфраструктуры - невеликое преимущество. Напротив, мне больше нравится убирать ненужные абстракции (интерфейсы) и получать возможность тестировать логику с инфраструктурными компонентами, используя такие инструменты, как Testcontainers

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

  • Получить данные от пользователя через вызов REST API с формы или из сообщения, полученного от брокера сообщений.

  • Провалидировать что-либо на наличие значений в обязательных полях, проверить значение на соответствие указанному минимум/максимум значению или соответствию регулярному выражению.

  • Провалидировать данные относительно имеющихся данных, например, “такой адрес электронной почты уже существует” .

  • Сохранить или обновить данные.

  • Извлечь данные из многочисленных источников (таблиц).

  • Вернуть только необходимые данные под специфичный кейс.

  • При необходимости отправить события в брокер сообщений, чтобы их могли использовать другие системы. 

Большинство бизнес-приложений, ориентированных на работу с данными, включают в себя эти задачи. 

Многие люди рекомендуют DDD (Domain Driven Development) как золотой стандарт для создания приложений. Мне нравятся некоторые аспекты DDD, такие как: 

  • Использование универсального языка.

  • Определение ограниченного контекста.

  • Моделирование значимых объектов, сущностей, репозиториев, сервисов и т.д.

Но ключевым аспектом DDD является Агрегат. 

Я понимаю разницу между сущностью и агрегатом. Обычно единица работы применяется на уровне агрегата. 

Некоторые сторонники DDD предлагают следовать строгим правилам в отношении того, как (не)обращаться к агрегату/сущности напрямую. При этом в их понимании всё должно проходить только через агрегат. Это отличный подход, пока ты не столкнёшься со случаем, требующим доступа к списку сущностей. В зависимости от сценария использования правила DDD становятся более гибкими, и сущность может повыситься до уровня Агрегата. Поэтому я предпочитаю моделировать домен напрямую на основе сценариев использования, а не на основе произвольных правил, предложенных пуристами. 

После изучения тонкостей всех этих концепций я остановился на следующем подходе для приложений, ориентированных на данные:

  • Создавать отдельные классы для работы с разными сценариями использования.

  • Создавать отдельные модели запроса и ответа для каждого случая использования. Это может привести к тому, что некоторые классы будут иметь одинаковые поля, но это нормально. 

  • Следовать CQRS (необязательно разделять базу данных для чтения и базу данных для записи). Использование одной модели для чтения и записи только всё усложняет. 

  • Писать юнит тесты для тестирования любой бизнес логики, включающей вычисления и т.д., используя mocks, если это необходимо.

  • Писать интеграционные тесты для проверки API с использованием реальных компонентов инфраструктуры. 

 Да, всё настолько просто.

Это мой опыт и моё мнение после многих лет работы над приложениями, ориентированными на данные. 

Если вы хотите сказать мне, что доменная модель Anemic с Transaction Script Pattern плоха, скажите это и предпринимателям, которые управляют многомиллионным бизнесом, используя только Google Sheets. 

Если архитектура Clean/Hexagonal/Onion/Ports&Adapters вам подходит – прекрасно. 

Но, как я уже сказал, я не вижу большой выгоды от использования этих стилей для приложений, ориентированных на данные. И я рад, что наконец избавился от мысли: “Возможно, я просто не смог оценить великолепие архитектуры Clean/Hexagonal/Onion/Ports&Adapters” — которая крутилась у меня в голове много лет.

Действительно ли мы (разработчики) любим все усложнять? 

Если ты дочитал до этого места, возможно ты думаешь, что я обвиняю этих размечтавшихся лидеров мнений в сложности процесса разработки ПО. На самом деле, не совсем. Я думаю, что мы (разработчики ПО) тоже любим всё усложнять. 

Позволь мне рассказать тебе простую историю.

Я начал программировать используя Windows OS, и я не использовал Linux как минимум 5 лет после начала моей карьеры в качестве разработчика ПО. Затем мой друг познакомил меня с Linux, и я установил Ubuntu в качестве второй ОС. 

Форматировать жесткий диск, устанавливать операционную систему и устанавливать кучу ПО через терминал — это, конечно, весело. Помню, как я пытался заставить работать Wi-Fi или Bluetooth, погрузившись в поиск ответов на Linux-форумах, запускал случайные Linux-команды и, в конце концов, удачно справился с проблемой. Однако на следующий день я обновил версию OS, и Wi-Fi или Bluetooth (или что-то ещё) снова сломалось. И мне снова пришлось повторить ту же процедуру с запуском многочисленных команд, предложенных на форуме. Как по мне, это какое-то гиковское занятие. 

Ещё, однажды я купил ноутбук новой модели, для которой драйвера Wi-Fi еще не были выпущены, но существовал GitHub репозиторий с исходным кодом для драйверов. Я клонировал этот репозиторий, собрал драйвера с использованием Make файла, установил их, и все заработало. В тот день я чувствовал себя супер-гением. 

Думаешь я стал использовать Linux в качестве операционки на каждый день, пройдя этот путь? Нет. Как только я обновился и исправил проблему на Linux, я переключился на Windows и продолжил работать, как и прежде. Так зачем же я потратил время и усилия на исправление проблемы с драйвером Linux? 

Я хотел почувствовать себя компьютерным гением, справляясь с трудными задачами. Я люблю решать сложные проблемы.

Раньше я читал код open-source проектов на GitHub, чтобы узнать, как другие разработчики решают задачи. Если код был простым, я пропускал его и искал следующий. Я хотел видеть код, использующий рефлексию и делающий какие-то безумно сложные вещи. Я хотел читать код, использующий шаблон strategy, а не обычный Enum или if-else, даже если необходимость использовать strategy у меня никогда и не возникнет. Ох, эта тяга к сложному в начале карьеры... 

Некоторым разработчикам нравится “ненавидеть PHP”. Сможем ли мы найти более расширяемую CMS, чем WordPress, написанный на PHP? Почему не существует большого числа более эффективных фреймворков типа Laravel на твоем любимом языке, который не является PHP? Ни у кого нет времени найти ответа на этот вопрос. Мы все слишком заняты бесконечным копированием свойств объектов из слоя в слой!!!

Я уверен на 100%, что это касается не только меня. Многие люди могут узнать здесь себя. Если сложных задач нет, что нам в таком случае делать? Мы делаем простые вещи сложными и затем решаем сложные проблемы. Не так ли? Мы, разработчики, любим сложность, по крайней мере в начале своей карьеры. 

Теперь, когда мне уже за 40, я очень ценю простоту. Я хочу, чтобы код моего приложения был настолько скучным, насколько это возможно, чтобы я мог закончить свою работу и заняться домашними делами. Мне нравятся сложные задачи, но я не хочу сталкиваться с ними каждый день. 

Я пересматриваю RailsConf 2014 - Keynote: Writing Software by David Heinemeier Hansson снова и снова, чтобы напомнить себе о красоте простых вещей и о необходимости избегать карго-культа.

Вывод

Нам повезло, что сегодня в нашем распоряжении есть огромное количество материалов, позволяющих научиться создавать сложные системы. Но мы не должны следовать за ними вслепую только потому, что какой-то лидер мнений сказал, что что-то является великой идеей. И самое главное, мы не должны бояться ставить под сомнение установленные нормы, если они покажутся нам неправильными. 

Не каждый из нас занимается написанием следующего Facebook, Google или Netflix. Необязательно применять все эти креативные и сложные решения к твоему бизнес-приложению, у которого будет не больше 5000 пользователей в любой отдельно взятый момент времени, только по той причине, что ты когда-то готовился к собеседованию по системному дизайну. 

И если кто-то пытается сказать тебе “просто на всякий случай, если ты вдруг захочешь использовать другую базу данных...” – БЕГИ. Настолько быстро, насколько сможешь.

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм - Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.

Ждем всех, присоединяйтесь

Комментарии (44)


  1. dae-fromru
    27.06.2024 10:10
    +14

    Создать сложное ПО, делающее сложные вещи - просто. А вот создать простое ПО, делающие сложные вещи - сложно.


    1. honest_niceman
      27.06.2024 10:10
      +21

      "Это письмо получилось таким длинным потому, что у меня не было времени написать его короче" (с). Паскаль


    1. Drucocu
      27.06.2024 10:10
      +3

      Поддерживаю. Не уверен, что часто встречаю разработчиков, которые намеренно пытаются где-то использовать "рефлексию и ... какие-то безумно сложные вещи". Проблема скорее в том, что для того, чтобы получилось просто, надо приложить больше усилий.
      Ну и пример с Wordpress как-то мимо кассы. Например, за интернет-магазины на Wordpress надо отлучать от профессии. Есть подозрение, что автор - индус.


      1. dae-fromru
        27.06.2024 10:10
        +3

        Западные бигтехи сегодня - яркий пример переусложнения ради переусложнения. Говорят раньше было лучше, начало ломаться в районе 2014-16 гг.


  1. Anarchist
    27.06.2024 10:10
    +3

    Дешёвые программисты - причина сложности и дороговизны ПО.


    1. aimfirst
      27.06.2024 10:10
      +2

      Я таки думаю, что не дешевые программисты, а некомпетентные менеджеры...


      1. randomsimplenumber
        27.06.2024 10:10
        +2

        И карго культы со всех сторон.


        1. Kanut
          27.06.2024 10:10

          "И велосипедисты."(с) народ


  1. headliner1985
    27.06.2024 10:10
    +6

    Странно, что вы не затронули тему микросервисов, которые не нужны в 95% случаев.


  1. lanseg
    27.06.2024 10:10
    +4

    Это ещё ничего, вот зоопарк методологий управления и планирования - вот где зоопарк, треш, угар и содомия


  1. rukhi7
    27.06.2024 10:10
    +3

    ... ты читаешь рекомендованные многими книги, такие как “Чистый код”“Рефакторинг” и т.д.

    Хотя ты ясно видишь преимущества некоторых из этих техник, ты все еще не очень уверен в некоторых из них.

    ...

    Однако, всему есть предел, и однажды ты говоришь, “мне не нравятся некоторые из этих практик”.

    если провести аналогию с физикой:

    ... ты читаешь рекомендованные многими книги, такие как что-то про теорию относительности, дуализм, энтропию,... и т.д.

    Хотя ты ясно видишь преимущества некоторых из этих техник (теорий, подходов,...), ты все еще не очень уверен в некоторых из них.

    ...

    Однако, всему есть предел, и однажды ты говоришь, “мне не нравятся некоторые из этих практик”.

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


  1. APXEOLOG
    27.06.2024 10:10
    +1

    Тем не менее, как я уже сказал ранее, мой стиль следования TDD мне нравится больше. И мне не надо никого ни в чем убеждать. Так что все в порядке. 

    Зачем вообще тогда пытаться подгонять свой стиль под TDD? Да, по ТDD нужно сначала писать тесты. Мне например это не нравится и поэтому я не использую TDD, не вижу тут совершенно никакой проблемы. Никто ж не запрещает писать тесты вне TDD.

    Я много раз пытался полюбить эти архитектурные стили. Но я так и не увидел от них никакой пользы.

    Потому что архитектурные стили обычно начинают показывать эффективность на реально больших проектах. Таких в целом не так уж и много. А с текущей тенденцией к разделению логики (микросервисы, лямбды, и т.д.) таких ситуаций еще меньше. Главное разделить логику, согласовать апишку, а дальше внутри проекта можно сделать максимально просто, так как там никакой сложности и нет.


  1. Batalmv
    27.06.2024 10:10
    +7

    Скажу коротко и просто:

    Ценность или ее отсутствие того или иного стиля легче всего понять, когда надо вносить изменения.

    Что в частности говорит о том, что если вносить изменения не требуется, то - можно меньше париться


  1. deliro
    27.06.2024 10:10

    Множество тестов можно вообще не писать, а их работу переложить на систему типов и тайпчекер (который справится намного лучше, чем прораммист). Рекомендую почитать "parse, don't validate"


  1. dididididi
    27.06.2024 10:10

    Извини пожалуйста, а какие плюсы ты увидел в TDD?

    Там же когда читать начинаешь, сначала думаешь: "гыгы, сказочник", потом " Мож и не надо легализовывать ничего", а потом "нужно сжечь кандома, пока это какой нить хирый мозгом менеджер не прочитал, и не пытался реализовать"!


  1. pirt
    27.06.2024 10:10

    Карго культ заканчивается там, где на кону появляются деньги.

    Немного странный посыл по поводу TDD, как будто сильно припекло от кого-то. Просто не называйте "сначала код, потом тесты" TDD, и ни у кого не должно возникнуть вопросов. И не общайтесь с неадекватами ;-)


    1. randomsimplenumber
      27.06.2024 10:10
      +1

      Карго культ заканчивается там, где на кону появляются деньги.

      Тогда начинается карго культ у менеджеров повыше. Будем делать как в Toshiba (Apple, Ford..).


  1. gun_dose
    27.06.2024 10:10
    +6

    Все эти паттерны и методологии очень полезны, когда сам не чувствуешь программирование и не понимаешь его до конца. Оттуда и лишние слои абстракции, лишние действия и т.д. - человек просто пытается из заученных вещей составить программу. Я не говорю, что всё это не нужно, ведь это необходимая база. Тут, как в кулинарии: если ты не умеешь готовить, просто бери рецепт и следуй ему, а хороший повар помнит тысячи рецептов, но в то же время может не следовать ни одному из них и приготовить шедевр.


    1. Yuriy_75
      27.06.2024 10:10
      +1

      Именно так - методологии, это всего лишь заучивание практик других людей. Необходимый этап обучения, не более.

      А уж методологии управления коллективом разработчиков, вроде скрама - вообще выглядят как инструкции по управления абсолютно расхлябанными и недисциплинированными людьми, которым если каждое утро не напомнить, какой задачей они заняты - так и не вспомнят.


  1. SimSonic
    27.06.2024 10:10
    +3

    Но утверждение, что “ты должен всегда сначала писать тест, прежде чем писать код для продакшена, потому что в противном случае ты не соблюдаешь TDD” — это то, с чем я не согласен.

    Но ведь оно верное, не написав тест вперёд, ты не следуешь TDD :)

    Имхо, TDD супер, когда ты правишь баг. Сперва воспроизвёл, убедился, что это оно, а потом поправил прод код, и тест прошёл.

    В остальных случаях скорее согласен с автором.


  1. SimSonic
    27.06.2024 10:10
    +1

    Но утверждение, что “ты должен всегда сначала писать тест, прежде чем писать код для продакшена, потому что в противном случае ты не соблюдаешь TDD” — это то, с чем я не согласен.

    Но ведь оно верное, не написав тест вперёд, ты не следуешь TDD :)

    Имхо, TDD супер, когда ты правишь баг. Сперва воспроизвёл, убедился, что это оно, а потом поправил прод код, и тест прошёл.

    В остальных случаях скорее согласен с автором.


  1. chaetal
    27.06.2024 10:10
    +1

    (В 100500-й раз!) TDD — не про тесты!

    Когда я реализую некую функциональность, я читаю задачу, анализирую ее, глубоко продумываю, как я собираюсь её реализовывать и затем начинаю писать код.

    Как происходит анализ? Как происходит продумывание? На сколько глубоко?

    …Там ещё много вопросов про то, как именно происходит "превращение" задачи в исходный код. И все эти вопросы увязаны в большой клубок, который и называют сложностью разработки ПО.

    TDD предлагает систему методов, позволяющих надёжно находить ответы на все озвученые выше и некоторые другие вопросы из этого клубка. TDD — это методология, то есть система методов. И написание "теста" до кода — один изз методов в этой системе. Но не единственный. И только в сочетании с другими методами получается система — нечто большее, чем "сумма" элементов. Можно использовать Test-First отдельно от другим методов. Но это не даст всех преимуществ TDD. Можно исключить Test-First из TDD. И это тоже разрушит систему и снизит её эффективность.

    Если кто-то знает другие, лучшие способы отвечать на эти вопросы — флаг ему в руки! TDD ему не нужно. Только вот почему-то очень редко, кто делится своими знаниями. Вы знаете метод "превращения" требований в реализующий их код? Поделитесь, пожалуйста!

    А то вот я практикую TDD уже скоро 20 лет. Не потому что фанат. А просто потому, что те способы, которые я знал и использовал до этого работали гораздо хуже. И до сих пор работают значительно хуже — я вынужден к ним время от времени возвращаться, так что знаю. И новых, которые бы давали лучший вариант, за это время не нашёл.

    У вас получается лучше без TDD? Тогда не тратьте время на критику, лучше расскажите подробнее, как надо!


    1. rukhi7
      27.06.2024 10:10

      TDD — это методология, то есть система методов.

      ...

      Можно исключить Test-First из TDD. И это тоже разрушит систему и снизит её эффективность.

      По моему главное в разработке софта это то что тот кто написал программу или алгоритм или какое-то взаимодействие, конфигурацию, ... что угодно что может быть написано и по этому написанному будет работать машина (вычислительная, а может стиральная в составе которой все равно есть вычислительная, например), так вот тот кто это написал должен знать как это проверить, в том смысле что он должен быть способен объяснить и даже доказать и показать что задача предметной области выполняется с помощью этой писанины(алгоритма и чего угодно) и значит алгоритм написан правильно - он работает.

      А то есть такие деятели которые говорят вот я тут ВСЕ(!) написал осталась сущая ерунда проверить то что я написал. Проверять это не моя работа. Пусть тестеры проверяют.

      Только написать проверочный код в общем случае намного сложнее чем просто рабочий код. Это из той же оперы что и проверочное и измерительное оборудование-железо к нему требования на порядок выше, поэтому оно на порядок сложнее и дороже.

      Потом если кто-то не знает как проверить то что он написал, возникает вопрос, а понимает ли он то что он написал, понимает ли задачу предметной области решение которой он собрался перепоручить машине.


      1. chaetal
        27.06.2024 10:10

        Я не очень понял, как эти рассуждения — во многом правильные — связаны с TDD?

        Да, хотелось бы, чтобы всё программное обеспечение было правильным. Да, тестирование — единственный на сегодняшний день практичный способ хоть как-то обеспечить это. Да, вероятно (и я с этим согласен) TDD делает код "более тестируемым".

        Но основная цель TDD состоит не в том, чтобы дать возможность тестировать код. Цель — дать возможность этот код написать.

        Но нельзя и проводить аналогию между TDD и описанными "деятелями", так как TDD — пусть и в качестве "побочного эффекта", но — поддерживает тестирование. Просто это не случайная побочка, а следствие какой-то закономерности, связи между спецификацией требований, их программной реализацией и проверкой соответствия полученной программной реализации исходным требованиям.

        (…Тут Остапа меня чуть было не понесло. Но я вовремя остановился и дальнейшие скачки своей мысли приберёг на будущее :) )


        1. rukhi7
          27.06.2024 10:10

          Но нельзя и проводить аналогию между TDD и описанными "деятелями", так как TDD — пусть и в качестве "побочного эффекта", но — поддерживает тестирование.

          где ж вы увидели такую аналогию-то? TDD по моему это как раз метод избавиться на корню с такими деятелями, мне так кажется! Чтобы даже не заикались что тестировать будет кто-то другой и когда-то потом. Ну и то что тестирование ставится во главу процесса и в первую очередь задает ту самую значимость тестирования про которую я написал ссылаясь на аналогию со значимостью измерительного оборудования.


          1. chaetal
            27.06.2024 10:10

            где ж вы увидели такую аналогию-то?

            Я её не увидел. Я как раз написал, что её нет. Возможно, перемудрил с формулировкой. Всего-то хотел сказать, что TDD — это про разработку, а не про тестирование. И тестировщиков напрямую не воспитывает. Просто позволяет писать код, про который можно как раз чаще говорить

            вот я тут ВСЕ(!) написал осталась сущая ерунда проверить то что я написал. Проверять это не моя работа. Пусть тестеры проверяют.

            Задача разработчика — написать код, который соответствует требованиям.

            Задача тестировщика — убедить (себя, а затем и других), что этот код действительно соответствует требованиям.

            Так что с утверждением

            TDD по моему это как раз метод избавиться на корню с такими деятелями, мне так кажется!

            я в корне не согласен. Хороший программист не участвует в тестировании. Но пишет код, который тестировать проще и приятнее. И когда (не если — так не бывает) найдутся баги, фиксит их быстро и эффективно. TDD способствует и в написании, и в сопровождении. Но каждый должен заниматься своим делом.

            Моя мысль стала понятнее или ещё больше запутал? :)

            TDD создана для разработчика. Разработчик должен разрабатывать, а не тестировать. Но если (как в случае с TDD) помочь в тестировании ничего не стоит, то почему бы и нет.


            1. rukhi7
              27.06.2024 10:10

              Моя мысль стала понятнее или ещё больше запутал? :)

              TDD создана для разработчика. Разработчик должен разрабатывать, а не тестировать.

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

              а разработка тестов это тестирование или разработка?


          1. chaetal
            27.06.2024 10:10

            Ну и то что тестирование ставится во главу процесса и в первую очередь задает ту самую значимость тестирования про которую я написал ссылаясь на аналогию со значимостью измерительного оборудования.

            И ещё раз — не устану повторять :) Если речь про TDD, то там тестирование не ставится во главу процесса. Написание теста — это ещё не тестирование. В TDD тест это (1) спецификация, (2) фронт работ (чтобы разраб не уходил в фантазии — по сути, YAGNI), (3) дизайн в коде, (4)… — там ещё "функции", но тестирования как такового среди них нет.


        1. rukhi7
          27.06.2024 10:10

          Но мне все таки кажется что тесты не обязательно надо писать до создания рабочего кода. Главное, по моему, нельзя считать код написанным (задачу решенной, функцию реализованной) пока нет теста который демонстрирует работу этого кода, при таком подходе это все равно можно определить как TDD, по моему. Если наличие теста определяет завершенность работы над функциональностью, процесс разработки управляется тестированием, неважно когда тест появился до или после, главное что без него работа не считается завершенной.


          1. Kanut
            27.06.2024 10:10
            +1

            Главное, по моему, нельзя считать код написанным (задачу решенной, функцию реализованной) пока нет теста который демонстрирует работу этого кода, при таком подходе это все равно можно определить как TDD, по моему

            А разве сам TDD не требует чтобы сначала были написаны тесты: https://martinfowler.com/bliki/TestDrivenDevelopment.html ?


            1. rukhi7
              27.06.2024 10:10

              я честно говоря теряюсь, пытаясь понять как ваш вопрос связан с тем что вы процитировали.

              Может вы просто ссылкой хотели поделиться, за ссылку спасибо.


              1. Kanut
                27.06.2024 10:10
                +1

                Очень просто. По ссылке описание TDD. В этом описании указано например вот такое:

                Although these three steps, often summarized as Red - Green - Refactor, are the heart of the process, there's also a vital initial step where we write out a list of test cases first.

                То есть важно не только чтобы тесты были, но и чтобы сначала были написаны тесты. Иначе уже получается не TDD.

                У вас есть какое-то другое определение TDD?


                1. rukhi7
                  27.06.2024 10:10

                  На сколько я это понимаю у меня оно не другое оно более обобщенное что ли. Потому что даже по вашей ссылке там в начале просто список тестов, я так понимаю примерный-предпологаемый, который в процессе работы уточняется и дополняется, то есть тесты не появляются раньше кода - это сложный процесс - некоторые тесты могут быть написаны раньше, а некоторые могут быть закончены или даже придуманы только по результатам работы с кодом. Там же написано: "Update list us we learn", на сколько я понимаю это значит что не все тесты мы обязаны написать сначала.

                  А вы как это понимаете?


                  1. Kanut
                    27.06.2024 10:10
                    +1

                    Потому что даже по вашей ссылке там в начале просто список тестов, я так понимаю примерный-предпологаемый, который в процессе работы уточняется и дополняется

                    Да, но по моей ссылке написано что сначала пишешь тест, потом пишешь код который его проходит.

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

                    некоторые тесты могут быть написаны раньше, а некоторые могут быть закончены или даже придуманы только по результатам работы с кодом

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


              1. chaetal
                27.06.2024 10:10

                Что ж непонятного?

                Есть принцип: "вся функциональность должна быть покрыта автоматическими тестами". Например, этот принцип присутствует в eXtreme Programming.

                Есть методология TDD, в которой написано чётко: "до написания кода, необходимо написать тест, который проверит, что данный код делает то, что требуется".

                Если вы покрываете всю функциональность автоматическими тестами, это прекрасно! Но если вы не пишите тесты до кода, то вы не придерживаетесь TDD. Просто потому, что нарушаете необходимое условие. (Оно, кстати, не является достаточным.)


                1. rukhi7
                  27.06.2024 10:10

                  Но если вы не пишите тесты до кода, то вы не придерживаетесь TDD.

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


                  1. Kanut
                    27.06.2024 10:10
                    +1

                    Вас же никто не заставляет придерживаться TDD. Не хотите так не надо. Никто же не утверждает что без этого нормальный код не напишешь.

                    Но если вы хотите работать по TDD, то правила надо выполнять.


                    1. rukhi7
                      27.06.2024 10:10

                      Но если вы хотите работать по TDD, то правила надо выполнять.

                      так почему же вы игнорируете правила, которые происходят из перехода: "Update list us we learn". Только вы можете правила определять?

                      Вы не замечаете, что вы утверждаете, что только ваше ограниченное в некотором смысле определение TDD истинно? То есть только вы знаете как оно правильно преобразуется в "правила"?


                      1. Kanut
                        27.06.2024 10:10
                        +1

                        так почему же вы игнорируете правила

                        Эээ, какие правила я игнорирую? И где?

                        Только вы можете правила определять?

                        В данном случае их не можем определять ни я, ни вы. Они уже давно определены.

                        Вы не замечаете, что вы утверждаете, что только ваше ограниченное в некотором смысле определение TDD истинно?

                        Это не моё определение. Это общепринятое определение. Более того я даже специально спросил можете ли вы привести ваше.

                        Вопрос скорее в том зачем вы хотите называть ваш подход именно TDD? Какой в этом смысл? Просто хотите использовать модное слово?


                      1. rukhi7
                        27.06.2024 10:10

                        Вопрос скорее в том зачем вы хотите называть ваш подход именно TDD? Какой в этом смысл? Просто хотите использовать модное слово?

                        Я хотел просто пояснить что не надо так буквально и формально воспринимать такую сложную концепцию, вы теряете ее смысл.

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

                        Спасибо за дисскусию.


                  1. chaetal
                    27.06.2024 10:10

                    В принципе, всё стало ясно. Точнее, подозрения подтвердились.

                    Просто возьмите нормальную книгу по теме. Советую "Test-Driven Development by Example" Кента Бека (есть плохой, но русский перевод). И разберитесь, какой смысл в этот термин вложил автор. Если есть желание именно разобраться и понять идею и принципы, этой книги хватит за глаза. Дальше можно моки, BDD и т.д.

                    Если же просто почему-то нравится название "TDD" и хочется наполнить его собственным содержанием… извините, удачи желать не буду. Не одобряю. Подобного "добра" уже хватает. На столько хватает, что TDD, похоже, ожидает участь ООП (и, наверняка, многих других) по схеме

                    Гениальная идея —> Хайп —> Непонимание —> Извращение —> Визги ОНО НЕ РАБОТАЕТ!!!


  1. v_malzam
    27.06.2024 10:10

    Создавать отдельные модели запроса и ответа для каждого случая использования.

    Под моделями запроса и ответа подразумеваются DTO?