Если б мишки были пчелами - или ООП межушного нервного ганглия

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

Начну издалека. В далекие седые времена люди писали программы на чем придется. Алгол там, ФорТран, Кобол вот это все. Скорее всего, конечно, все было не так - и старая гвардия, мощно потрясая седыми мудями, решит упрекнуть меня в недостоверности - но пример иллюстративен, и всякие (не)совпадения с известными персонажами случайны. Так вот, после написани первого HelloWorld в машинных кодах и дикой радости от мигающей лампочки - прогресс пошел по примерно тому же пути, по которому шла эволюция разума. А именно - обобщению и введению абстракций. Самым первым и базовым уровнем абстракции служили разные там условные ветвления и циклы, которые позволяли сделать код более компактным и удобным к пониманию. Далее придумали процидурки и функции. Процидурки и функции позволяли еще более абстрагировать куски кода и делать его более специализированным, вводя понятие контракта. Здесь математики узрели клевую возможность заточить все под свои нужды, и придумали функци анальное программирование. Более прагматичные предки современных программистов придумали процедурное (или императивное) программирование. Разница между этими подходами с одной стороны - заметна невооруженным взглядом, с другой стороны - все то же самое, только вид в профиль, да и монады по итогу выполняются в какой-то там виртуальной машине цацкеля, которая крутится на вполне императивных процессорах. Это все может завести в дебри первичности курицы и яйца, войны императивного и функци анального программирования все еще актуальны и поныне, поэтому не стоит в это углубляться, по крайней мере сейчас. Важно понять - от набивания новых программ в машинных кодах люди постепенно перешли к переиспользованию уже существующего кода. Отсюда пошли разные там стандартные библиотеки, boost, хекедж и весь тот зоопарк фреймворков и костылей, которые можно найти в чуть менее чем всех существующих приложениях.

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

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

И вот тут в ширнармассы проникли идеи, что Все Суть Объект, ну то есть Сущность, со своим поведением и некими свойствами. Это обозвали инкапсуляцией. Потом кто-то обратил внимание, что объекты натуральным образом формируют иерархии. Ну то есть есть какая-то фигня под названием “автомобиль”, в которой (как правило) присутствуют двигатель, управление - ну и прочая фантазия. Грузовая машынко ко всему этому добавляет еще кузов и некую характеристику грузоподъемности например, автобус - количество перевозимых людев. Ну вы поняли идею. Иерархия четко прослеживается, и для вот этой банальности придумали наследование. Ну все как у людей. Параллельно с этим обратили внимание, что для умения крутить баранку автомобиля и жать на педаль газа не нужно точно знать, а что ж у нас там за машина - а достаточно собственно знать, какую педальку жать и куда крутить руль. Соответственно случилось изобретение subtyping полиморфизма, который в полный рост присутствует в жабе, крестах и еще где-то там.

Вот как правило знание этих, простых в сущности, вещей и требуется на разных интервью жабодевелоперов. Причем любой жабодевелопер уверен, что полиморфизм бывает только один единственный. Я очень надеюсь, что кто-то меня тут разубедит в том, что ни в одной книжке про жабу нет ни единого упоминания про ad-hoc полиморфизм, или параметрический полиморфизм. Собственно, вопрос “сколько видов полиформизма вы знаете” практически с гарантией вырубает любого конь ди дата с жабьим бекграундом. Не говоря уже про вычисления на типах и kind expressions.

Далее, в виду особенностей человеческого восприятия (ну не каждый может оперировать абстрактными формулами) понятие объектов и взаимодействия между ними стало близким и доступным, создав ложное впечатление, что ООП - это серебрянная пуля, золотой молоток, альфа и омега всего программирования. Вон в SmallTalk даже и методов как таковых нет, только передача сообщений (отсюда кстати растет Actor model, двигаемая Typesafe в Akka).

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

Что же представляют из себя эти шаблоны? Как видно из педивикии и прочих мурзилок по теме - набор неких практик, которые позволяют решить какие-то проблемы. И вот в этом месте почему-то у многих людей снесло башню что эти ШП могут помочь решить проблемы проектирования приложений вообще. Упоротость простерлась до классификации этих ШП, и на многих, многих интервью на полном серьезе спрашивают про “что такое производящий шаблон, и что такое поведенческий шаблон”. Также в обиход вошли попытки засунуть эти ШП в разные, совершенно ненужные места, ну просто чтоб было. Для полной ясности можно охуеть в конвульсиях посмотреть на потроха Swing или того же SWT, ну или оценить java.io.* во всей его красе.

Я как-то стебался на интервью, задавая вопросы типа “как вы думаете, что лучше - наследовние или полиморфизм”. И товарищи даже пытались ответить.

Применение ШП без включения разума как правило приводит к “шаблонному методу фабрик синглтонов для стратегий прокси флайвейт объектов”. То есть когда нужно просто взять - и закодить два for-цикла - создается итератор итераторов с визитором сверху. Мотивация “а вдруг надо будет расширять”.

Вот это вот “надо будет расширять”, вкуче с ШП, приводит к появлению монструозных фреймворков типа спринга или хибернейта, где упоровшиеся авторы выдумали себе проблемы, которые надо бы решать, и сделали все, чтобы решение ваших проблем стало заклинанием духов на поляне среди кладбищ в жаркую июньскую ночь, с поеданием паутины тарантула и укушением жопы жертвенной жабы во имя великой Жабы.

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

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

Так что ж такое ШП и зачем оно нужно? Как правильно было указано - ШП позволяют решить некоторые проблемы, а именно - обобщение обхода ограничений языков программирования. В самом деле, если у есть case class из scala - то зачем билдеры. Или если есть duck-typing - то не нужны стратегии. А наличие функций высшего порядка и лямбд позволяет избавиться от большинства поведенческих шаблонов практически полностью. Наличие вывода типов позволяет избавиться от визиторов. Ну и так далее.

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

Что же делать? Вариант - не писать на жабе/крестаъ/коболе - можно отбросить как неконструктивный (но все же лучше рассмотреть, потому как в чем смысл тратить годы жизни на войну с костылями?). Остается вариант включения мозга. И там, где можно обойтись двумя циклами - лучше обойтись двумя циклами, а не городить фабрики визиторов в надежде на “вдруг в будущем надо будет что-то сделать, а тут я раз такой - и все готово за 15 минут.”. Как правило, такие инвестиции не работают, а вся эта микроархитектура нахер не нужна. KISS.

Почему-то в куче мест рассказывают про предварительную оптимизацию, а вот про предварительный оверинжениринг - нигде. Это досадное упущение, которое противоречит даже основным принципам проектирования ООП-систем “Single class - single responsibility”.