Кроме пакта Молотова Ребентропа у Германии уже был ряд пактов. — Англо-германская декларация (1938); — Франко-германская декларация (1938); — Договор о ненападении между Германией и Польшей (1934); — Договор о ненападении между Германией и Эстонией (1939); — Договор о ненападении между Германией и Латвией (1939).
СССР пыталось договориться с Финляндией в отношении распределения границ. Делалалось это не с целью ненависти к Финам или возрождения российской империи, а с целью защиты от Гитлера. Было ли это справедливо по отношению к финскому народу - не очень. Было ли у финского правительства возможность этого избежать - да. СССР изначально предлагал выгодные уступки финами. Но финское правительство испугалось потери власти и пошло на войну.
СССР вначале войны сделало много ошибок, но быстро исправилось и разгромило финскую армию. Потом финны выступали на стороне Гитлера. На стороне фашизма. Могло ли СССР полностью поставить свое правительство после победы в руско-финской войне и после победы в великой отечественной - да. Почему оно не стало этого делать? Потому что что цель была только в том чтобы защитить жителей Ленинграда от армии Вермахта.
Мы свою историю помним.
Какое отношения имеют разработчики из России к тем событиям или событиям на Украине - никакого.
Обвинять их в своих ревизионистских обидах - это нацизм. Мелкий и жалкий.
Процессы бесспорно важны, но более важным является управление человеческим фактором. Ивар Якобсон в последней своей книге раскрывает в целом, что послужило основным проигрышем RUP по сравнению с гибкими методологиями.
> As strange as it may sound, the methods we employed in the early days did not pay much attention to the human factors. Everyone understood of course that software was developed by people, but very few books or papers were written about how to get people motivated and empowered in developing great software. The most successful method books were quite silent on the topic. It was basically assumed that in one way or the other this was the task of management.
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
Services:: и Interactors:: — это лишняя абстракция, опытным разработчикам она не нужна. Я использую ее, здесь, в статьях и мы используем в части проектов, для наглядности, чтобы показать к какому шаблону проектирования относится CheckEngine. Об этом я упомянул в последней части статьи.
. pedals.gas.press — это один из возможных вариантов если он удовлетворяет вашу команду, используйте его. Мне, лично, не нравится в этом подходе, что метод относится к субъекту, а не к объекту. Дрова — нарубитесь, хлеб нарежься, масло намажься.
Если у нас подходящий домен, можно сделать:
racer.press car.pedals.gas
Но это только в подходящем домене. Машина для гонщика и машина для инженера обслуживания, это две разные модели одной и той же реальной сущности.
Тут важно достичь выразительности, чтобы читая код был понятен процесс, который он выражает. Степень выразительности лучше определить внутри команды. Но я бы тоже вынес многострочку в отдельный метод -) Возможно в Сервисный слой.
Не соглашусь. Во-первых такая схема работает ровно до того момента, пока не появится мальчик — или дублирования кода, или миксины или множественное наследование.
Во-вторых девочка возможно имеет методы use, take, age, но точно она не должна знать как включать телевизор, это явный RDM.
Чтобы расстроить Мартина, надо понять что они имеют ввиду в этой статье как раз делается вывод, что к Entity нет доступа напрямую.
Сервисы добавляются потому, что есть разные сценарии использования _Сущности.
Сценарий "Включение телевизора": У нас есть девочка, которая включает телевизор. Она может включить его кнопкой, а может с пульта. Причем кнопкой она может и не дотянуться, т.к. у нее маленький рост.
Проверка роста, точно, не должна находится в модели телевизора — выносим в сервис. Поиск пульта в другой сервис. Метод включения для Сущности Телевизор который включает светодиод и матрицу — ок.
Методы изменения в сущности — ок. Сценарии использования — не ок. И сущность не может изменить себя сама.
Хороший пример, методы которые описываются в приведенном классе, изменяют его. Это такие своеобразные, сеттеры + обработка. Но они никогда не вызываются напрямую, вся работа с ними ведется через сервисы: assignToRoute, specifyNewRoute, deriveDeliveryProgress.
Данный пример и позволил выявить точку нашего взаимонепонимания. Я ни в коем случае не приываю вынести подобные методы изменения атрибутов из класса Сущности. Я призываю к тому что бизнес операции не могу быть описаны в модели и их необходимо выносить на слой бизнес-логики. Пользователь не должен менять сущность напрямую, он должен вызвать процесс, который приведет к изменению Сущности. Есть еще некоторые особенности от типа системы которую мы пишем Запрос-Ответ или Событийная. Тут мы говорим про web и rest, т.е. Запрос-Ответ.
Руби не позволяет обращаться к атрибуту напрямую все это делается только через методы, инкапсуляция никогда не нарушается.
class Foo
arr_accessor :bar
end
# это по факту:
class AnotherFoo
def bar=(val)
@bar = val
end
def bar
@bar
end
end
На хабре есть кнопка Ответить, под каждым комментарием, чтобы не создавать новую ветвь дискуссии.
Не хочется скатываться до холивара. Ко всему надо подходить рационально и не уходить в крайности. Давайте разберем пример.
Задача
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 секунд) не следует хранить в Сущности, так как это внешний процесс.
Если предложенный мной пример не раскрывает сути вопроса, предложите пожалуйста свой, попробуем его разобрать.
Касательно денег, зачастую, в базе данных, для того чтобы сохранить деньги, используются поля с плавающей запятой. Это не совсем удобно, в дальнейшем возникают ряд ошибок связанных с округлением. По факту, не может в учете указваться половина копейки. Удобнее все хранить в фракциях — копейках, центах и.т.д., использовать целочисленный тип. Валюта тоже важна, кроме собственно валюты, она показывает разрядность тех или иных фракций. Если у рубля и доллара это одна сотая, то у иены ее нет, у сатоши одна девятимиллионная. Валюты могу так же разделять тестовые и реальные платежи. Если в проекте все эти проблемы не стоят, проще использовать decimal и не усложнять свою жизнь. В руби gem 'money' достаточно популярен, 2000 звезд на GitHub хороший показатель.
Относительно онлайн казино, я не смотрел с этой точки зрения. Для меня как разработчика, это просто сложная система, где можно применить DDD. Возможно, у кого-то, легкий сарказм, в сторону надоедливой рекламы, вызовет улыбку. Объемную сухую статью без вставок читать тяжело. Никого не призываю разрабатывать онлайн казино и нарушать законы.
Ну тут все зависит от того какое у вас flow, какие инструменты и самое главное как вы договорились.
Я смотрю на это так: PR это запрос на code review. Он должен быть удобным для code review. Мы используем гитхаб. Для большой фичи создается ветка 'feature/epic'. В эту ветку идут небольшие PR, из малых веток 'feature/epic_new_entity' поскольку они небольшие их удобно смотреть и проверять. В малые ветки коммиты используются как сохранения. После того как ветка 'feature/epic' стала осмысленной, мы ее обновляем по мастеру, сквошим, ее протестировали автотестами и руками. После этого делаем PR в мастер.
Поскольку в мастер отправляются засквошенные ветки коммиты в мастере выражают что-то целостное фичу, баг по истории комитов можно проследить историю проекта.
Малые ветки позволяют прогерам сохранятся также часто, как они жмут quick save в своей любимой игре.
Нацистом ты становишься когда обвиняешь человека в чем либо исключительно по нацианальному признаку. Что Линус и сделал.
Кроме пакта Молотова Ребентропа у Германии уже был ряд пактов.
— Англо-германская декларация (1938);
— Франко-германская декларация (1938);
— Договор о ненападении между Германией и Польшей (1934);
— Договор о ненападении между Германией и Эстонией (1939);
— Договор о ненападении между Германией и Латвией (1939).
Именно.
СССР пыталось договориться с Финляндией в отношении распределения границ. Делалалось это не с целью ненависти к Финам или возрождения российской империи, а с целью защиты от Гитлера. Было ли это справедливо по отношению к финскому народу - не очень. Было ли у финского правительства возможность этого избежать - да. СССР изначально предлагал выгодные уступки финами. Но финское правительство испугалось потери власти и пошло на войну.
СССР вначале войны сделало много ошибок, но быстро исправилось и разгромило финскую армию. Потом финны выступали на стороне Гитлера. На стороне фашизма. Могло ли СССР полностью поставить свое правительство после победы в руско-финской войне и после победы в великой отечественной - да. Почему оно не стало этого делать? Потому что что цель была только в том чтобы защитить жителей Ленинграда от армии Вермахта.
Мы свою историю помним.
Какое отношения имеют разработчики из России к тем событиям или событиям на Украине - никакого.
Обвинять их в своих ревизионистских обидах - это нацизм. Мелкий и жалкий.
Процессы бесспорно важны, но более важным является управление человеческим фактором. Ивар Якобсон в последней своей книге раскрывает в целом, что послужило основным проигрышем RUP по сравнению с гибкими методологиями.
> As strange as it may sound, the methods we employed in the early days did not pay much attention to the human factors. Everyone understood of course that software was developed by people, but very few books or papers were written about how to get people motivated and empowered in developing great software. The most successful method books were quite silent on the topic. It was basically assumed that in one way or the other this was the task of management.
Разделить на два класса?
Cool Story, bro )
Да, извиняюсь, перепутал значения терминов субъект и объект.
Да, Interface segregation principle, была статья как-раз неплохая на эту тему
https://medium.com/roonyx/solid-ruby-ad046727ec26
И там как раз пример приводится:
Но если бы у нас была сущность Human, то я бы не стал вносить метод
drive
в нее:Services::
иInteractors::
— это лишняя абстракция, опытным разработчикам она не нужна. Я использую ее, здесь, в статьях и мы используем в части проектов, для наглядности, чтобы показать к какому шаблону проектирования относитсяCheckEngine
. Об этом я упомянул в последней части статьи..
pedals.gas.press
— это один из возможных вариантов если он удовлетворяет вашу команду, используйте его. Мне, лично, не нравится в этом подходе, что метод относится к субъекту, а не к объекту. Дрова — нарубитесь, хлеб нарежься, масло намажься.Если у нас подходящий домен, можно сделать:
Но это только в подходящем домене. Машина для гонщика и машина для инженера обслуживания, это две разные модели одной и той же реальной сущности.
Тут важно достичь выразительности, чтобы читая код был понятен процесс, который он выражает. Степень выразительности лучше определить внутри команды. Но я бы тоже вынес многострочку в отдельный метод -) Возможно в Сервисный слой.
Во-вторых девочка возможно имеет методы use, take, age, но точно она не должна знать как включать телевизор, это явный RDM.
Чтобы расстроить Мартина, надо понять что они имеют ввиду в этой статье как раз делается вывод, что к Entity нет доступа напрямую.
Сервисы добавляются потому, что есть разные сценарии использования _Сущности.
Сценарий "Включение телевизора": У нас есть девочка, которая включает телевизор. Она может включить его кнопкой, а может с пульта. Причем кнопкой она может и не дотянуться, т.к. у нее маленький рост.
Проверка роста, точно, не должна находится в модели телевизора — выносим в сервис. Поиск пульта в другой сервис. Метод включения для Сущности Телевизор который включает светодиод и матрицу — ок.
Методы изменения в сущности — ок. Сценарии использования — не ок. И сущность не может изменить себя сама.
Хороший пример, методы которые описываются в приведенном классе, изменяют его. Это такие своеобразные, сеттеры + обработка. Но они никогда не вызываются напрямую, вся работа с ними ведется через сервисы: assignToRoute, specifyNewRoute, deriveDeliveryProgress.
Данный пример и позволил выявить точку нашего взаимонепонимания. Я ни в коем случае не приываю вынести подобные методы изменения атрибутов из класса Сущности. Я призываю к тому что бизнес операции не могу быть описаны в модели и их необходимо выносить на слой бизнес-логики. Пользователь не должен менять сущность напрямую, он должен вызвать процесс, который приведет к изменению Сущности. Есть еще некоторые особенности от типа системы которую мы пишем Запрос-Ответ или Событийная. Тут мы говорим про web и rest, т.е. Запрос-Ответ.
Руби не позволяет обращаться к атрибуту напрямую все это делается только через методы, инкапсуляция никогда не нарушается.
На хабре есть кнопка Ответить, под каждым комментарием, чтобы не создавать новую ветвь дискуссии.
Не хочется скатываться до холивара. Ко всему надо подходить рационально и не уходить в крайности. Давайте разберем пример.
1) Вы пишете демон для холодильника. У вас есть некий цикл который проверят открыт ли холодильник или нет, если открыт то шлем смс.
Отправка смс, достаточно сложная логика, лучше вынести в отдельный сервис.
2) Вы пишете демона, и холодильник у вас достаточно умный там встроен моторчик, для которого реализован какой-то драйвер, вынесенный в стороннюю библиотеку.
Создавать отдельный сервис который инициирует работу драйвера излишне. Но с другой стороны, правила проверки (раз в 30 секунд, если уже открыта более 15 секунд) не следует хранить в Сущности, так как это внешний процесс.
Если предложенный мной пример не раскрывает сути вопроса, предложите пожалуйста свой, попробуем его разобрать.
Касательно денег, зачастую, в базе данных, для того чтобы сохранить деньги, используются поля с плавающей запятой. Это не совсем удобно, в дальнейшем возникают ряд ошибок связанных с округлением. По факту, не может в учете указваться половина копейки. Удобнее все хранить в фракциях — копейках, центах и.т.д., использовать целочисленный тип. Валюта тоже важна, кроме собственно валюты, она показывает разрядность тех или иных фракций. Если у рубля и доллара это одна сотая, то у иены ее нет, у сатоши одна девятимиллионная. Валюты могу так же разделять тестовые и реальные платежи. Если в проекте все эти проблемы не стоят, проще использовать decimal и не усложнять свою жизнь. В руби gem 'money' достаточно популярен, 2000 звезд на GitHub хороший показатель.
Относительно онлайн казино, я не смотрел с этой точки зрения. Для меня как разработчика, это просто сложная система, где можно применить DDD. Возможно, у кого-то, легкий сарказм, в сторону надоедливой рекламы, вызовет улыбку. Объемную сухую статью без вставок читать тяжело. Никого не призываю разрабатывать онлайн казино и нарушать законы.
Ну тут все зависит от того какое у вас flow, какие инструменты и самое главное как вы договорились.
Я смотрю на это так: PR это запрос на code review. Он должен быть удобным для code review. Мы используем гитхаб. Для большой фичи создается ветка 'feature/epic'. В эту ветку идут небольшие PR, из малых веток 'feature/epic_new_entity' поскольку они небольшие их удобно смотреть и проверять. В малые ветки коммиты используются как сохранения. После того как ветка 'feature/epic' стала осмысленной, мы ее обновляем по мастеру, сквошим, ее протестировали автотестами и руками. После этого делаем PR в мастер.
Поскольку в мастер отправляются засквошенные ветки коммиты в мастере выражают что-то целостное фичу, баг по истории комитов можно проследить историю проекта.
Малые ветки позволяют прогерам сохранятся также часто, как они жмут quick save в своей любимой игре.
PR в эпики делет code review удобным.