ReactJS, TypeScript, Micro FrontendsReact fwdays | 27 березня. Долучайся!
×Закрыть

В защиту Фабрик

По следам поста на Хабре «Почему я ненавижу фреймворки»

habrahabr.ru/post/141477

Стоит отметить, что пост помещён на Хабре под тегом «юмор», однако кто их читает эти теги?

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

Зачем нужны фабрики фабрик фабрик? В принципе, это описано в любой книге и любом блоге с пометкой ООП.

ФФФ избавляют нас от необходимости писать нечто такое new Hammer(new Нandhold(new Weather(new .... и так далее в самых разных местах программы.

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

Допустим вам надо выполнить очень простое действие — забить гвоздь.

Как программист, вы создаёте Гвоздь, вы создаёте Молоток и в зависимости от предпочтений и начитанности делаете или Гвоздь.Забивайся(Молоток) или Молоток.Забить(Гвоздь)

В принципе, если программа на этом и ограничится, то статья автора могла бы иметь основания для сарказма. Но так не бывает никогда! Это самое незыблемое правило программирования, после правила «Все лгут».
Программа начнёт меняться как только ваш заказчик утвердит тремя печатями самые железобетонные требования в ТЗ. Так было, так есть, так будет. Меняться будет всё.

И ситуация несколько осложнится — потребуется забить двадцать пять гвоздей. Причём, десять до авторизации, а остальные сорок семь после. Вы не ослышались так и будет — всего двадцать пять, но десять до, а сорок семь после. Почему? Ну понимаете, гвоздей двадцать пять, а ещё шестьдесят восемь это дюбели. Погодите, погодите, двадцать пять плюс шестьдесят восемь... Ой, там ещё обойные гвоздики есть. Россыпью. Они лежат в разных частях программы, под самыми разными именами. Понятно?

И радуйтесь если молоток останется один.

Что произойдёт на самом деле, если ффф будут осмеяны и отложены.

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

Вы можете подумать что это страшилка или бред, но поверьте — если вы пишите что то сложнее Привет, Мир! То вы очень скоро столкнётесь с этой ситуацией.

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

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

ps. Фабрики фабрик фабрик — это иронический термин. Лично, я пока не ощутил необходимости даже в фабрике фабрик. Простой фабрики в виде готовой сторонней библиотеки типа ninject или castle должно хватить для всего.

ззы. Разумеется сами по себе фабрики никаких чудес делать не будут, но написать класс со множеством инъекций (по простому — интерфейсных ссылок), который будет удобно использовать в разных местах программы, который будет сам следить за временем жизни объектов от которых он завист, который сам будет уничтожаться и появлятся в нужный момент, всё это лучше оставить фабрике, а не пихать в конструктор десяток своих ссылок и уж тем более не писать new в конструкторе. Всё имхо с учётом моего небольшого опыта.

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

👍НравитсяПонравилось0
В избранноеВ избранном0
LinkedIn

Похожие топики

Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

А где же: забить(гвоздь, молоток)?

Тогда уже Программа(Забить, Молоток, Гвоздь, Доски, Чертежи, Зарплата...) и пусть сами там разбираются

Психбольницы — пациентам! (i)

Эта тема и комменты к ней вызывают у меня «внутренний конфликт». Поэтому вопрос:
О чем тут срач?

Или как обычно: Кто о чем хочет?

Не нравится — не читай! Всяко лучше непрофильного «срача» про рекрутеров и увольнения.

Для меня лично, излюбленное «ООП vs ФП»

Для меня лично, излюбленное «ООП vs ФП»
О нятно.

UPD
ООП vs ФП — как-то слабо раскрыто. По большей части личные оскорбления и флуд.

Всяко лучше непрофильного «срача» про рекрутеров и увольнения.
Таки да.

так на RSDN это многолетняя тема. И у сильной кучки типа в ЖЖ, типа thesz.livejournal.com

ФП vs ООП, по моим наблюдениям уже становится мегабаяном, типа Linux vs Windows.

Задумывалось как ООП вс Хардкод

Эта тема и комменты к ней вызывают у меня «внутренний конфликт». Поэтому вопрос:
О чем тут срач?

Или как обычно: Кто о чем хочет?

Этот же капитанский вопрос можно задать в почти любой теме форума. Чего ты именно сюда пришел?

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

Единственно, что на C++ писать фабрики довольно неудобно, так как нет ни виртуальных конструкторов ни рефлекшена ни статических конструкторов. Тоесть вместо написания универсального кода фабрики для определенного типа объектов — приходится писать вручную код инициализации для каждого класса.

В С++ нет сторонних готовых библиотек типа unity, ninject, castle?

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

unity, ninject, castle
Они не входят в стандарт языка C++

А так вообще в C++ даже делегаты и свойства есть, но большинство работодателей плохо относятся к «зафреймворкливанью» C+±кода.

PS
А где находятся эти библиотеки(unity, ninject, castle) для C++?

Не знаю, потому и спросил. Может их и нет

Ну да, там их нет. Хотя есть templates, что даёт то же самое удобство программирования, но полученный код сможет понять программист минимум с 5 годами программирования в C++.

Вот пример создания универсальной фабрики объектов без параметров в конструкторе.

insidecpp.ru/...tterns/factory

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

В вашем примере, в строке 22, сложно было написать файнд в мапе, и если нету такого, то кидать эксепшн, что бы прога не валилась при попытке создать незарегенный класс.

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

Майкрософт достаточно обоснован в том, что он не закроется ;)

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

А так вообще в C++ даже делегаты и свойства есть

— а это откуда? Насколько я помню, в терминах языка, никаких делегатов и свойств не присутствует... Возможно во многих фрэймворках это и реализовано, но в самом С++ (в отличае от того же C#) такого нету.

Может имелся ввиду C++/CLI :)

На счет C++/CLI, я мелкософтеров так и не понял. У них свой C# есть — там что хош , то и делай, то и выдумывай.

Но на кой было так над С++ издеваться, ведь C++/CLI — это уже нифига не С++, там пол синтаксиса переделано, зачем было это делать ...

На C++/CLI очень удобно связывать native c++ код с дотНетом (в смысле с .net проектом, или наоборот). Это одна из самых главных фишек — ’клей’ между старым добрым С++ и .net фреймворком.

В терминах языка нет, в фреймворках есть. К примеру делегаты на C++

www.codeproject.com/...astest-Possible

Linq++

github.com/...ang/linqxx/wiki

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

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

Это называется неправильной декомпозицией. Если разговаривать аналогиями, это вера в халяву: кто-то за вас рассчитает модель молотка, силу удара, вложит молоток вам в руку и забьет гвоздь. Так не бывает, вы просто прячете проблему за «фабриками». Вы наивно думаете, что спрятав сложные моменты вы сможете нанять таджиков которым пофиг что и чем забивать. Но ни в реальности, ни в софте халявы не бывает. Закончится это плохо — на сдаче проекта заказчик вам справедливо заметит, что дюбеля забиваются не молотком/кувалдой, а монтажным пистолетом, а ваши таджики будут самозабвенно лупить по дюбелю рукояткой этого самого пистолета.

И? Какую мысль вы хотели выразить ссылкой на мой же пост?

Заметил что молодые разработчики ориентированны прежде всего на реализацию, поэтому мыслят методами и классами но очень редко пишут интерфейсы.
Т.е. для них разработка начинается сразу с написания кода, без попыток абстрагироваться, представить и продумать предметную область и ее объекты.
Я считаю что синьор должен всегда писать сначала интерфейсы, просто представляя, как они «волшебным» образом делают то, что надо. Следующим шагом это представление превращается в тесты и моки. И только потом пишется настоящая реализация («невидимая» ни для кого, кроме IoC контейнеров или фабрик). В итоге программа превращается в «мозаику», каждый кусочек которой писали разные разработчики в разное время но потом это все собирается в нужную картинку в зависимости от настроек. Очень гибкое и расширяемое решение.

P.S. Если интересно могу расписать подробнее плюсы и пример реализации на .Net.

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

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

Дык а почему интерфейсы нельзя здесь пропустить и создать при необходимости, когда наклюнется несколько реализаций?

Почему не D.R.Y. K.I.S.S.?

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

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

Чего переписывать? Один клик мышкой «extract interface»!

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

Да, я забыл, ты у нас самый умный и опытный здесь. Извини, больше не буду не уважать твою мудрость.

То есть до клика мышкой ты не успел написать всё что надо через new?
Если были только классы со свойствами то можно. А вообще это рефакторинг вроде называется. У меня не получается просто раз и

«extract interface»

Не буду не уважать это индусский код if (false != true). Можно написать «буду уважать»

То есть до клика мышкой ты не успел написать всё что надо через new?

new меняется вторым кликом мышки «introduce factory»

Не буду не уважать это индусский код if (false != true). Можно написать «буду уважать»

Та нет, до уважения в данной ситуации очень далеко.

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

Настоящему программисту мышь не нужна =)

По той же причине, почему хорошо TDD — надо сначала думать, а потом уже кодить. Без интерфейсов нет ни мокинга, ни TDD, ни «слабой связности», ни «инверсии». Если сходу написал класс — то и тесты напишешь «по готовому». В итоге окажется что класс делает много всего хорошего (и тесты проходит), но не совсем то, что от него хотели другие классы.
Избегайте заблуждения что интерфейсы и абстрактные классы нужны только если есть больше 1 реализации. Они нужны всегда и еще до самого класса.

Без интерфейсов нет ни мокинга, ни TDD, ни «слабой связности», ни «инверсии». Если сходу написал класс — то и тесты напишешь «по готовому».

Набор вызывающе невежественных утверждений.

Вопрос на самом деле не принципиальный. Не хотите интерфейсы плодить? — Пожалуйста! Сделайте класс с пустыми методами и пляшите от этого. Мысль верхнего комментария заключается в том, что api должно определять реализацию, а не наоборот. На деле, конечно, они вырастают рука об руку, но первый шаг должно делать api.

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

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

А в другой очередности у тебя код писать не получается?

Первый шаг должны делать обои

Казалось бы при чем тут Java

Фабрики фабрик — костыли кривого ООП, как и практически все паттерны в ООП языках.

Конечно, костылям всегда есть альтернатива. ОО парадигма не единственная и плохо её везде использовать. Например, то что распараллеливать функциональный код намного проще, вроде бы очевидная мысль, а до многих так и не дойдёт. А обилие фабрик, IoС контейнеров, xml и аннотаций это не ООП, а недалёкость архитектора.

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

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

при желании

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

Да ОО подход позволяет писать параллельный код но что проще, следить за общей памятью с помощью мьютексов, мониторов и прочих прелестей синхронизации или просто передавать сообщения?

Тема ООП вс Функциональщины ортогональна теме передачи сообщений.

ООП вс Функциональщины

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

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

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

А вот ограничение функциональной парадигмой in place изменений ведут к сильной потере производительности во многих случаях.

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

Мне проще использовать одну команду для паралельной обработки (FOR). Это касатель .net.

Грамотно, только это можно только с 4го фремворка. А было бы не плохо еще и понимать как оно работает.

До TPL был стандартный набор для парелельного программирования. Семафоры и прочее. Но теперь то жизнь стала проще)

функциональный код намного проще

Пишите) Требую кнопку поржал. В чем смысл? Проще для кого?

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

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

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

Если всё же у Вас были какие-то причины для выбора крайне ускоспециализированой и сложного занятия, кроме очевидно некорректных " в 23 можно получать 2.5k«, то, они вполне подойдут и в качестве ответа на вопрос «в чём смысл?».

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

Действительно, видел много серьезной критики ООП ( ru.wikipedia.org/...рограммирование ). Все кивают на функциональные языки. Если можете, подскажите, как проектировать архитектуру без ООП подхода. Чем моделировать предметную область, если не классами?

Вы наверное имели ввиду «если не объектами», т.к ООП не имеет полные права на слово класс. На самом деле все зависит от ситуации, если у вас реальная архитектура требующая объектов, любимый пример складское управление: приходные, расходные, то да ООП тут король. Однако, если взять область которую можно выразить математически, то намного удобно моделировать предметную область языками типа Haskell, например финансовые операции.Или если вам нужно генерировать много кода в другом языке, тогда lisp/clojure, т.к объекты будут лишней надстройкой.

Что касается слова класс, но оно используется и в Haskell(привожу его как самый чистый ФЯП), но значится больше в контексте «тип типа данных», решаемый задачи «класса из ООП», но смотря на прикладную область несколько по другому.

Они там выступают в качестве интерфейсов в ООП понимании.

в качестве интерфейсов java, т.к для с++ аналогия будет виртуальная функция =)

лучше тогда «протокол взаимодействия» сказать...

К сожалению в функциональных языках не силен — так, читал по-верхам. Насколько понял — в них специально избегают хранения «состояния». А что такое ООП объект как не состояние (+ методы). А базы данных так вообще «состояние» в чистом виде.

Функциональное программирование для математических, финансовых и других «вычислительных» задач — это понятно. Вопрос именно в том как на них целиком написать, например, интернет — магазин или портал?

Целиком вообще нельзя написать, как раз в силу приведенных вами причин, т.к это изначально против логики взаимодействия с внешним миром, нарушение детерминированности. Такие языки как lisp потеряли в процессе развития функциональную чистоту добавив возможности взаимодействия не только с интерпретатором. Однако, разработчики Haskell поступили интереснее, они создали что-то типа своего «мирка» отдельного от основного ядра языка и назвали его IO для взаимодействия с внешнимим устройствами, а оттуда уже строили мосты обеспечивая детерминированность данных. Т.е они решили сугубо прикладную задачу, которой не возникало в мире математики и вычислений, как взаимодействие с пользователями. Очень интересно сделан OCaml который в себе содержит элементы как функциональных языков, так и ООП.

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

Однако и тут замечу, что императивная составляющая языков быстрее понимается людьми без математического бэкграунда, оговорюсь, что это не укор. Бывают в том же Haskell удобные вещи, а бывают совсем идиотские с точки зрения человека писавшего годами на java, например. Это вопрос восприятия и исторической традиции =)

Интересно поступили с состояниями в clojure, там есть контейнеры, которые хранят историю состояний, но не само состояние, сам объект всегда иммутабелен. Clojure наиболее адекватная надстройка над JVM на данный момент, даже в твитерре много многопоточного кода на нем написано, и они отказались от scala в пользу clojure в некоторых участках.

даже в твитерре много многопоточного кода на нем написано, и они отказались от scala в пользу clojure в некоторых участках.

Я так понял они не отказывались, а просто купили clojure shop Backtype, перцы из которого и продолжили писать на clojure.

Backtype само собой, но это кажется было еще в конце 2010, я смотрел уже в 2011 конференцию O’Relly немогу найти доклад того чувака (худой гаваец), и он говорил, что они ушли от части поискового кода со scala в clojure и были очень довольны.

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

Это какой то единичный случай который фиг нагуглишь. Помоему как раз твиттер для нагруженных апликух актовно продвигает скалу, о чем свидетельтвуют например заопенсоршенные finagle & cassie.

www.youtube.com/...dZXnsNi8#t=250s вот один кусочек, он тут просто говорит, что используют clojure, но видел где он подробнее рассказывал про это дело...

Raffi Krikorian — TL of AS

Ну так он как раз и говорит что купили бектайп и начали юзать clojure.

Модули, не?
Все равно вы в серверной разработке ООП не используете. У вас либо объекты с методами, но без полей (поля для инжекта не в счет), либо с полями, но без методов (опять же, геттеры-сеттеры не в счет). Чем по вашему это отличается от модулей и структур процедурных языков?

Вот когда вы занимаетесь UI, тогда да, ООП присутствует.

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

В моем представлении Domain Driven Design — это только ООП (даже если объекты без методов). Возможен ли DDD на функциональном языке или что его там заменяет?

Подписаться на комментарии