• Поваренная книга разработчика: DDD-рецепты (5-я часть, Процессы)
    0

    Да, извиняюсь, перепутал значения терминов субъект и объект.


    Да, Interface segregation principle, была статья как-раз неплохая на эту тему
    https://medium.com/roonyx/solid-ruby-ad046727ec26


    И там как раз пример приводится:


    class Driver
      def drive
        @car.open
        @car.start_engine
      end
    end

    Но если бы у нас была сущность Human, то я бы не стал вносить метод drive в нее:


    
    module Entities
      class Human
        # ...
      end
    end
    
    module Services
      #не все мы водим машины, и лучше это вынести в отдельный сервис
      module HandlingVehicle
         def self.drive(racer, car)
           # ...
         end
      end
    end
  • Поваренная книга разработчика: DDD-рецепты (5-я часть, Процессы)
    0

    Services:: и Interactors:: — это лишняя абстракция, опытным разработчикам она не нужна. Я использую ее, здесь, в статьях и мы используем в части проектов, для наглядности, чтобы показать к какому шаблону проектирования относится CheckEngine. Об этом я упомянул в последней части статьи.
    .
    pedals.gas.press — это один из возможных вариантов если он удовлетворяет вашу команду, используйте его. Мне, лично, не нравится в этом подходе, что метод относится к субъекту, а не к объекту. Дрова — нарубитесь, хлеб нарежься, масло намажься.


    Если у нас подходящий домен, можно сделать:


      racer.press car.pedals.gas

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

  • Поваренная книга разработчика: DDD-рецепты (5-я часть, Процессы)
    0

    Тут важно достичь выразительности, чтобы читая код был понятен процесс, который он выражает. Степень выразительности лучше определить внутри команды. Но я бы тоже вынес многострочку в отдельный метод -) Возможно в Сервисный слой.

  • Поваренная книга разработчика: DDD-рецепты (4-я часть, Структуры)
    0

  • Поваренная книга разработчика: DDD-рецепты (4-я часть, Структуры)
    0
    Не соглашусь. Во-первых такая схема работает ровно до того момента, пока не появится мальчик — или дублирования кода, или миксины или множественное наследование.
    Во-вторых девочка возможно имеет методы use, take, age, но точно она не должна знать как включать телевизор, это явный RDM.
  • Поваренная книга разработчика: DDD-рецепты (4-я часть, Структуры)
    0
    И соглашусь, что последний абзац стоит переписать.
  • Поваренная книга разработчика: DDD-рецепты (4-я часть, Структуры)
    0

    Чтобы расстроить Мартина, надо понять что они имеют ввиду в этой статье как раз делается вывод, что к Entity нет доступа напрямую.


    Сервисы добавляются потому, что есть разные сценарии использования _Сущности.


    Сценарий "Включение телевизора": У нас есть девочка, которая включает телевизор. Она может включить его кнопкой, а может с пульта. Причем кнопкой она может и не дотянуться, т.к. у нее маленький рост.


    Проверка роста, точно, не должна находится в модели телевизора — выносим в сервис. Поиск пульта в другой сервис. Метод включения для Сущности Телевизор который включает светодиод и матрицу — ок.


    Методы изменения в сущности — ок. Сценарии использования — не ок. И сущность не может изменить себя сама.

  • Поваренная книга разработчика: DDD-рецепты (4-я часть, Структуры)
    0

    Хороший пример, методы которые описываются в приведенном классе, изменяют его. Это такие своеобразные, сеттеры + обработка. Но они никогда не вызываются напрямую, вся работа с ними ведется через сервисы: assignToRoute, specifyNewRoute, deriveDeliveryProgress.


    Данный пример и позволил выявить точку нашего взаимонепонимания. Я ни в коем случае не приываю вынести подобные методы изменения атрибутов из класса Сущности. Я призываю к тому что бизнес операции не могу быть описаны в модели и их необходимо выносить на слой бизнес-логики. Пользователь не должен менять сущность напрямую, он должен вызвать процесс, который приведет к изменению Сущности. Есть еще некоторые особенности от типа системы которую мы пишем Запрос-Ответ или Событийная. Тут мы говорим про web и rest, т.е. Запрос-Ответ.


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


    class Foo
      arr_accessor :bar
    end
    
    # это по факту:
    
    class AnotherFoo
      def bar=(val)
        @bar = val
      end
    
      def bar
        @bar
      end
    end

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

  • Поваренная книга разработчика: DDD-рецепты (4-я часть, Структуры)
    0
    Приведите конкретный пример.
  • Поваренная книга разработчика: DDD-рецепты (4-я часть, Структуры)
    0

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


    Задача


    1) Вы пишете демон для холодильника. У вас есть некий цикл который проверят открыт ли холодильник или нет, если открыт то шлем смс.


    loop do
      Service::SendSms(master.phone, 'Fridge is open') if fridge.open? && fridge.open_time > 15.sec
      sleep 30
    end

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


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


    class FridgeEntity
      def close!
        driver.close_door
      end
    
      #...
    end
    
    loop do
      fridge.close! if fridge.open? && fridge.open_time > 15.sec
      sleep 30
    end

    Создавать отдельный сервис который инициирует работу драйвера излишне. Но с другой стороны, правила проверки (раз в 30 секунд, если уже открыта более 15 секунд) не следует хранить в Сущности, так как это внешний процесс.


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

  • Поваренная книга разработчика: DDD-рецепты (4-я часть, Структуры)
    0

    Касательно денег, зачастую, в базе данных, для того чтобы сохранить деньги, используются поля с плавающей запятой. Это не совсем удобно, в дальнейшем возникают ряд ошибок связанных с округлением. По факту, не может в учете указваться половина копейки. Удобнее все хранить в фракциях — копейках, центах и.т.д., использовать целочисленный тип. Валюта тоже важна, кроме собственно валюты, она показывает разрядность тех или иных фракций. Если у рубля и доллара это одна сотая, то у иены ее нет, у сатоши одна девятимиллионная. Валюты могу так же разделять тестовые и реальные платежи. Если в проекте все эти проблемы не стоят, проще использовать decimal и не усложнять свою жизнь. В руби gem 'money' достаточно популярен, 2000 звезд на GitHub хороший показатель.


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

  • Я порчу разрабам жизни своими код ревью и больше так не хочу
    0

    Ну тут все зависит от того какое у вас flow, какие инструменты и самое главное как вы договорились.


    Я смотрю на это так: PR это запрос на code review. Он должен быть удобным для code review. Мы используем гитхаб. Для большой фичи создается ветка 'feature/epic'. В эту ветку идут небольшие PR, из малых веток 'feature/epic_new_entity' поскольку они небольшие их удобно смотреть и проверять. В малые ветки коммиты используются как сохранения. После того как ветка 'feature/epic' стала осмысленной, мы ее обновляем по мастеру, сквошим, ее протестировали автотестами и руками. После этого делаем PR в мастер.


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


    Малые ветки позволяют прогерам сохранятся также часто, как они жмут quick save в своей любимой игре.


    PR в эпики делет code review удобным.

  • Я порчу разрабам жизни своими код ревью и больше так не хочу
    0
    У вас Entity это только структура или еще и БЛ?
  • Я порчу разрабам жизни своими код ревью и больше так не хочу
    +1
    Не соглашусь. Если рассматривать наш диалог, именно вопрос привел к тому, что мы выяснили:
    — Мы кодим на php
    — Для php кавычки не влияют на производительность.
    Теперь нам только осталось договориться о том, какие кавычки использовать. И вероятнее мы будем исходить из того, какие кавычки уже использовались в остальном коде.
    В данном случае использовать\не использовать одинарыне\двойные кавычки становится осознаным. Это гораздо лучше чем «У нас принято везде писать одинарные кавычки».
  • Я порчу разрабам жизни своими код ревью и больше так не хочу
    +1

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


    1. Человек не знает, что одинарные работают быстрее, поэтому они предпочтительнее, если нет обработки переменных. Он ищет информацию об этом, или спрашивает у проверящего. И вносит изменения в свой код.
    2. Человек знает об этом, но данный код представляет из себя кладбище домашних животных. Время на рефакторинг нет. И кавчки не решат ни чего. Ну и смысл тратить время на исправление?
    3. У вас идеальный код. Везде одинарные кавычки, все по гайдлайну. Вы объяснили человеку почему это так, и как это важно для вас лично. Человек занимается умышленным вредительством, осознано. Кастрируйте этого тупорылого #@удака, пока он весь мир не заразил.
  • Я порчу разрабам жизни своими код ревью и больше так не хочу
    0
    Ну собственно, да. С кавычками я утрирую, но вот бывает, что проверяющий парится на вкусовщине — тут важно чтобы решение оставалось за исполнителем таска. Могут вдвоем запарится и ничего плохого в этом тоже нет.
  • Я порчу разрабам жизни своими код ревью и больше так не хочу
    0
    Да, конечно =)
  • Я порчу разрабам жизни своими код ревью и больше так не хочу
    +1
    Я конечно не исключаю, что и такое может быть и по другому никак. Но обычно стоит разделить такую Entity на структуру, пару тройку другую сервисных объектов, интеракторов, фабрик.
  • Я порчу разрабам жизни своими код ревью и больше так не хочу
    +3
    Ну а почему бы и не разбить?
    feature/epic_new_entity => feature/epic
  • Я порчу разрабам жизни своими код ревью и больше так не хочу
    +7
    1. Нельзя пропускать коммиты если они содержут явные ошибки (Errors). Напр.: Забыл обернуть в транзакцию БД.
    2. Остальные замечания сделать рекомендательными (Warnings). Удобно делать их вопросами. Напр.:
      Почему были использованны двойные кавчки вместо одинарных?. По факту это вкусовщина. Если инициатор коммита задумался после вашей рекомендации, то он скорее поправит код. Возможно это было осознаным решением. А возможно вам нужно забить на это замечание.
    3. Ну и пулреквесты должны быть вменяемого объема, чтобы проверяющий их смог переварить. С 1000 строк я вероятнее отклонил PR.
  • Проблемные личности среди разработчиков
    0
    Спасибо, что поправили. Тут это сделано скорее умышленно. Проверять грамотность написанного текста также можно периодически. Если есть возможность потратить на это время. Мне это дается сложнее, но это однако не значит, что я не могу написать текст без ошибок. А если верить авторам вышеизложенной статьи то я «безграмотный».
  • Проблемные личности среди разработчиков
    +3

    Делить по паттернам поведения тоже не верный подход.


    Все люди делятся на две категории: те, у кого револьвер заряжен, и те, кто копают. Копай.

    Я ем оливье когда я хочу его есть. Т.е. преодически, меня нельзя отнести ни к какой категории. Я использую новые технологии, переодически. Довожу до идеала код переодичекски. Проявляю оптимизм или пессимизм тоже перодически и.т.д. стараюсь всегда смотреть по ситуации, относить меня к какой-то категории нельзя. А к чему призывает эта статья — увидели паттерн поведения человека. Поставьте на нем клеймо. И по этому клейму применяйте решение.


    Все люди делятся на две категории: те, кто мыслит стериотипами, и те, кто умеют думать. Копай.
  • Проблемные личности среди разработчиков
    +18
    Все евреи жадные, а американцы тупые, гуманитарии не могут мыслить логично, женщины не умеют пользоваться молотком. Куча каких-то штампов. Для комичной статьи написанно слишком серьезно. Для серьезной статьи написанно слишком глупо.
  • Поваренная книга разработчика: Domain Driven Design рецепты ( 2-я часть, структура и взаимодействие )
    0
  • Поваренная книга разработчика: Domain Driven Design рецепты ( 2-я часть, структура и взаимодействие )
    0

    Впечатление сложилось правильное :)


    1. Из-за того, что бизнес-логика уходит в ServiceObjects, тесты для ServiceObjects выглядят как описание бизнес логики. И это очень и очень удобно. Писать на русском удобно, особенно если термины существуют только на русском языке. Бизнес вряд ли будет смотреть тесты, если у вас не IT компания. Но если вы смогли их заставить это сделать, вы очень круты :)
    2. Так и есть. И зачастую все называют лошадью. И кобыл, и жеребцов и коров =)
    3. На 180 градусов развернутся не получится, это решение не для MVP. Но всяческие корректировки проходят в разы быстрее. По-большому счету если изменился процесс — переписываем только ServiceObject, изменился порядок процессов — меняем Interactor. И из-за слабой связанности классов, не боимся, что у нас что-то рассыпаться в другом месте.
    4. Согласен. Если смотреть на всякие старые методологии, вроде RUP, то в них, деятельность IT воспринималась как автоматизация документооборота. А результатом любой хоз. деятельности бизнеса являлся документ. А оборот это как раз связки, унификация и выстраивание потоков.
  • Cucumber в облаке: использование BDD-сценариев для нагрузочного тестирования продукта
    0

    Да, это можно так решить. Но тест на степ Дано в системе 0 бронирований от пользователя это по факту, DELETE FROM booking WHERE user_id = ?. Или 'TRUNCATE users', что на самом деле не совсем корректный тест, так как мы искуственно подчищаем базу.
    Мы проверяем увеличене на единицу.
    Хотелось бы иметь что-то вроде


    describe `Создается 1 бронирование в системе:`;
      before_count = SELECT COUNT(*) FROM bookings where user_id = ?;
      run nested steps;
      after_count = SELECT COUNT(*) FROM bookings where user_id = ?;
      after_count - before == 1;
  • Cucumber в облаке: использование BDD-сценариев для нагрузочного тестирования продукта
    0
    Основная проблем gherkin это отсутвтие блоков, что делает его крайне не удобным языком для тестов. Взять те же отели, нам нужно посмотреть что у нас создалась бронь.

    Дано незарегистрированный пользователь
    Когда пользователь заходит на сайт
    И делает бронирование
    То создается 1 бронирование в системе
    

    Чтобы проверить, на то что боннирование создалось. Нам надо убедится что создалась 1 запись в бд. Но посравнению с чем?

    или нам очищать все бронирования перед началом теста:

    Дано незарегистрированный пользователь
    И в отеле нет ни одного бронирования
    Когда пользователь заходит на сайт
    И делает бронирование
    То создается 1 бронирование в системе
    


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

    Было удобнее если бы в функционале gherkin появилось что-то вроде:

    Дано незарегистрированный пользователь
    Создается 1 бронирование в системе:
        Когда пользователь заходит на сайт
        И делает бронирование
    


    Без подобных вещей все тесты написанные для gherkin-спецификаций, подверженны огромной энтропии. Приэтом сами спецификации выглядят прекрасно.

    image
  • Поваренная книга Ruby-разработчика: Domain Driven Design рецепты ( 1-я часть, область применения )
    0
    Спасибо за замечание, исправил.
  • Rails 4. Гибкая разработка веб-приложений
    0
    Купил бы epub, актуалено для книгочиталок с небольшим разрешением экрана.
  • Новый HP Chromebook 11 доступен в Google Play
    +6
    «Впечатляющий угол обзора 176». Маркетологи как всегда на высоте.
  • Поливаем цветы – просто и быстро
    +2
    Точно цветы?
  • Прокладываем путь через желудок
    +2
    Теперь ждем API по точкам продаж разливного пива.
  • Эдвард Сноуден получил временное убежище в России
    +66
    Как раз, день ВДВ посмотрит.
  • Большой список 256-ти языков программирования
    +1
    а как же 1с ?)
  • Apple Macintosh Performa 475
    –2
    Made in India
  • 25 января 1915: первый трансконтинентальный звонок
    +1
    Что, простите?
  • Chromebook за 249 у.е. уже доступен в Google Play Store
    0
    А консоль с bash можно запустить?
  • Видеообзор ультрабука Lenovo ThinkPad X1 Carbon
    –2
    А физически выковыривать можно? А то «Нажми Ctrl +R… Ай да, не у меня Fn и Ctrl в биосе поменяны… поэтому Fn+r»
  • Видеообзор ультрабука Lenovo ThinkPad X1 Carbon
    0
    Ну там увы стандандартные 1366, и pgUp pgDown справа от Enter, хотя в данном случае это все равно удобнее чем у леново, но стандартный блок из 6ти кнопок уже и делл по-моему убрали.
  • Видеообзор ультрабука Lenovo ThinkPad X1 Carbon
    +4
    Ну как можно было сделать такую ужасную клавиатуру? Мало того что острова, но зачем убрали с места функциональные клавиши? Опять таки PgUp PgDown рядом со стрелками для программиста — крайне не удобно.
    Батарею расширенную не поставить, каркас выбросили…

    Хотя да 14, легкий, но не в ущерб же комфорту.