Здравствуйте, IB, Вы писали:
IB>Инкапсуляция — это средство уменьшения связности кода, путем сокрытия конкретной реализации за публичным контрактом.
Да, согласен. Теперь вижу, где я прокосячил: забыл, что инкапсулировать можно не только состояние.
IB>Так какую реализацию ты скрываешь, навешивая на данные, к которым один фиг есть публичный доступ, левую логику?
А кто тебе сказал, что у меня ко всем данным, на которые я навешиваю логику, есть публичный доступ? Разумеется, я прячу многие вспомогательные вещи, переопределяю геттеры/сеттеры и т.п.
D>>Если же речь идёт об инкапсуляции бизнес-логики (как я догадываюсь), то это далеко не "одна", а совсем даже "другая". IB>Чем она другая? Не мог бы ты привести определение обеих?
Само по себе коллекционирование взаимосвязанных методов бизнес логики в одном месте — это, строго говоря, не инкапсуляция вообще. Если же брать конкретную точку входа (метод интерфейса BLL), тогда да, посыпаю голову пеплом. Упираться рогом в классификацию "инкапсуляция состояния" vs "инкапсуляция поведения" смысла не вижу, сути оно не меняет, так что ты прав.
Здравствуйте, IB, Вы писали:
D>> Помнится, IT честно говорил, что в его архитектуре ООП с инкапсуляцией идут лесом. IB>IT умница, и к ООП относится с нежностью и трепетом, так что пальцами ООП не трожь.. =) IB>IT, если что, сам за себя скажет.
У меня вообще складывается ощущение, что большинство здешних "гуру от архитектуры" нарочно запутывают простые вещи, чтобы утвердиться в собственной крутизне. Все с готовностью соглашаются с тем, что универсальных решений нет, и при этом редко кто опускается до разбора конкретики. Игорь хоть и выступил адвокатом абстрактных разговоров, но в итоге соблаговолил разобрать конкретный пример, и разбор его оказался гораздо короче, чем тысячи строк кода, которыми он меня стращал. Многие ли тут способны повторить этот подвиг? Джаверы неизменно доброжелательны и конструктивны, практически все (платформа видимо влияет). От остальных чёрта с два добьёшься, одни общие размытые слова. Я прошу прощения за агрессивную манеру общения в этой (и не только) ветке, но конкретику приходится из вас из всех выдразнивать, побуждая ваш эгоизм грубыми намёками на вашу глупость.
Здравствуйте, dimgel, Вы писали:
D>У меня вообще складывается ощущение, что большинство здешних "гуру от архитектуры" нарочно запутывают простые вещи, чтобы утвердиться в собственной крутизне.
У меня обратное ощущение. Гуру архитектуры как раз предлагают самые простые решения.
D>Все с готовностью соглашаются с тем, что универсальных решений нет, и при этом редко кто опускается до разбора конкретики.
Универсальных — дейсвтительно нет. Всегда найдется очень редкий частный случай, который ломает универсальное решение.
Зато есть квазиуниверсальное решение, которое в очень многих случаях подходит, но такое решение натыкается на волну протестов "это не ООП", "а где же инкапсуляция", "доменная модель всегда долна быть валидна" и прочее.
Причем вера некоторых людей в ООП гораздо сильнее любой религиозной веры. Это несмотря на то что программист просто обязан быть прагматичным.
Здравствуйте, gandjustas, Вы писали:
G>Зато есть квазиуниверсальное решение, которое в очень многих случаях подходит, но такое решение натыкается на волну протестов "это не ООП", "а где же инкапсуляция", "доменная модель всегда долна быть валидна" и прочее. G>Причем вера некоторых людей в ООП гораздо сильнее любой религиозной веры. Это несмотря на то что программист просто обязан быть прагматичным.
Я с удовольствием проглотил и переварил Игорево решение, в котором ООП и не пахнет. Он выдал совершенно конкретные и исчерпывающие (на данном уровне детализации) рекомендации. От тебя же я слышал одно только многоумное бла-бла-бла из названий принципов и общих рассуждений, без намёка на конкретику применительно к моим примерам, которыми я тут всю ветку зафлудил. Впрочем, в соседней ветке ты удосужился привести даже пример кода для генерации отчётов; так что чеши туда, где от тебя польза.
А про мою приверженность или отверженность от ООП не тебе судить — когда я 2-3 года назад с пеной у рта защищал тут построение небольших сайтов в архитектуре Transaction Scripts (не называя этот паттерн по имени), без намёка на слои и классы (кроме служебных типа провайдера базы), мне тоже всей толпой на голову срали, с умным видом говорили про DAO и контроллеры. Дураков посамовыражаться за чужой счёт всегда хватает.
D>От тебя же я слышал одно только многоумное бла-бла-бла из названий принципов и общих рассуждений
Вру, это было от Нахлобуча. От тебя было высокомерное ха-ха-ха и какой-то бред про shared_ptr из C++, не имеющий к рассматриваемой теме никакого отношения. Короче, неадекват.
dimgel wrote:
> А про мою приверженность или отверженность от ООП не тебе судить - > когда я 2-3 года назад с пеной у рта защищал тут построение небольших > сайтов в архитектуре Transaction Scripts (не называя этот паттерн по > имени), без намёка на слои и классы (кроме служебных типа провайдера > базы), мне тоже всей толпой на голову срали, с умным видом говорили > про DAO и контроллеры. Дураков посамовыражаться за чужой счёт всегда > хватает.
Паттерн Transaction Script никоим образом не приводит к отказу от слоев
AKA Controllers/Services/DAO и, упаси меня инкапсуляция, от классов. Это
всего лишь страшилка в которую тыкают пальцем при обсуждении Anemic
Domain Model.
Здравствуйте, dimgel, Вы писали:
D>Здравствуйте, gandjustas, Вы писали:
G>>Зато есть квазиуниверсальное решение, которое в очень многих случаях подходит, но такое решение натыкается на волну протестов "это не ООП", "а где же инкапсуляция", "доменная модель всегда долна быть валидна" и прочее. G>>Причем вера некоторых людей в ООП гораздо сильнее любой религиозной веры. Это несмотря на то что программист просто обязан быть прагматичным.
D>Я с удовольствием проглотил и переварил Игорево решение, в котором ООП и не пахнет. Он выдал совершенно конкретные и исчерпывающие (на данном уровне детализации) рекомендации. От тебя же я слышал одно только многоумное бла-бла-бла из названий принципов и общих рассуждений, без намёка на конкретику применительно к моим примерам, которыми я тут всю ветку зафлудил.
С чего ты взял что тебе кто-то что-то должен объяснять, а уж тем более примеры кода показывть. Можно радоваться если тебе хотя бы показали направление.
D>Впрочем, в соседней ветке ты удосужился привести даже пример кода для генерации отчётов; так что чеши туда, где от тебя польза.
Чья бы корова мычала
Здравствуйте, mazurkin, Вы писали:
M>Паттерн Transaction Script никоим образом не приводит к отказу от слоев AKA Controllers/Services/DAO и, упаси меня инкапсуляция, от классов.
Я кажется написал про небольшие сайты. Усложнение нужно там, где оно оправдано, т.е. где в итоге даёт упрощение. Наворачивать слои просто "чтобы были"? Следующий.
Здравствуйте, dimgel, Вы писали:
D>Выносить всю логику из пунктов (2) и (3) в контроллеры — значит дублировать её во множестве контроллеров для всех entities, являющихся TreeNode.
Это неправда. D>Или делать отдельные методы в helper-классах, что всё равно дико: всё-таки гораздо понятнее и более ожидаемо написать node1.addChild(node2), чем TreeController.addChild(node1, node2).
Никаких отдельных методов тут нет. D>Все вот эти SomethingController, плодящиеся как грибы после дождя, если отказаться от активных entities, дико раздражают.
Никто не плодится.
Почему тебя не устраивает единственный TreeController.addChild(node1, node2), который подходит ко всем классам с примесью TreeNode?
В случае, когда отношения parent-child это деталь реализации, то совершенно нормально из одного контроллера вызвать другой:
EmployeeController.enrollEmployee(Employee e, Department d, WorkContract wc)
{
TreeController.addChild(d, e); // мы не предполагаем в бизнес-коде прямых вызовов типа d.addChild(e)
}
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Почему тебя не устраивает единственный TreeController.addChild(node1, node2), который подходит ко всем классам с примесью TreeNode? S>В случае, когда отношения parent-child это деталь реализации, то совершенно нормально из одного контроллера вызвать другой: S>
S>EmployeeController.enrollEmployee(Employee e, Department d, WorkContract wc)
S>{
S> TreeController.addChild(d, e); // мы не предполагаем в бизнес-коде прямых вызовов типа d.addChild(e)
S>}
S>
Да просто, как мне видится, это лишняя косвенность. Ничего летального, конечно, но зачем она, если можно всё делать "на месте"? (Я уже посыпАл голову пеплом, отвечая GlebZ-у, так что не надо мне повторять, что в сложных случаях я со своим подходом сяду в лужу — в моих конкретных случаях всё было ок.)
Вот я, кстати, надеялся, что ты, как веб-разработчик, наверняка с богатым опытом возни с DOM из javascript, меня поймёшь. Представь, что все эти операции addChild, createElement, createTextNode, сами по себе многословные до тошноты, в дополнение ко всему ещё пришлось бы вызывать через какой-то DOMController? Пальцы отсохнут.
S> мы не предполагаем в бизнес-коде прямых вызовов типа d.addChild(e)
Здравствуйте, dimgel, Вы писали:
D>Здравствуйте, Sinclair, Вы писали:
S>>Почему тебя не устраивает единственный TreeController.addChild(node1, node2), который подходит ко всем классам с примесью TreeNode? S>>В случае, когда отношения parent-child это деталь реализации, то совершенно нормально из одного контроллера вызвать другой: S>>
S>>EmployeeController.enrollEmployee(Employee e, Department d, WorkContract wc)
S>>{
S>> TreeController.addChild(d, e); // мы не предполагаем в бизнес-коде прямых вызовов типа d.addChild(e)
S>>}
S>>
D>Да просто, как мне видится, это лишняя косвенность.
Не очень понятно, что означает "лишняя косвенность".
Косвенности никакой нет — всё идет напрямую.
D>Ничего летального, конечно, но зачем она, если можно всё делать "на месте"?
А что означает "на месте"? Как будет выглядеть метод "принять на работу" и где он будет расположен? В Employee? В Department? В WorkContract?
Очевидно, метод будет расположен где-то в EmploymentSubsystem, чтобы легче было повторно использовать Employee, Department, и WorkContract.
В таком случае остается понять, как будет устроен этот метод в обоих подходах.
D>(Я уже посыпАл голову пеплом, отвечая GlebZ-у, так что не надо мне повторять, что в сложных случаях я со своим подходом сяду в лужу — в моих конкретных случаях всё было ок.)
Совершенно непонятно, откуда взялся Ok, при том что тебе даже в простых случаях нужно порождать отдельные DTO на каждый чих и оборудовать каждого toDTO/fromDTO.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Косвенности никакой нет — всё идет напрямую.
Ниже уже ответил.
S>А что означает "на месте"? Как будет выглядеть метод "принять на работу" и где он будет расположен? В Employee? В Department? В WorkContract?
Там же, где и ты его написал. Но букаф в нём будет меньше.
S>Совершенно непонятно, откуда взялся Ok, при том что тебе даже в простых случаях нужно порождать отдельные DTO на каждый чих и оборудовать каждого toDTO/fromDTO.
Про то, что я был неправ с toDTO/fromDTO, мне уже объяснили. Но это ортогонально примеру с addChild() даже если от DTO не отказываться, а сделать внешний сериализатор, как объяснил Blazkowicz.
Здравствуйте, dimgel, Вы писали:
D>Здравствуйте, Sinclair, Вы писали:
D>Вот я, кстати, надеялся, что ты, как веб-разработчик, наверняка с богатым опытом возни с DOM из javascript, меня поймёшь. Представь, что все эти операции addChild, createElement, createTextNode, сами по себе многословные до тошноты, в дополнение ко всему ещё пришлось бы вызывать через какой-то DOMController? Пальцы отсохнут.
А тебя не удивляет, что createXxx есть только у document? Который выступает, собственно, как DOM-factory?
Далее, здесь "DOM-контроллер" не нужен, потому как объекты DOM существуют ровно в одном месте, их жизненный цикл ограничен, а поведение определено. S>> мы не предполагаем в бизнес-коде прямых вызовов типа d.addChild(e) D>А почему, собственно?
Потому, что непонятно зачем. Какова семантика этого вызова? Если это перевод из отдела в отдел, то нужно убедиться, что у какого-то d2 был вызван removeChild(e). Кто за это будет отвечать? d.addChild()? или e.setParent()? А если setParent вызывается в процессе десериализации, то как нам его трактовать?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Потому, что непонятно зачем. Какова семантика этого вызова?
Скажем так: я эмпирически поделил операции на высокоуровневые (собственно BL) и низкоуровневые (вся эта кухня с поддержкой иерархических структур и прочих мелочей типа ordered, filtered и т.п.). Высокоуровневые размещаются в контроллерах, как ты и нарисовал. Благодаря тому, что низкоуровневые инкапсулированы внутрь entities, они имеют немногословный интерфейс, в итоге BLL выглядит существенно компактнее и приятнее.
S>Если это перевод из отдела в отдел, то нужно убедиться, что у какого-то d2 был вызван removeChild(e). Кто за это будет отвечать? d.addChild()? или e.setParent()?
Да без разницы. Они оба относятся к слою кода, реализующему эту низкоуровневую абстракцию TreeNode.
S>А если setParent вызывается в процессе десериализации, то как нам его трактовать?
А вот это хороший аргумент. Сижу пытаюсь вспомнить, почему я с этой ситуацией не сталкивался.
Здравствуйте, dimgel, Вы писали:
D>Там же, где и ты его написал. Но букаф в нём будет меньше.
За счёт чего именно в нём будет меньше букаф? Ты взял пример с одной строчкой. Действительно, если у объекта нет других обязанностей, кроме как хранить ссылку на родителя, то внешний контроллер не нужен. Но в жизни-то у него есть и другая работа.
D>Про то, что я был неправ с toDTO/fromDTO, мне уже объяснили. Но это ортогонально примеру с addChild() даже если от DTO не отказываться, а сделать внешний сериализатор, как объяснил Blazkowicz.
Нет, не ортогонально. Просто это еще одна обязанность — типа, "увеличить счётчик ссылок родителя", которую ты возлагаешь на этот объект. Это не работа employee. Работа employee — хранить информацию об employee.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>За счёт чего именно в нём будет меньше букаф? Ты взял пример с одной строчкой. Действительно, если у объекта нет других обязанностей, кроме как хранить ссылку на родителя, то внешний контроллер не нужен. Но в жизни-то у него есть и другая работа.
Я разве спорю? Но как говорится, тут строчка, там строчка... Дело в том, что с точки логики BL, разницы никакой. Я всё пытаюсь как-то донести эту простую мысль. Логика BL не изменится. А букв в низкоуровневой кухне станет меньше, вызываться она станет естественней. Уберётся TreeController, и суть не изменится вообще, только выглядеть всё станет проще.
Есть подозрение, что у тебя просто не было этой кухни в таком диком количестве, как у меня.
Я сейчас прикидываю иерархию на mixin-ах в lift, чтобы написать, к примеру, class Category extends DataMapper[Category] with TreeNode with Sorted with Filtered, и чтобы все эти поведения подцепились сами, с хорошим поведением по умолчанию даже при полном отстутствии соответствующих вызовов из BLL. Пока что не уверен, честно говоря, насколько хорошо это получится, но если получится, тогда я буду тихо молча праздновать победу (только не на форуме, а с бутылкой водки(зачёркнуто) лимонада).
S>Нет, не ортогонально. Просто это еще одна обязанность — типа, "увеличить счётчик ссылок родителя", которую ты возлагаешь на этот объект. Это не работа employee.
Верно. Это работа его базового класса TreeNode. Не вижу противоречий. Нормальная декомпозиция. (Язвительно: да, я в курсе, ООП и наследование используют только дураки. Но здесь оно ложится вполне по уму.)
Здравствуйте, dimgel, Вы писали:
D>Я с удовольствием проглотил и переварил Игорево решение, в котором ООП и не пахнет.
Почему ты так решил?
D> без намёка на конкретику применительно к моим примерам, которыми я тут всю ветку зафлудил.
Только половина твоих примеров никакого отношения к исходному вопросу не имеют.
Здравствуйте, dimgel, Вы писали:
D>А кто тебе сказал, что у меня ко всем данным, на которые я навешиваю логику, есть публичный доступ?
Потому что, если речь идет о персистентном хранении этих данных, то без публичного доступа к ним ты не обойдешься. Так как в противном случае, в твой бизнес объект придется "заинкапсулировать" взаимодействие со всеми возможными хранилищами, и вообще всеми подсистемами с которыми объект имеет дело.
D>Само по себе коллекционирование взаимосвязанных методов бизнес логики в одном месте — это, строго говоря, не инкапсуляция вообще.
Строго говоря, только ты и говорил, что это инкапсуляция, а вообще это называется когезия (cohesion)
Здравствуйте, IB, Вы писали:
D>>Я с удовольствием проглотил и переварил Игорево решение, в котором ООП и не пахнет. IB>Почему ты так решил?
Прочитай ссылку на его пост, которую я тебе дал.
IB>Только половина твоих примеров никакого отношения к исходному вопросу не имеют.
Прочитай заголовок темы. Приведи примеры, имеющие отношение к исходному вопросу. Скажи что-нибудь умное по второй половине моих примеров. Короче, продемонстрируй интеллект.