Концепция объектно-ориентированного программирования воспринимается разработчиками по-разному: кто-то говорит, что ей уже пора на свалку истории; кто-то кодит и не задумывается о том, что, как и почему он делает; а кто-то пытается работать в «pure OOP» парадигме, переворачивая классические паттерны с ног на голову.

В преддверии Joker 2016 мы попросили Баруха Садогурского обсудить судьбу Java и ООП с Егором Бугаенко. Что из этого получилось, слушайте в аудиоформате или смотрите в видео:



А под катом лежит полная расшифровка интервью со всеми ссылками.

Барух jbaruch Садогурский: Всем привет. Меня зовут Бaрух, я developer advocate в компании JFrog, ведущий подкаста «Разбор Полётов», спикер на конференциях вроде Joker, JPoint, ну и всякой лабуде типа JavaOne, Devoxx и прочего. И сегодня в солнечном Маунтин-Вью мы сидим с известным в определённых кругах Егором Бугаенко, встретились поговорить за жизнь.

Егор yegor256 Бугаенко: За жизнь? А я думал, про ООП, Java…

Барух: Наша жизнь — это и есть ООП, Java. Для начала расскажи о себе для тех, кто не слышал.


Егор: Java-программист, архитектор. Программировать начал лет 20 назад, ещё в школе — вначале это был PASCAL, потом ассемблер, потом C, потом C++, потом Java. Последние два с половиной года веду блог, благодаря которому появилась какая-то известность. Пишу книжки, сейчас пишу второй том. Пытаюсь немного поправить объектно-ориентированные подходы, которые используются в Java. Где-то получается, где-то меньше, но пытаюсь эту идею доносить в массы, благодаря чему эти массы…

Барух: Бурлят!

Егор: Бурлят и реагируют по-разному, да. Кому-то это нравится, кому-то нет, но эффект это производит, до кого-то какие-то мысли доходят. Кто-то против, и я не могу сказать, что сам уверен во всех своих мыслях на текущий момент, но процесс идёт. Да, чем я зарабатываю на жизнь: у меня небольшая распределённая команда в Пало-Альто, порядка 50 человек сейчас, так сказать, работающих, а суммарно человек 100. Мы пишем софт на заказ на Java. Заказчики у нас здесь, в Силиконовой долине, я управляю этими процессами с несколькими проджект-менеджерами. Программисты по разным странам, отовсюду. Вот этим зарабатываю, ну и книжка немножко денег даёт.

Барух: У меня к тебе масса вопросов. Во-первых, задам острый вопрос: откуда ты такой взялся? Ты появился на поверхности русскоязычного Java-комьюнити год назад, вихрем прошёлся по конференциям на постсоветском пространстве, и я так понимаю, что завязал. Что это было, Бэрримор?



Егор: Не завязал, у меня ещё 7 конференций впереди — меня приглашают, я не отказываюсь. Но теперь не так активно. Я выступил за последние полгода на 25 конференциях, немножко многовато.

Барух: Так вот, как так получилось, зачем это тебе надо? Это достаточно тяжёлая работа, я по своему опыту знаю. Программист, архитектор, CTO внезапно решает: «А не провести ли мне полгода, разъезжая по конференциям».

Егор: Хороший вопрос, у меня нет на него ответа. Но в какой-то момент я понял, что хочется расширить аудиторию. Блог меня на это подбил.

Барух: Зачем тебе эта аудитория? На блоге много не заработаешь, на книжке много не заработаешь, я не вижу в этом коммерческого интереса. Может быть, ты таким образом хайришь людей?

Егор: Ты понимаешь, я уже не контролирую этот процесс, я стал заложником процесса, который сам создал. Я завёл блог, появилось комьюнити, люди дают свой фидбэк и начинают меня вытаскивать, чтобы я с ними поговорил. Это двунаправленный процесс. С одной стороны, я хотел выступить на нескольких ключевых конференциях: JPoint в Москве, в Киеве JEEConf, в Белоруссии тот же JET. А другие места появились сами, потому что люди меня стали видеть и говорить «Давай и сюда тоже».

Барух: У меня есть интересная аллегория, она весьма непроста, но попробую. То, что ты делаешь, у меня вызывает религиозные коннотации. У тебя «пророчество» как процесс: ты ходишь по миру, рассказываешь какие-то совершенно «еретические» вещи, люди тебя любят, ненавидят, ты это уже не контролируешь. Это совершенно библейская история. И они обычно плохо кончают, эти пророки!

Но у меня по поводу твоей концепции объектно-ориентированного программирования очень много вопросов, сейчас мы попробуем их как-то последовательно выстроить. Основной вопрос такой: ты пытаешься придать термину «объектно-ориентированное программирование» какое-то значение, которого не только сейчас у него нет, как ты утверждаешь, но и которого, на мой взгляд, никогда не было.

Есть то, что мы называем объектно-ориентированным программированием. Это, как мне кажется, отличается от того, что ты называешь объектно-ориентированным программированием. И возникает вопрос «зачем?» Есть тот путь, который ты считаешь правильным, и у него могут быть плюсы и минусы, как и у любой парадигмы — функциональной, объектно-ориентированной и так далее. Почему ты пытаешься всунуть свой путь именно в нашу знакомую, уютную, обжитую, нишу объектно-ориентированного программирования?

Егор: Почему не создать какую-то новую парадигму, ты спрашиваешь?

Барух: Ну она и есть новая парадигма же. У слов есть свои значения. ООП — это классы, объекты, посылка месседжей объектам с определёнными параметрами для получения обратно какого-то значения. Это полиморфизм, наследование, какие-то вещи, которые мы знаем, любим и так далее. Теперь ты приходишь и говоришь: «Нет, объекто-ориентированное программирование — это не это». Зачем?

Егор: Ну, скорее не «зачем», а «почему». У меня нет ответа на вопрос «зачем?», потому что для этого должна быть какая-то цель, у меня такой чёткой цели нет. Ни денежной, ни какой-то другой. Это вопрос, скорее, «почему?», почему я так делаю. Потому что мне сильно не нравится то, с чем я работал на протяжении многих лет… Мне не нравится ни тот код, который я писал, ни та Java, которую я видел, ни библиотеки, с которыми я сталкивался, мне неприятно с ними работать. Не только мне, а людям, которые вокруг меня, программистам. Я вижу, какой код они пишут, как тяжело этот код потом понимать, поддерживать, как вообще неприятно программировать.


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



Я на конференциях задавал вопрос аудитории: «Вам нравится то, что вы делаете? Вы любите этот код, вы с утра просыпаетесь, смотрите на этот код и хотите его писать, или вы пишете потому, что вам нужно это делать?» Кто-то говорит «Да, нам нравится», но я думаю, многие лукавят. Я помню себя, когда первые три дня или три недели пишешь программу с нуля, и она тебе нравится, а последующие три года ты пишешь её потому, что должен.

Барух: Ну это всё понятно, но это нормальное явление…

Егор: Я думаю, что ненормальное.

Барух: Ну я к тому, что это известное явление, и решение этого тоже неизвестно, например возьми всех, кто сегодня использует функциональное программирование, они говорят «нам не нравится объектно-ориентированное программирование, и мы пошли в другую парадигму потому, что нам было противно от этой вашей Джавы». И они взяли и пошли в другую парадигму.

Егор: Но они и там нагадят. Если они не поняли ООП и просто от него отвернулись, сказали, что оно плохое в целом, всё ООП… Как вот недавно в блоге я собрал цитаты известных людей об объектно-ориентированном программировании. Они все говорят гадости. Начиная с Дейкстры, заканчивая сегодняшним днём. Люди говорят, что это противная концепция в принципе, давайте её не использовать, потому что она помогает создавать «spaghetti code».

Барух: Ну да, они утверждают, что индустрия переросла объектно-ориентированное программирование — так же, как она переросла процедуральное программирование. И тут я опять возвращаюсь к тому же вопросу. Естественный ответ был бы: «ОК, вот новая парадигма, вот «ООП 2.0». А ты говоришь: «Нет, то, что вам не нравится, на самом деле называется по-другому». И вместо того, чтобы предствавить свою новую парадигму (что само по себе непростой путь), ты к этому добавляешь ещё сопротивление того, что люди не понимают, зачем ты пытаешься назвать это чем-то иным.


Весь мейнстрим неправильный, 95% вы делаете неправильно



Егор: Ну чтобы носом их ткнуть. Это такой элемент провокации, который необходим, чтобы люди задумались. Если я им предложу «ООП 2.0», как ты говоришь, ну почитают несколько человек, скажут: «Ну хорошо, ещё одна идея какая-то, отложим её, подумаем. У нас есть Java, она прекрасна, она идёт вперед, она мейнстрим, на ней все пишут, по ней проводятся огромные конференции, на ней огромные фреймворки, всё прекрасно». Есть какая-то другая, новая парадима? Ну хорошо, у него пол-фреймворка, восемь программистов, ну вот пусть они там сидят и копаются. Когда же я прихожу в этот центральный мейнстрим и говорю «Ребята, весь ваш мейнстрим неправильный, 95% вы делаете неправильно», народ начинает шевелиться, ёрзать на стуле и понимает, что ему не предлагают что-то третье (куда он может пойти, а может проигнорировать), а объясняют, что сегодня ты только вредишь всем. Конечно, это вызывает большие эмоции. У меня много мейлов есть, мне люди пишут: «Я понял, что десять лет подряд делал не то, твоя такая-то статья открыла мне глаза, я теперь всё понял, я буду делать так», а другой пишет: «Да заткнись ты, прекращай это рассказывать, мы знаем, что делать». Такая разнополярная реакция говорит о том, что людей это затрагивает, что им это небезразлично, а это хорошо. А если делать что-то стоящее в стороне, это мало кому покажется интересным.

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

Егор: Так получилось. Когда я начинал статьи писать, у меня была первая статья о том, что null reference — это плохо. Она не очень провокационная, потому что многие об этом знают и говорят. Я написал немного более резким тоном: большинство статей говорит о том, что старайтесь его избегать, а я написал, что это в принципе плохо, это evil, не трогайте его. Потом пошёл чуть дальше и написал про геттеры и сеттеры. То есть я не хотел никого провоцировать, я просто писал, исходя из своего опыта. Потом отследил реакцию и понял, что многих людей это цепляет за живое, и они согласны с этим, увидел много фолловеров, не хейтеров. А потом подключились хейтеры. Но я их игнорировал, потому что видел, что кому-то это в кассу, кто-то с этим согласен. Я пошёл немного дальше. Но я не специально, не было такой задачи: давай мы сейчас спровоцируем толпу, увидим, на что у них будет реакция и начнём собирать трафик. Такой цели не было. Я просто написал сначала несколько статей из своего нескольколетнего опыта.



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

Егор: Причем хейтеры — это в основном люди, которые мало читают, которые мало слышали, слышали звон — ну ты сам это видел на «Разборе полётов» в 109-м выпуске, когда Женя EvgenyBorisov Борисов пришёл и клеймил меня, особо не прочитав ничего. Я всё хочу послать ему книжку. Я бы очень хотел, чтобы он прочитал всё целиком и собрал всё в кучу, ты же читал книжку, ты понимаешь это. А он прочитал что-то, услышал: «А, он говорит, что вот это плохо и это плохо, да он дурак».

И большинство негативных реакций именно такое. Люди узнали что-то по пол-слова и сформировали мнение. Это не сбивает меня, потому что есть люди, которые согласны. Если бы были все несогласны, я бы сильно задумался, не зря ли провоцирую толпу. А так сделали недавно на Gitter-чат, там набралось за полтора месяца 120 человек, и люди обсуждают, часто уже в стороне от меня. Часто бывает идея какая-то, один спрашивает: «Как бы вы это сделали?», а другие ему отвечают: «Мы бы сделали это так» и дают ссылки на мой блог. Это очень прикольно наблюдать, когда мысли уже не мои, они уже там живут, люди этим пользуются. Это приятно. Хотя есть в этом же чатике хейтеры, мы систематически стараемся тушить, а они поднимают флейм. И там часто задают этот твой вопрос: «Зачем ты меняешь ООП, у нас всё хорошо, у нас есть Java… Ну назови это по-своему и отстань от нас».

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


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



Егор: Да, ты прав совершенно, это плохо отражается на бизнесе. Во-первых, с приёмом на работу проблема, во-вторых, с поиском клиентов. Когда клиент приходит и слышит, что мы делаем что-то сильно иначе, чем другие, то возникает вопрос «а не ошибаются ли они». Мы вам всё закажем, а через полгода будем искать новую команду, которая всё это выбросит, потому что понимает только эта. Это есть. С набором на работу тоже проблема — хотя есть люди, которые очень хотят именно к нам, пока таких немного. Но мне интереснее не быть ещё одной компанией в большом ряду других, а быть компанией, которая делает что-то иначе и лучше. Может, я ошибаюсь.

Барух: Женя Борисов просил узнать, насколько часто бывает, что на интервью ты даёшь претенденту тестовое задание, показываешь кусок кода, а он переворачивает стол и говорит «что это за херня, я не буду это писать».

Егор: Я слышал тоже, как Женя Борисов сказал в каком-то «Разборе полётов», что у него в Израиле была знакомая команда, где люди делали что-то по-своему, и все остальные компании банили людей из этой команды. То есть, если ты приходишь из той компании, то всё, никаких интервью, потому что у тебя мозг сломан и ты пишешь по-другому. Я понимаю, у нас тоже есть такая штука. Мы когда принимаем Java-программистов на работу, мы часто даём кусок кода на Java, который, на мой взгляд, написан с большим количеством ошибок. И просим показать ошибки. Что бы вы исправили? И многим этот кусок кода кажется правильным, а там сеттеры, геттеры, null… Всё, про что я выступаю, там представлено. И те, кто не обращает на это внимания, просто рефакторит и считает, что всё нормально. Мы таких людей отклоняем. Но есть люди, их не так много, но и немало, которые находят и говорят: «Да вот тут у вас эти сеттеры, геттеры — это что за фигня, это ерунда… надо переписать по-другому». Вот таких людей мы сразу: оп, заходи. И они находятся, в месяц одного-двух неплохих ребят имеем.

Барух: Это хороший темп.

Егор: Мы не спешим, мы же не строим сейчас команду из тысячи человек. У нас на данный момент такой задачи нет. Но ситуация, мне кажется, на рынке меняется. Меня слышат, не так много людей, но кто-то слышит. Я думаю, что изменения пойдут не через мою компанию, не через коммерческие. А люди на местах у себя начнут менять. Мне написал человек несколько недель назад, что прочитал мою книжку, она ему очень понравилась, потом он показал из нее куски своим коллегам, и теперь с ним не дружат. Но он же пошёл и показал, значит, какой-то эффект пошёл, не я это рассказал, а он пошёл. Это прикольно.

Барух: Антропологический интерес в этом всём я понимаю. Раз уж всплывает книжка, давай немножко поговорим про книжку. Это началось, как блог, который ты решил подбить вместе в какую-то подборку…

Егор: Не, сначала я писал в блог чуть больше года, а потом со мной связалось издательство Manning. И они предложили написать книжку: ты напиши, мы опубликуем. Сначала я сказал «нет», потому что был занят, потом через полгода решил всё-таки написать. Сел прошлым летом и за два месяца её написал. Это было несложно, потому что материал из блога. Сейчас я пишу второй том, и это тяжелее: про некоторые темы никогда раньше не писал, и нет реакции людей. Когда писал первый том, знал реакцию читателей, у меня была куча комментов. С Manning потом не сложилось, и я опубликовал книгу сам. Желания изначально писать книжку у меня не было, но когда издательство предложило, я задумался.

Барух: Твоя концепция развивается, в ней есть противоречивые моменты, это какой-то ментальный work in progress, когда картинка ещё не полностью сложилась. Что требует какого-то переосмысления того, что было написано. Вот этот второй том является переосмыслением первого, или ты первый откладываешь и говоришь «что было, то было»?

Егор: Нет, я первый не трогаю, я во втором делаю ссылки на него: «вот я говорил это, а теперь я говорю немножко другое…»

Барух: Вот это я ищу: где будет написано, что ты был неправ?


immutability сейчас очень активно обсуждается в нашем чате и не можем до конца понять, что такое immutable object...



Егор: Ну у меня это бывает. Я пишу, что я был неправ, уточняю что-то. Допустим, immutability сейчас очень активно обсуждается в нашем чате и не можем до конца понять, что такое immutable object… И это обсуждение очень живое, у меня есть в блоге четыре штуки, и в книжке целая глава про … Если всё это сложить, то там есть вещи, которые друг другу противоречат. Но я открыт этому, нет проблем сказать, что я был неправ.

Барух: Сказать «я был неправ» в теоретических размышлениях — почётно, круто, но легко. Возвращаясь к бизнесу: что делать с кодом, который ушел в продакшн, и ты сейчас понимаешь, что там ой…

Егор: Вопрос хороший. Но даже если там были какие-то ошибки, они не такие серьёзные. Там нет таких фундаментальных ошибок, которые нужно было бы переписать целиком. Есть какие-то моменты, которые чуть-чуть левее, чуть-чуть правее, но в целом нет. И концепция — я не сказал бы «стройная», но складывается одно с другим. Я не просто пишу об идеях, я еще и код пишу также. И есть некоторые продукты, которым три года, два года, один год. Можно их просмотреть и увидеть, что в продуктах, которым три года, два года, масса вещей, до которых я дошел вот недавно, не было. Сеттеров не было, но в некоторых местах есть и null pointer, и ORM используется где-то. То есть некоторые вещи можно открыть в опенсорсе и увидеть, что теоретическая мысль была там ещё в зачатке. А более свежие продукты более интересные, в них уже используется вся красота ООП.

Барух: Ну вот это интересное раскрытие информации о том, что на самом деле концепция ООП от Егора — она work in progress. Я не уверен, что многие, кто с твоей концепцией познакомился, это понимают. В основном из-за книжки. Потому что обычно, когда человек пишет книжку, поскольку оно на бумаге и автор не может добавить апдейт «вот тут мне написали в комментах, что я был неправ», оно как-то воспринимается законченным. Immutable, так сказать. Мне кажется, многие люди не в курсе, что это всё живёт, развивается, течёт. И на самом деле ты готов не только слушать, но и принимать критику, и она действительно может как-то изменять концепцию.


Класс — это вообще ошибка. Не должно быть классов.



Егор: Приведу пример. Ну вот например в книжке у меня написано, что класс — это определенная концепция, которая нужна и важна. Я разговораривал с Дэвидом Уэстом. И он мне говорил, что класс — это вообще ошибка. Не должно быть классов. Я думаю, я пока не уверен, прав он или что он имеет в виду.

Барух: Концепция, что класс — это ошибка, это из JavaScript. Объектно-ориентированное программирование через prototype. И есть очень серьёзный диспут на очень высоком уровне, который уже продолжается двадцать лет, о том, нужен класс или нет. И есть доводы за и против. Довод за: в объектно-ориентированном программировании класс — это действительно совершенно лишняя сущность. Она не добавляет ничего. Ты создаёшь объект, как его считаешь нужно создать, и потом создаёшь ещё сколько-то таких же. Но тут, с другой стороны, есть масса проблем типа immutability: объект может измениться, что происходит с теми, кто создан до этого? Должны ли они измениться, должны соответствовать новому или старому? И почему вроде одинаковые объекты, созданные с разницей в несколько строк кода ведут себя по разному? Потому что в каком-то другом месте изменился prototype. Ну, приехали, классно теперь. Вот эта концепция blueprint как класса, из которого ты клепаешь объекты, этот вопрос решает, потому что класс — это что-то неизменяемое, а объекты от него потом отпочкуются и живут своей жизнью. А с прототипами это не так понятно. Поэтому тут безусловно есть, о чем подумать.

Егор: Есть, да. И что, если я поменяю свое мнение?

Барух: Ну, если ты ещё и от классов откажешься, то это вообще будет армагеддон.

Егор: Я пока не отказываюсь от них, но Дэвид сказал мне: «Кто это вообще придумал, зачем они нужны?»

Барух: А вот теперь скажи мне, давай возьмём такую гипотетическую ситуацию, что ты действительно решил отказаться от классов и наследования. Ты — человек, который мёртвой хваткой вцепился в Java (надо понять, почему, сейчас мы об этом тоже поговорим), но гнуть Java под свой ООП можно только до определённой степени.

Егор: Да.

Барух: Что ты будешь делать, если ты решишь, что класс — враждебная ООП структура?

Егор: Я надеюсь, что я так не решу, хотя… Понимаешь, у меня есть некоторые статьи, где сказано «как плохо делать вот это», но не предложено никакой альтернативы Java, я так их и заканчиваю: если Java улучшится, и это будет какой-то новый язык, тогда мы сможем делать то-то и то-то.


я предлагаю управление памятью: говорю, что диски и память должны быть чем-то одним. Мы же даём программисту в Java управлять файлом на диске — открыли, закрыли. Почему то же самое нельзя делать с памятью?



Например, я предлагаю управление памятью: говорю, что диски и память должны быть чем-то одним. Мы же даём программисту в Java управлять файлом на диске — открыли, закрыли. Почему то же самое нельзя делать с памятью? Вот такой концептуальный вопрос. Java этого не даёт, а мне кажется, что правильный язык должен давать возможность управлять памятью. Как в C/C++, но в каком-то удобном виде. Но Java я не поменяю.

Барух: Это подводит меня к следующему вопросу: почему ты мёртвой хваткой вцепился в Java? Ты уже пришёл к выводу, что истинного ООП-языка не существует. У нас есть платформа JVM, позволяющая относительно малой кровью написать любой синтаксис языка, в котором будут все карточные игры и все девушки лёгкого поведения истинного ООП, которые ты только захочешь. Тебе не приходило в голову такое?

Егор: Это большая работа, и пока у меня нет большого количества фолловеров, коммьюнити, она ни к чему не приведёт. Должна быть большая группа людей, иначе это будет мёртвый язык. Есть какие-то люди, которые были бы не против помочь, но это большая работа, я к ней пока не готов. У меня есть очень старая статья, ей года четыре, где я просуммировал все фичи, которые хотел бы иметь в правильном языке. Так вот, мне кажется, что он должен совмещать язык и платформу разработки. Приведу пример. Почему из кода мы не можем получить доступ к Git-истории? Я могу получить в комментариях то, какой у меня хэштег в этом файле, ну и всё.

Барух: Я, наверное, тебе отвечу, что это отличная библиотека, но не обязательно функция языка. Существует подход, что в принципе языки должны быть минимализированы, а всё остальное подключается с помощью необходимых библиотек. И тебе есть дело до истории твоих коммитов в Git’е, а мне нет, например. Тебе нужна эта фича — ты подключаешь библиотеку, и она у тебя есть.

Егор: А её невозможно сделать как библиотеку, она должна быть в языке.

Барух: Вот это интересный вопрос. Почему?


Потому что эта библиотека будет выглядеть криво, как AOP в Java, приклеена сбоку, как AspectJ



Егор: Потому что эта библиотека будет выглядеть криво, как AOP в Java, приклеена сбоку, как AspectJ. Прикольная идея, классная, но нет её поддержки в языке. Есть аннотации, которые появились позже. В четвёртой Java вообще не было никакой поддержки AOP, и всё это было налеплено через неродные технологии. Поскольку они неродные, всё неудобно, некрасиво. Java, или любой язык, должен давать AOP by definition, он должен быть by default, встроен в язык. И так же доступ к Git. Это история наша — кто коммитит, сколько коммитит — это уже часть языка.

Барух: Но сегодня это Git, а завтра — Mercurial.

Егор: Это проблема, да.

Барух: И эта проблема решается библиотекой. Сегодня подключил библиотеку для того, завтра для другого.

Егор: Я согласен, возможно, нужна какая-то комбинация «язык + библиотека». Нужна возможность, используя язык, получить доступ.

Барух: С тем, что для языка может быть полезно бoльшее количество SPI я, возможно, соглашусь.

Егор: Вот штук 40 таких фич, которые должны появиться. Допустим, Continuous Integration. Она совершенно никак не приклеена к языку. Или build automation. У нас есть все эти мавены и грейдлы, которые к Java никакого отношения нативно не имеют. Сам код на Java не знает, что его будут билдить. Я внутри кода не могу получить доступ к этой информации. Или, допустим, юнит-тесты. Они существуют на Java как просто класс, но какие это классы? Какие это объекты? У меня есть объект book, что такое объект bookTest? Это странно. И эти методы — это не методы, это процедуры в чистом виде, микроскрипты. Оно должно быть сделано как-то иначе. Сделано так, потому что тесты сделали после Java. Нужны вам юнит-тесты — ну вот так лепите. Это не нативно, не клеится одно к другому. Этим пользуются, но должны быть более удобные средства внутри языка. Я думаю, что мы к этому идём. Такие plain языки типа C, где просто можете скомпилировать бинарник — это двадцатилетней давности, а сейчас нужно что-то новое.

Барух: Это Java двадцатилетней давности, а C уже сорокапятилетней.

Егор: Тем более, должно быть что-то новое. Я думаю, появится. Может быть, я что-то создам, не знаю. Это требует времени и, главное, должно быть коммьюнити. Создавая под себя, получу чисто моё решение. Вот ты говоришь «не Git, а что-то другое», а мне такое и в голову не придёт, для меня Git стандарт фе-факто. Ты скажешь «у нас целая команда на Mercurial или Subversion», а у меня уже не лепится, целый кусок рынка моё решение не будет поддерживать. Тут должно быть гетерогенное коммьюнити, где разные люди.

Барух: Скажи, а что ты думаешь о новых языках? Два примера — Kotlin и, может быть, Ceylon, если ты на него смотрел.

Егор: Ceylon мало смотрел, Kotlin — был на презентациях на конференциях. Я тут не могу быть экспертом, но, к сожалению, мне кажется, что общее направление в индустрии не в сторону чистого ООП, а, наоборот, в сторону его коммодизации. Вам нужны геттеры и сеттеры — так вот они by definition. В Котлине вам не нужно их писать, они там есть! Язык придуман и развивается как design pattern — люди накодили, а потом другие приходили и говорили «это назовём синглтоном, а это вот так». А должно быть с обратной стороны, должны люди приходить и говорить «давайте использовать такой design pattern, такое решение». И потом все практики за ними должны идти. А мы идём от практики к теории.


Java EE, практически покойный по сравнению с технологией, которая рождается из best practices, по сравнению со Spring.



Барух: Ты предлагаешь башню из слоновой кости. У нас в Java коммьюнити такая есть. И она на наших глазах рассыпается. Я говорю про Java EE, практически покойный по сравнению с технологией, которая рождается из best practices, по сравнению со Spring. Смотри: Java EE развивался как раз так, как ты считаешь правильным. Сидели умные пацаны, которые думали, какие best practices должны быть, назвали их официальным стандартом. Более того, этот стандарт продвигался самым сильным на рынке Java-игроком — самим Sun, а потом Oracle, у тебя есть стандарт from the source, что может быть лучше. И вот.

Егор: Я согласен. Значит, плохие теоретики, инженеры. И они должны работать в связке, теоретики должны смотреть на практиков. Но потом не описывать увиденное, как Kotlin. Не хочу сказать конкретно про Kotlin, но выглядит так: посмотрели на то, что люди делают, и увидели, что все делают геттеры и сеттеру, давайте людям упростим жизнь. Я предлагаю наоборот: давайте людям усложним жизнь там, где они делают что-то неправильно, чтобы они перестали делать геттеры и сеттеры. А большинство языков программирования создаётся в битве за популярность. Они понимают, что если дать людям не 4 инструмента, а 14, упрощающих то, что и так делают, то их станут использовать с большим интересом.


У Kotlin и им подобных направление, по-моему, неправильное. Практика должна идти с теорией, и теория должна корректировать практику.



Как Ruby. Язык вроде создавался правильно, но там такое огромное количество статики, такое огромное количество процедур, что весь язык… Язык хороший, но с библиотеками выглядит как какая-то каша. Им очень тяжело пользоваться, по крайней мере, мне. Я пишу на Ruby, но это какой-то кошмар, Java лучше. У Kotlin и им подобных направление, по-моему, неправильное. Практика должна идти с теорией, и теория должна корректировать практику.

Барух: То есть ты считаешь, что за языком должны стоять какие-то визионеры.

Егор: Конечно. Должны говорить «Ребята, вы идёте немножко не туда, теперь пойдём туда». А не «Все идут туда, побежим вперёд и встанем с флагом». К чему это приведёт? Это временные языки, они умрут через несколько лет.

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

Егор: Они не пойдут по новой дорожке, даже если ты им предложишь. Безусловно, то, что ты говоришь, имеет смысл. Никто не пойдёт по новой, потому что никто платить за это не будет.



Барух: Почему Java унаследовала столько болезней C? Потому что должно было быть похоже, чтобы программисты могли это взять и начать фигачить код.

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


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



Барух: Вот тут у меня есть для тебя интересная рефлексия. Вот то, что ты пытаешься сделать, и эти твои блог-посты, каждый поодиночке, преследуют эту цель. Ты объяснил, почему null — это плохо, что должно быть N параметров в методе, почему в конструкторе нельзя писать бизнес-логику. Каждый из этих ходов, наверное, немножко улучшает сегодняшнего Java-программиста. А потом я беру твою книжку, и, как я написал в ревью, я вижу совершенно другую, новую концепцию, по сравнению с сегодняшней Джавой. По совокупности всего вместе взятого. Когда я читаю один пост, могу немножко улучшить свой код, оставив всё остальное так же. Когда я читаю твою книжку, это геометрия Лобачевского. У меня начинают пересекаться параллельные линии. Это невозможно сочетать с тем, что я делаю сейчас. Или делаешь так, или по-другому. И твой код — он тоже совершенно другой. Он не постепенное изменение существующего. Когда я смотрю на твой код и сравниваю с моим, решающим те же задачи, это не просто «у тебя нет null, а у меня есть». Твой код вообще ничем не похож на мой, кроме скобочек и точек с запятой. И тут у меня получается некоторый диссонанс с твоей идеей инкрементальных изменений.

Егор: Понимаю, о чём ты говоришь. Но я не добьюсь результата мягкими действиями. В блоге я в рамках одной статьи вбрасываю, человек читает, немножко меняется. Книжка делает бросок далеко вперёд. Она говорит «Вы здесь, а правильно — вот там, через 20 километров. Как вы туда доберётесь, я не знаю». Как в анекдоте: «Моё дело — стратегия, а с тактикой вы сами решайте». А блог даёт какие-то шаги — тут немножко так, тут так. Книжка забрасывает далеко вперёд и писалась с такой задачей, не на один год — как вброс в будущее. Ну и она должна быть резкой. Тяжело человека сдвинуть. Масса была статей про null и про геттеры-сеттеры. Ты можешь погуглить, не один я это пишу. Почему мои вызывают такой флейм, у меня про геттеры-сеттеры триста комментов за полгода, а у уважаемого Аллена Холуба за десять лет пару комментов? Потому что он говорит мягче. Он говорит «Старайтесь держаться от них подальше, не использовать их». А я говорю «Если ты используешь их, то ты дурак». Естественно, это вызывает реакцию и побуждает к изменениям.

Барух: Ты сейчас ставишь две противоречивых цели. С одной стороны, ты говоришь об инкрементальном изменении людей, а с другой, про бросок на 20 километров… Вот смотри — Мой личный фидбэк — я прочитал, насладился мысленным экспериментом и забыл, потому что так писать сейчас я точно не буду. Мне очень понравилось, было очень интересно, я размял мозги, но что я приду на работу и начну писать так, не возникло мысли ни разу — в отличие от того, как я прочитал твой пост про null’ы и подумал «надо мне вот этого постараться поменьше теперь делать». Потому что я работаю в команде, мой код должны читать, и если я сейчас закоммичу в Git код «Yegor Style», то после code review мне нечем будет кормить семью. А если я уберу null’ы, меня только похвалят. И тут у тебя, насколько я вижу, есть конфликт этих двух целей — что-то реальное, что можно сделать завтра, и концепция, из которой нельзя ничего сделать завтра, если только не занимаешься опенсорсом себе в удовольствие.

Егор: Это твоя позиция, а вот, например, Антон antonarhipov Архипов написал в ревью, что задумался над тем, как его собственный код исправить.

Барух: Ха, ну ты привел пример, «код Антона Архипова»! Антон на данный момент — ведущий продакт-менеджер в ZeroTurnaround, и он не пишет код в продукт. Он не штатный программист. Он пишет много кода в опенсорсе, он делает кодревью, но это не тот человек, который пришел, надел наушники, хряпнул кофе, и до вечера у него восемь часов портянки кода выходят, который потом нужно тестировать, интегрейтить, ревьюить, поддерживать…

Егор: Ты вроде тоже не такой.

Барух: Я тоже не такой, но я ставлю себя на место программистов в команде, и я понимаю, что нет, я это никогда этого не сделаю. То, что я прочитал в книжке, это не просто прикольно, это супер-круто, причём, как по мне, самое крутое — это настолько непохоже на всё, что мы делаем и, тем не менее, имеет смысл. Но я почитал, я закрыл и меня это конечно обогатило, но ничего такого, что завтра я могу пойти и написать там нет, потому что книжка намекает, что это одна концепция, что это всё должно работать вместе, в отличие от разрозненных блог-постов. В этом есть прелесть, потому что ты построил общую концепцию, и в этом есть недостаток, потому что я не чувствую себя вправе взять один кусок, и проигнорировать остальное, я таким образом нарушаю концепцию, это неправильно! В блоге у тебя всё это отдельно, я захотел — согласился с null’ами, захотел — не согласился с сеттером. Книжка — это концепция. С концепцией я или соглашаюсь целиком, или нет.



Егор: Согласен, есть такая проблема. Но в блоге всё разрозненно, и были люди, которые говорили прямо противоположные вещи: ты вот нам рассказываешь про здесь какой-то кусок, здесь какой-то, а оно всё куда-то сведётся у тебя воедино? Что ты вообще думаешь про ООП, как должен вообще выглядеть объект, ты можешь хоть раз написать целый код? То есть люди искали какой-то целостности. Поэтому книжка суммирует.

Барух: В целостности есть безусловный плюс — из книжки мы понимаем, что такое «ООП от Егора». Но возвращаясь к твоей цели изменить разработчиков one step at a time — оно не там. И может быть нужно и то, и другое. И кажется в процессе этой беседы у меня появилось некоторое понимание, что для установления твоей credibility нужно, чтобы с одной стороны, люди узнали, что у человека есть концепция, книжку, в конце-концов написал, не проходимец, а с другой стороны, вот практические шаги, которые можно предпринять сейчас, если конкретно эти шаги вам подходят и нравятся… Вот тебе совет: берёшь эту книжку, которая концепция, и в конце каждого параграфа у тебя будет что-то типа: «Ребята, я понимаю, что у вас сейчас взорвётся мозг, и я понимаю, что вы не сможете это использовать завтра, а вот это вот, то что будет написано дальше — вот это сможете применить в коде без опасности быть убитым стулом на код ревью». Не просто ссылка на блог, а сформулированый practical advice на основе прочитанной главы. И тогда получается некоторая комбинация и целостной картины, и каких-то маленьких шагов, которые можно предпринять сегодня.

Егор: Это хорошая мысль, может быть, действительно так сделаю.

Барух: И вот тогда это, наверное, сводит две противоположные концепции.

Егор: Я согласен, я попробую это сделать. Может быть, не прямо в книжке, но мысль хорошая. У меня было много комментов к книжке, люди говорят «мало практических примеров про то, как нам жить». Ты вот взял и показал нам два класса, это интересно, но у нас класс на две тысячи строк, как шестнадцать строчек твоего класса перенести на наши огромные портянки кода. Есть такой concern.

Барух: Мне было бы интересно видеть не только второй том, но и второй revision первого. Какие будут сделаны выводы из первого тома, как это будет представлено. Вот эти практические советы — это то, чего мне очень не хватало в книжке: для меня она была абстрактным конём в вакууме и абсолютно мысленным экспериментом. И увидеть, как revision этой книжки изменит именно это, было бы интересно.

Егор: Буду работать.

Барух: Что ещё мы не обсудили? Какие планы на будущее?

Егор: Я буду на Java Day в Киеве, там будут два моих доклада, не касающиеся моей книжки, не касающиеся ООП, и discussion board как раз про ООП с вышеупомянутым Женей Борисовым. Я думаю, этой дискуссии многие ждут. На JPoint’е получилось что-то спонтанное, но была реакция достаточно агрессивная, и я был недостаточно подготовлен.

Барух: Вот да, это правильно, доклады по «твоему ООП» и по книжке должны быть дискуссионными, круглыми столами. Я очень рад, что в Киеве как раз такой формат выбрали.

Егор: Так в любом докладе они начинают со мной дискутировать на четвёртой минуте доклада!

Барух: Вооот. А тут у тебя как раз и будет «пять слайдов, а теперь давайте рубиться». И всё будет культурно, модераторы микрофоны носят, а не зоопарк.


Люди не понимают фундаментальных вещей, а без этого сложно что-то строить.



Егор: Мне ещё сложно презентовать на конференциях, потому что, когда читаешь всю книжку, то всё складно, а когда начинаешь кусок какой-то выдавать, то у меня не всегда хорошо получается. Перед тем, как научить чему-то, нужно научить чему-то ещё. Я пытаюсь рассказать про ORM, но для этого нужно рассказать вот это и вот это, а времени нет. Люди не понимают фундаментальных вещей, а без этого сложно что-то строить. Поэтому я не точно знаю аудиторию, насколько они готовы. Неплохой у меня доклад был, единственный, которым я был доволен — это было на Java Day в Минске, где я рассказывал про ООП в целом и приводил примеры. В нём было всё гладко, и вопросы были в тему, но это был последний мой доклад того турне. Когда говорю про практические вещи, про ORM, это беда уже.

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

Егор: Ещё у меня будет выступление на конференции Oredev в Швеции. Посмотрим, что Европа скажет, у меня ещё не было такого опыта. Я попытаюсь подготовиться, это будет та же тема, что и на JPoint’е, но я попытаюсь ёе сделать в формате дискуссии или короче. Но ты знаешь, европейская публика более пассивная, чем наша.

Барух: Северная Европа — тем более. В Швеции у тебя будет всё очень спокойно.

Егор: У нас прямо шквал вопросов, так и должно быть, да?

Барух: Конечно.

Егор: Для меня это было открытие. Ну и пишу второй том, не знаю, когда его закончу, но до нового года он точно выйдет. Там будет про ORM много, там будет про MVC — точнее, против них. Там будет про аннотации, про монады, про именование переменных и ещё про что-то. По главам пишу, сейчас ORM заканчиваю.

Барух: Спасибо огромное, увидимся.
Поделиться с друзьями
-->

Комментарии (314)


  1. lasalas
    01.09.2016 10:41
    -8

    Через 20 лет java и C++ будут восприниматься как сегодня Objective-C или Delphi — нагромождение нелепых пережитков.


    1. ARG89
      01.09.2016 10:49
      +6

      Через 20 лет Java будет 40 лет (как С++ сейчас), так что может быть и будет она живее всех живых. Правда у Java есть целый выводок перспективных JVM «детей», которые теоретически могут сократить ее ЖЦ.


    1. deniskreshikhin
      01.09.2016 11:20
      +2

      Я бы не был так категоричен в отношении Objective-C, это все-таки полноценный ООП язык, а C++ не совсем.


    1. hd_keeper
      01.09.2016 12:14
      +1

      Да они и сейчас уже…


    1. yegor256
      01.09.2016 18:23
      -1

      Я очень на это надеюсь


      1. franzose
        02.09.2016 04:41

        В том смысле, что всё будем писать на JS?


  1. qadmium
    01.09.2016 12:14

    На амазоне у Егора нет электронной версии книги, как так?


    1. ARG89
      01.09.2016 12:14

      Вопрос к yegor256


    1. phillennium
      01.09.2016 12:19

      «I'm not planning to turn this into an e-book, at least until the end of 2018. Mostly because I'm greedy. I realize that the moment I publish a Kindle version, it will be available for a free download somewhere» (со страницы книги)


      1. qadmium
        01.09.2016 12:25

        ога, спасибо, печально конечно, я бы для kindle купил даже по цене бумажной копии


    1. yegor256
      01.09.2016 18:24

      Электронной нет и, скорее всего, не будет. Бумажную можно купить либо на Амазоне, либо через мой блог с доставкой из Украины. Пишите не shop@yegor256.com


  1. qadmium
    01.09.2016 12:43
    +4

    я прочел первую статью про null из 2014 года, и я слабо понимаю чего это народ так наиндуцировался. По сути расписаны весьма очевидные вещи. Я не знаю как там в Java мире, но у нас в .net вещи примерно так и обстоят.

    BTW, оттуда же из статьи

    Iterator found = Map.search("Jeffrey");
    if (!found.hasNext()) {
      throw new EmployeeNotFoundException();
    }
    return found.next();
    


    имхо под этим куском кода маскируется желание использовать некий Optional<>, просто автор еще сам этого не понял ))


    1. bsideup
      01.09.2016 13:04
      +3

      Вообще, если говорить о Монадах, то List — это 0..n, а Optional — это 0..1, что хорошо объясняет попытку Егора использовать итератор.

      в Java 8, правда, Optional не следует этому на 100% и не предоставляет тот же набор API, что мы имеем для Stream API, из-за чего композиция Optional-ов например не возможна (в Java 9 добавили метод, но осадок остался)


      1. qadmium
        01.09.2016 13:16
        +1

        в догонку, это можно сделать и без null и всяких Optional/Nullable

        TValue GetValue(TKey key, Action onNotFound);
        


        return this.map.GetValue("Jeffrey", () => throw new EmployeeNotFoundException());
        


        1. bsideup
          01.09.2016 14:04

          Либо в языках, где есть Tuple-ы (как, например, 7ой шарп):

          (value: TValue, found: bool) GetValue(TKey key);
          


          (value, found) = this.map.GetValue("Jeffrey");
          
          return found ? value : throw new EmployeeNotFoundException();
          


          1. deniskreshikhin
            01.09.2016 15:33
            -1

            Или где функции могут возвращать множественное значение (https://play.golang.org/p/FcpXetR1SC):


                fruits := map[string]int{"apple": 100, "peach": 200}
            
                if fruit, ok := fruits["apple"]; ok {
                    fmt.Println("found", fruit)
                } else {
                    panic("can't found")
                }
            


        1. relgames
          01.09.2016 18:14

          В Java 8 можно сделать map.computeIfAbsent(«key», () -> throw new EmployeeNotFoundException());


          1. bsideup
            01.09.2016 19:07

            Не скомпилится если EmployeeNotFoundException checked


    1. yegor256
      01.09.2016 18:24
      -5

      Optional<> есть зло, ровно такое же, как и NULL. Он не решает проблемы, а лишь камуфлирует ее. В коментах к статье об этом есть.


      1. bsideup
        01.09.2016 19:12
        +2

        Вот только вариант из статьи с Iterator это, по сути дела, и есть Optional. Противоречите-с.


        1. yegor256
          01.09.2016 20:04
          -1

          «По сути дела» весь наш код это лишь буквы и символы) Это не «суть» дела, а ее полное игнорирование. Суть дела как раз в том, что мы должны иметь дело либо с объектом либо с ошибкой. Все остальные суррогаты только вредят, будь то NULL, Optional, Iterator, Collection, etc.


          1. TargetSan
            02.09.2016 13:17
            +1

            Использовать исключения для control flow кажется мне не лучшей идеей. Особенно если функция по своей семантике возвращает или значение, или "здесь такой не проживает". Для этого и служит Option.


    1. warlock13
      05.09.2016 23:31
      +1

      В статье про null написано, что null — это плохо, и в качестве хорошей альтернативы приведены два способа сделать всё ещё хуже (null object и кидание эксепшена). Если это впечатляет, то не в ту сторону.


    1. warlock13
      05.09.2016 23:37

      Точный аналог Optional в ООП — это контролируемые эксепшены.


  1. stfn
    01.09.2016 13:21
    +5

    Иисусе, Кремниевая долина, кремниевая!


    1. jbaruch
      01.09.2016 18:12
      +1

      мы в курсе, что кремний для процов, а не силикон для сисек, чесслово. К сожалению, устоявщееся название региона это "Силиконовая Долина".


      1. lany
        02.09.2016 05:17
        +5

        Так было лет 10 назад. Сейчас всё же грамотность побеждает. Это вы там в эмиграции отстаёте от российских трендов ;-)


        1. Shamov
          02.09.2016 15:24
          +2

          По-русски правильными будут оба варианта. В зависимости от того, что ты хочешь сказать. Слово «силиконовая» несёт в себе важную смысловую коннотацию, связанную с сиськами. Что бы ты не назвал «силиконовым», сразу возникает ассоциация с раздутыми сиськами и одновременно подгружается некоторый контекст, в котором раздутые сиськи принято осуждать, а тех, кто придаёт размеру сисек такое большое значение, — презирать. Так что если ты просто хочешь обозначить географическое место, то лучше говорить «кремниевая». Если же ты хочешь добавить немного иронии, то надо говорить «силиконовая», подразумевая тем самым, что на уровне пиара значимость этого места сильно преувеличена… как и привлекательность силиконовых сисек для истинных ценителей.


        1. jbaruch
          02.09.2016 18:08
          +1

          Википедия всё еще перебрасывает "Кремниевую" на "Силиконовую".


    1. yegor256
      01.09.2016 18:25
      +1

      И не Иисусе, а Иисус.


      1. deniskreshikhin
        01.09.2016 18:32
        +2

        Звательный падеж же. Аналогично "О Боже!", а не "О Бог!"


        1. yegor256
          01.09.2016 18:41
          +1

          Тогда «О, Егоре» стало быть?


          1. deniskreshikhin
            01.09.2016 19:01
            +8

            Нет, не стало быть. Правильно было бы "О, Георгий!". Т.к. Егор это современное имя, и нельзя сказать как бы оно звучало на старославянском.


            В русском языке славянизмы (заимствования из старославянского), играют такую же роль как латинизмы в английском. Вы же не исправляете своих американских коллег, когда они говорят data, а не datums.


            Ведь единственное число от data это datum, поэтому с точки зрения английской грамматики правильно было бы говорить datums. Но на латинизмы правила английского языка не распространяются. Точно так же правила русского языка не распространяются на славянизмы.


            Поэтому для выражения восклицания форма "Иисусе" обоснована, т.к. является славянизмом, а употребление "О Егоре" не обосновано, т.к. этот вариант имени не является славянизмом. Имя вполне себе современное.


            1. yegor256
              01.09.2016 19:28
              +3

              Убедил)


  1. relgames
    01.09.2016 13:26
    +3

    Вот он говорит:

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

    Но не ясно — нравится ли ему тот код, который он пишет «правильно»? Дальше он упоминает, что концепция in progress, что код, ушедший в продакшн, уже не такой «правильный». То есть я не вижу каких-то радикальных плюсов по сравнению с другими концепциями.

    Каков вообще средний возраст его проектов? Если они пишут под заказ, то, я предполагаю, нет долгоживущих проектов. Тогда да, можно нагородить «ООП от Егора» и забыть, а в следующей проекте уже будет «ООП 2.0 от Егора», и так далее.

    Есть ли у него код, которому, скажем, 5, 10 лет, и он ему все еще нравится? Есть ли реально большие и долгоживущие проекты, в котором «правильное ООП» показало себя на практике? Ну чтобы все было покрыто тестами, чтобы можно было спокойно менять устаревшие куски, чтобы глаза не болели? Как по мне, это недостижимый идеал.


    1. yegor256
      01.09.2016 18:27
      +2

      Да, нравится. Тот код, который мы пишем сейчас, мне (и нам) нравится. Вот например наш web framework: https://github.com/yegor256/takes Он весь написан руководствуясь именно теми принципами, которые описаны и на блоге и в книжке. Средний возраст наших проектов на настоящий момент два года. Реально больших проектов (5-10 лет) у нас пока нет. Всем этим идеям, о которых и книга и блог, всего года четыре. И таки да, все покрыто тестами. Посмотрите Takes Framework.


      1. relgames
        01.09.2016 19:04

        Понравился малый размер классов. Некоторые вещи режут глаз.

        Однако же мне это сильно напоминает мир Scala (не код, но, скажем, отличие от традиционного мира Java).
        Свидетели Scala тоже говорят, что у них золотая таблетка, правильное ФП и вообще рай. Однако там точно такие же проблемы: высокий порог вхождения, сложность с поиском людей, сложность с чтением кода.


        1. yegor256
          01.09.2016 19:29

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


          1. relgames
            01.09.2016 19:35

            Для меня takes тоже не сильно читаем :) Дело привычки.

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


            1. sshikov
              01.09.2016 22:27

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


              И таки да, все покрыто тестами

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


              1. G-M-A-X
                02.09.2016 00:38

                +1
                Тесты не гарантируют, что багов нету.
                Разве показывают, что что-то сломалось при изменении. Но скорее всего это сломался сам тест, так как он не ложится на измененный код. :)


                1. sshikov
                  02.09.2016 11:01

                  Так о том и речь. Тесты в общем случае не гарантируют. Поэтому стремление покрыть все тестами зачастую вызывает подозрение, что тут что-то не так. А если это цель фреймворка, то...


          1. Source
            01.09.2016 21:57
            +3

            современный код на Java это почти всегда нечитаемый мусор.
            Ну это by design xD
            “If Java had true garbage collection, most programs would delete themselves upon execution.”
            — Robert Sewell


            1. MacIn
              01.09.2016 22:13

              Что в Java является наиболее нечитаемым? Из академического интереса спрашиваю.


              1. Source
                01.09.2016 22:50

                Не думаю, что можно выделить что-то одно. Весь язык заслоняет собой программу и чтобы увидеть смысл написанного приходится продираться через бесконечные нагромождения синтаксиса, неуместных абстракций и т.д.
                Конечно, к этому можно привыкнуть и даже начать считать удобным, если достаточно долго себя в этом убеждать… только какой в этом смысл?


                1. poxu
                  02.09.2016 16:59

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

                  А про какой язык так сказать нельзя?


                  1. MacIn
                    02.09.2016 18:20

                    Про машинный язык.


                  1. Source
                    02.09.2016 22:15
                    +1

                    Да про многие так нельзя сказать… Дальше всех к дзен продвинулись Lisp и SQL.
                    Кроме них, на мой взгляд, хорошо сбалансированы Ruby, Elixir, Smalltalk, F#… Да даже C# тут Java явно обходит, начиная с 3-й версии.


              1. Flammar
                08.09.2016 15:35

                Для меня, среди прочего, нагромождение логики обработки исключений.


                1. MacIn
                  08.09.2016 16:08

                  Можно пример кода?


      1. onikiychuka
        01.09.2016 20:21
        +8

        Посмотрел, ужаснулся именоваю классов, закрыл.

        public final class App {
          public static void main(final String... args) {
            new FtBasic(
              new TkFork(
                new FkRegex("/robots.txt", ""),
                new FkRegex("/", new TkIndex()),
                new FkRegex(
                  "/xsl/.*",
                  new TkWithType(new TkClasspath(), "text/xsl")
                ),
                new FkRegex("/account", new TkAccount(users)),
                new FkRegex("/balance/(?<user>[a-z]+)", new TkBalance())
              )
            ).start(Exit.NEVER);
          }
        }
        

        FtBasic — что это???
        TkFork — что это???
        Что такое Ft или Tk? Зачем эти префиксы из аббревиатур?
        Этот код читаем только потому что там есть пути к ресурсам. Количество WTF на момент прочтения readme зашкаливает. Я очень надеюсь что мы не будем писать код с таким именованием классов больше никогда.


        1. r0zh0k
          03.09.2016 21:05
          +1

          TkFork это Takes Fork, вероятно какая-то штука из фреймворка Takes которая что-то обрабатывает.
          Fk это скорее всего Fake, по крайней мере так именовано в других проектах.

          Еще есть например Comment и DyComment – это коммент в DynamoDB (реализация).

          На самом деле названия очень нормальные, просто нужно иметь конвенцию. Вот меня раздражает стандартная многословность Java и необходимость все свои классы называть DynamoUser, PostgresUser и так далее. А тут DyUser, PgUser – все четко.

          Upd: ой, ниже уже все ответили…


          1. onikiychuka
            05.09.2016 12:42
            +3

            Я всетаки отвечу.
            Вот пришел я к вам в команду и вижу что вы используете DyUser. Это DynamicUser ( ну какой-то может быть очень активный) или DynamoUser — структура записи пользователя в DynamoDB? Часто бывает что из контекста это не понятно. В лучшем случае — я час проведу изучая код и пытясь понять что такое Dy, в худшем — пойду пытать вас. А у вас релиз завтра и пара противных багов висит. Но это еще «хорошие обревиатуры». Предположим что у нас есть еще бизнес обьекты типа Route и класс DyRoute — и это как раз тот самы Dynamic Route — он вообще относится к инфраструктуре и определяет куда нужно сейчас оправлять ваш запрос в зависимости от загрузки нижележащих сервисов. И ваще жопа — тк какого художника одна и таже обревиатура в разных кусках одного проекта означает соовсем не связанные между собой вещи.
            Когда я был маленький, деревья большие и code-competion был только в emacs и контекстный — тогда сокращения имели смысл. На текущем витке развития software development — это примерно такой-же атавизм как и Go-To. Лучше про него просто забыть.
            PS: Я не считаю что имена классов, обьектов или методов должны быть длинными. Совсем наоборот — они должны быть максимально корткими — но при этом читаемые. Такая вот задача минимизации — как не выплеснуть ребенка читаемости вместе с водой.


            1. r0zh0k
              05.09.2016 13:45

              Вам надо еще почитать как люди «приходят в команду» к Егору и как они «пытают». Там все схвачено :)


      1. sentyaev
        02.09.2016 02:01
        +3

        Вот я когда пишу код, думаю о тех кто это потом будет читать.

        Как там понять что такое Fk, Tk, Fb, Xe? A RsXembly, что такое xembly?
        Rs и Rq — догадался, но почему нельзя было написать Request, Response?


        1. lany
          02.09.2016 05:27

          У Егора есть целая заморока насчёт длины идентификаторов. Он в стопятом про это говорил. Мол, поля не длиннее восьми символов, хардлимит. Про классы, наверно, тоже такое есть.


          1. sentyaev
            02.09.2016 11:29
            +2

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


            1. MacIn
              02.09.2016 13:56

              Нет, ну возможен компромисс. У нас в коде тоже иногда приходится сокращать для повышения читаемости. Обычно эти сокращения расшифровываются в месте объявления в комментарии. Просто когда идентификатор такой длины, что невозможно написать в одну строку что-то вида a.push(b.pop), когда a и b длиной в пол-экрана — это тоже плохо.
              Потому что альтернатива —

              a.push(
                  b.pop)
              


              А это ужас.


              1. sentyaev
                02.09.2016 14:18

                У нас в коде тоже иногда приходится сокращать для повышения читаемости.

                Это понятно, тут вы говорите об исключениях из правил. Я не хочу тут говорить вам, что можно придумать более информативные имена для «a» и «b», тк не знаю контекста.

                Посмотрев же на Тakes Framework, я увидел, что эти странные именования используются повсеместно.


                1. MacIn
                  03.09.2016 15:29

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

                  Это условные обозначения, мне было лень придумать примеры.
                  Допустим, это было бы что-то типа
                  TConList = class //TConnectionList
                  или 
                  lFIdx: integer; //lFirstElementIndex;
                  


                  1. sentyaev
                    03.09.2016 15:35
                    +1

                    С появление intellisense я перестал думать о длинне имен и стараюсь писать читаемый код. Т.к. даже я сам через месяц с трудом вспоминаю такие аббревиатуры. Но возможно это у меня просто память короткая.


                    1. MacIn
                      03.09.2016 15:43
                      +1

                      С появление intellisense я перестал думать о длинне имен и стараюсь писать читаемый код

                      Когда код не влазит в строку, и приходится его бить на несколько — это не сильно добавляет читаемости.

                      Условно говоря,
                      lItem := lItem + some_func() + other_func();
                      

                      лучше, чем
                      lSomeListItemWithNiceJavaStyleName := 
                      lSomeListItemWithNiceJavaStyleName +
                      SomeFunctionGivingResultWithNicejavaStyleName() +
                      OtherFunctionGivingResultWithNicejavaStyleName();
                      


                      1. sentyaev
                        03.09.2016 16:05

                        OtherFunctionGivingResultWithNicejavaStyleName();

                        Вот отличный пример такого: FizzBuzzEnterpriseEdition

                        А вообще, именование — это на самом деле довольно не просто.

                        Вот например ваши ConnectionList и FirstElementIndex.
                        Если бы я использовал FirstElementIndex только внутри List, скорее я бы назвал его просто «first».
                        Если бы он был частью публичного интерфейса List, то назвал бы FirstElementIndex.

                        Я же изначально писал, все очень зависит от контекста и домена.


                        1. MacIn
                          03.09.2016 16:37

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

                          Если бы я использовал FirstElementIndex только внутри List, скорее я бы назвал его просто «first».

                          Здесь есть некоторая порция неоднозначности, потому что непонятно, индекс ли это, итератор ли, или сам элемент. Более того, непонятно даже, переменная ли это или формальный параметр. А уж в Delphi, на котором мне выпало сейчас писать, и вовсе может быть property объекта.


          1. chabapok
            03.09.2016 10:19
            +3

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

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


            1. exvel
              03.09.2016 15:16

              Там автор сеттеры и геттеры вообще в любом виде не любит. Встроены они в язык или нет.
              P.S. Минус мой. Промахнулся. Простите.


            1. sentyaev
              03.09.2016 15:32
              +1

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


          1. Flammar
            08.09.2016 16:19

            Лучше не 8, а 9. У швейцарского заказчика фирмы, где я работал 9 лет назад, было де-факто правило трёхбуквенности: все слова в идентификаторах и наименованиях сущности и поля сокращались до трёх, в редких случаях шести букв. Это было в общем удобно, хотя некоторые вещи надо было специально запомнить, но их было мало. Две бкувы — это, конечно, маловато.

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

            К наименованиям полей и интерфейсных методов сокращение лучше, конечно, не применять.


      1. webkumo
        02.09.2016 13:09
        +1

        Простите, что это:
        https://github.com/yegor256/takes/blob/master/src/main/java/org/takes/Take.java
        Response act(Request req) throws IOException;

        Глагол в качестве имени класса? Я не сталкивался в литературе с take в форме существительного (хотя гугл-транслейт говорит, что таковое значение есть).
        Действие «act»??? Что за хрень? Никак не получилось сделать нормальное имя действия?

        https://github.com/yegor256/takes/blob/master/src/main/java/org/takes/misc/EnglishLowerCase.java
        public String string()

        Что за действие «string»?
        Почему имя класса — какое-то действие/состояние, а не объект-субъект?


        1. MacIn
          02.09.2016 13:58

          Зачем вам гуглтранслейт, когда вы ищете перевод слова?
          http://www.multitran.ru/c/m.exe?CL=1&s=take&l1=1


          1. webkumo
            02.09.2016 14:14

            Гуглтранслейт универсален и знаком, раньше использовал яндекс.словари, но они закрылись… спасибо за интересную ссылку… А есть такое же, но больше с пояснением смысла (меньше вариантов, но с попыткой определения) и с примерами использования для каждого варианта? Сгодится и на английском языке…


            1. paolo77
              02.09.2016 18:53

              https://www.lingvolive.com/en-us/translate/en-ru/take
              Это те же Яндекс.Словари


  1. qadmium
    01.09.2016 14:06

    Едем дальше, в статье про геттеры/сеттеры вообщем то тоже ничего нового. Даем собаке мяч, а не устанавливаем его.

    Чем это отличается от rich model? переименовали сеттеры? А что нам делать с DTO?


    1. xotey83
      01.09.2016 14:26

      Почитал блог Егора. Он пишет, что DTO — гадость.


      1. relgames
        01.09.2016 14:36

        А можно ссылку?


        1. qadmium
          01.09.2016 14:48
          +1

          видимо вот это — http://www.yegor256.com/2016/07/06/data-transfer-object.html


          1. qadmium
            01.09.2016 15:14
            +1

            и как то там весьма, кхм, как бы это сказать. Вообщем-то все то же, что можно увидеть в книжках критикуемого фаулера ))
            И очевидно предлагается научить обьект загружаться/сохраняться в базу/json/… минуя DTO


            1. relgames
              01.09.2016 15:35
              +1

              Получается, вот так плохо:

              Book book = api.loadBookById(123);
              database.saveNewBook(book);
              

              А так хорошо:
              Book book = api.bookById(123);
              book.save(database);
              

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

              Конечно, если бы это был реальный мир, то книгу на полку ставил бы человек. Или робот :)
              Тогда следует писать
              bookManager.saveToDb(book, db);
              

              Что логически приводит к ORM системам :)


              1. qadmium
                01.09.2016 15:41
                +2

                Что логически приводит к ORM системам :)


                ORM низя — http://www.yegor256.com/2014/12/01/orm-offensive-anti-pattern.html


                1. relgames
                  01.09.2016 15:57
                  +1

                  Я в курсе, это я так типа пошутил :)


                1. Flammar
                  05.09.2016 14:07

                  Спасибо за ссылку.


              1. zzashpaupat
                01.09.2016 15:42
                +2

                Разница в том, что вы не уважаете объект :)


                1. qadmium
                  01.09.2016 15:46
                  +1

                  но когда к нему слишком много уважения, он, очевидно, начинает нарушать SRP )


                1. relgames
                  01.09.2016 15:58
                  +1

                  Я очень уважаю инстанс HibernateSession! Это ведь тоже объект! :)


              1. qadmium
                01.09.2016 15:51

                основной посыл в этих двух примерах, как я понял, что в первом случае мы получаем DTO из api и чего-то там с ним делаем, а во втором у нас уже появляется entity, которая обладает поведением и всем таким, что присуще rich model. Нууу… как бы да, хорошо, а где ООП v2?


                1. relgames
                  01.09.2016 16:01

                  А почему книга должна обладать поведением «сохраниться в базу»? Single responsibility principle хоть Егор не отменил еще своим божественным указанием? :)


                  1. qadmium
                    01.09.2016 16:26
                    +1

                    ну про SRP я выше написал


                    1. VolCh
                      02.09.2016 07:39
                      +1

                      ActiveRecord криминален по SOLID


                  1. qadmium
                    01.09.2016 16:56

                    как бы ничего особо криминального в этом нет, это банальный active record


                    1. relgames
                      01.09.2016 17:48
                      +1

                      Конечно, криминального нет. Я же не пророк нового ООП.


                      1. VolCh
                        02.09.2016 07:39

                        А также о формате сериализации.


                  1. MacIn
                    01.09.2016 17:56
                    +1

                    Логично было бы иметь универсальное data = book.serialize; и database.saveserialized(data, booktype); Или сразу наследовать объект от serializable и передавать его базе. Действительно, нафига козе баян объекту что-то вообще знать о базе данных?


                    1. relgames
                      05.09.2016 14:51

                      Но тогда базе придется знать внутренний формат сериализованной data, что в принципе не сильно отличается от DTO.


                      1. MacIn
                        05.09.2016 17:57

                        Это почему еще? Blob как есть.


                        1. relgames
                          06.09.2016 12:44

                          А как мапить на колонки в таблицах? Или просто blob хранить?


                          1. MacIn
                            07.09.2016 18:06
                            -1

                            А зачем мапить на колонки в таблицах? Просто blob.
                            Это у товарищей АИС-программистов профдеформация — привычка раскидывать через ORM всякие таблицы вида «сотрудники», где все по колонкам разбито. А зачастую нужно просто хранить сериализованные объекты. У нас в системе, например, в виде сериализованных объектов хранятся всякие user-specific настройки для разных модулей.


                            1. sentyaev
                              07.09.2016 19:37
                              +1

                              А искать по блобам как?


                              1. MacIn
                                07.09.2016 22:52
                                -1

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


                                1. sentyaev
                                  07.09.2016 23:24

                                  Про «book» же говорили.
                                  Вот есть у вас библиотека, допустим большая.
                                  Как выбрать все книги по автору, или по названию, или еще по какому критерию.

                                  Просто если хранить «user-specific настройки», то проблем нет по userId достать можно, тут все просто.
                                  А вот например с users уже врятли прокатит.


                                  1. MacIn
                                    08.09.2016 16:11

                                    Извините, ветка большая. Я вне контекста писал — как раз сейчас с теми самыми настройками работаю.


                                    1. sentyaev
                                      08.09.2016 17:04

                                      Ничего страшного.

                                      Вот вы писали выше:

                                      Логично было бы иметь универсальное data = book.serialize; и database.saveserialized(data, booktype);


                                      Как я понял «data» — это бинарные данные (или может быть строка, не суть).
                                      Сохранить данные в таком виде, да, очень просто.
                                      Но как потом искать или обновить записи?
                                      Я просто не вижу хорошего решения.


                                      1. MacIn
                                        08.09.2016 18:24

                                        Если для книги, то да, больше orm с маппирование объекта на таблицу подойдет, где мы можем выборку по индексу сделать. Иначе придется ряд параметров, которые попадают под сериализацию, дублировать в виде колонок, а это слишком жирно.
                                        Когда я писал о book.serialize я не думал о книге; ветка, в которой я писал, была об, условно, «сохранении объекта в базу данных» и я думал об этом в контексте своей текущей задачи, которая — о сериализации объекта и передаче по сети и/или сохранении в БД. Так что приношу извинения за не совсем корректный комментарий, написанный для иного контекста.


              1. Flammar
                05.09.2016 14:16
                +1

                book.save() — это будет ActiveRecord, что, по крайней мере для языков со статической типизацией, давно признано антипаттерном.

                bookManager.saveToDb(book, db);
                Если db инкапсулировать в bookManager (например, через «фабрику»), то будет как раз тот подход, что применяется сегодня в использовании ORM.


                1. relgames
                  05.09.2016 14:51

                  давно признано антипаттерном

                  Подскажите, где про это почитать?


                  1. Source
                    05.09.2016 19:14
                    +1

                    Да, если я ничего не путаю, ещё в первоисточнике (PoEAA) было примечание, что Active Record нарушает SRP и не рекомендуется использовать его в случаях сложнее, чем тривиальные.


    1. yegor256
      01.09.2016 18:28

      Про DTO нам придется забыть.


      1. relgames
        01.09.2016 18:55

        Но тут же DTO таки используется! https://github.com/yegor256/takes/blob/master/src/main/java/org/takes/Take.java
        И получается, Request это лишь контейнер для данных. Почему он наружу свои данные выставляет? Это же нарушение инкапсуляции! :)
        Вместо того, чтобы писать request.respond(outputStream), тут введен некий конвертер :)

        Граница инкапсуляции есть всегда. И DTO есть в реальном мире (например, всяческие анкеты, фотографии, записи).


        1. yegor256
          01.09.2016 19:30
          +4

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


  1. PerlPower
    01.09.2016 16:46
    +20

    Кто все эти люди? Почему их междусобойчик со стенограммой находится здесь?


    1. sergof
      01.09.2016 17:03
      +2

      какие то новые свидетели


    1. yegor256
      01.09.2016 18:29
      -3

      Это лучший комент! Жаль не могу апвоут его, кармы не хватает)


    1. guai
      07.09.2016 12:37
      +1

      Один из них точно — д'Артаньян


  1. TimeCoder
    01.09.2016 16:52
    +2

    Почему-то сразу вспомнил тред про то, что язык Си — шутка (http://www.linux.org.ru/forum/talks/284934)

    По статье: неприятное впечатление производят высказывания. То у них гадость, это — плохо, то — неправильно, се — неправильно. Очередная песня в стиле «крах ООП, победа ФП». А как правильно?
    Software development — это инженерная наука, где практика — главный критерий. Что конкретно они сделали? Если своими эпатирующими провокационными заявлениями они выступают против ряда повсеместно используемых в современной разработке вещей — пусть покажут, как надо. Где их мега-крутой проект, супер-чистый код с джедайским подходом и космической производительностью? Если их подход — работает, почему они ездят по конференциям, а не создают стартап, который за несколько дней привлечет миллионы инвестиций? Заявлять можно много чего, пиар и коммерция это все…


    1. ARG89
      01.09.2016 17:10

      Ну собственно yegor256 в своих проектах пишет код в соответствии с описанными в статье принципами. Он как-то даже давал ссылки на github.


      1. TimeCoder
        01.09.2016 17:42
        +3

        Хорошо, но каков результат? Задачи стали решаться в 2 раза быстрее? Код сократился на 50%? Количество багов уменьшилось в разы? Если нет, то это разговоры о стиле, ничем не отличающиеся от того где ставить открывающую скобку. Вопрос удобства и соглашения. А замах в статье, словно новую парадигму придумали. Более того: даже если бы и придумали, ее эффективность нужно доказать. Уже много лет я слышу от одного знакомого, что ФП позволяет решать те же задачи в разы быстрее и с минимумом кода. Годы идут — но все (кроме гиков и некоторых стартапов) пишут на ООП. Ругают сам ООП, его последователей (мол, вы просто неспособны иначе мыслить, ФП освободит ваш разум..). Годы идут. Но мы же все тут понимаем, что разработка во многом движется бизнесом? Если бы ФП, или подход из данной статьи давал бы хотя бы 1% прироста скорости/качества/производительности — он бы быстро вышел на мировой рынок разработки, потому что 1% от этого рынка — это миллиарды долларов экономии (а значит прибыли). Рассуждаю, как торгаш сейчас, но увы, таковы реалии. Делать что-то потому что «это просто круто» (например, использовать git вместо svn) — трата времени и сил. Не все себе могут это позволить. Должен быть реальный результат, хотя бы в перспективе. А ругатели ООП тратят на это время уже не одно десятилетие.


        1. yegor256
          01.09.2016 18:32
          +1

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


          1. TimeCoder
            01.09.2016 19:29
            +2

            В каком формате мир завоевали сделанные на коленке Python, PHP, MySQL? Это происходит естественным путем, так что время само покажет.


            1. yegor256
              01.09.2016 19:31
              +1

              И Вам нравится тот мир, который они завоевали? Точнее, нравится то, во что они превратили мир?


              1. TimeCoder
                01.09.2016 21:00
                +1

                Не очень. Многие тривиальные и интуитивно понятные вещи до сих пор в мире программирования делаются тяжело. Есть ощущение, что что-то не так. Но вот тот код в комментариях ниже, с функцией max — точно не улучшит ситуацию.


                1. yegor256
                  01.09.2016 22:43
                  +1

                  А что улучшит, как думаете?


                  1. TimeCoder
                    01.09.2016 22:59

                    Не думал над этим. У меня нет цели изменить мир программирования, для меня это лишь инструмент для решения совершенно иных задач.


                  1. Source
                    01.09.2016 23:25
                    +2

                    Улучшат языки, которые перестанут тянуть идею «всё есть объект» куда не надо… Объектами останутся только те части программы, которые действительно обладают своим поведением и полностью изолированы от остальной программы. Между собой они будут общаться исключительно отправкой сообщений. А само поведение объекта будет реализовываться декларативно (в функциональном и/или логическом стиле).


                    1. yegor256
                      01.09.2016 23:55
                      +1

                      А что такое «части программы, которые действительно обладают своим поведением и полностью изолированы от остальной программы»? Это что-то новое, пока нами не открытое? Почему эти части сейчас не являются объектами и счастье еще до сих пор не наступило? Что мешает?


                      1. Source
                        02.09.2016 09:43

                        Это уже есть, посмотрите на Erlang или Elixir, там это процессами называется, но по сути это и есть настоящие объекты.
                        Я уверен, что через 20 лет все актуальные ЯП (кроме самых low-level) будут придерживаться аналогичных подходов, потому что это позволит эффективно использовать все 1024 ядра (ну или сколько тысяч их там будет к тому времени) и управлять сотнями компонентов умного дома из одной программы.


                    1. MacIn
                      02.09.2016 14:02
                      +1

                      которые перестанут тянуть идею «всё есть объект» куда не надо…

                      Действительно. ООП — это лишь метод, способ работы с данными. Есть ситуации, где это оправдано, есть, где нет. Где нет внутреннего состояния, где слои абстракции только скрывают суть действия ничем не помогая.


    1. yegor256
      01.09.2016 18:31
      -1

      Вот один из наших мега крутых проектов с джедайским подходом: https://github.com/yegor256/takes Про производительность говорить не буду, мы о ней речи не ведем и за нее не боремся. Но в области ООП этот проект сделан неплохо. Значительно лучше чем весь тот мусор, который сейчас доминирует на рынке: Spring, Hibernate, и прочие. На счет стартапа мысль правильная — мы создаем стартап. На счет миллиона инвестиций, мы в процессе, следите за новостями )


      1. sentyaev
        02.09.2016 02:17

        Web Framework и вы не боретесь за производительность?
        Да и когда вы называете решения проверенные годами и тысячами проектов — мусором… Это не профессионально.


        1. yegor256
          02.09.2016 02:28
          -1

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


          1. sentyaev
            02.09.2016 02:55

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


            1. yegor256
              02.09.2016 03:04
              +3

              Android SDK рекомендует использовать статические методы и не использовать объекты. Стоит ли эту рекомендацию принимать как правильный стиль в ООП? Не будет ли правильнее считать частный конкретный случай просто временным затруднением аппаратной части? То же самое и у нас. Да, Java не умеет работать быстро с большим числом объектов. Она куда быстрее работает со статическими методами. Это беда Java, а не ООП. Придет время и место Java займет другая платформа, где ООП сможет работать правильно и красиво. И там не будет статических методов. Я предлагаю подумать об этой платформе уже сейчас. А еще почитайте вот это.


              1. sentyaev
                02.09.2016 03:36

                Я бы посмотрел на прототип такой платформы.


                1. yegor256
                  02.09.2016 03:40
                  +1

                  Я бы тоже. Вот так я ее описал три года назад.


  1. qadmium
    01.09.2016 17:45
    +10

    Вообщем заголовок меня заинтриговал, а в этом увлекательном разговоре нет возможности ознакомиться с позицией
    Егора, потому что тут больше про борьбу с оппонентами, чем про ООП. Возможности купить книгу в электронном варианте тоже нет,
    поэтому пришлось собирать целостную картинку из записей в блоге, а не из книги.

    Итак нам обещают ООП 2.0

    1) Why NULL is Bad?
    «null плохой». ок, но мы это уже давно знаем. эта тема обсосана со всех сторон.

    2) Getters/Setters. Evil. Period.
    «get/set плохо». суть статьи — вместо процедурного барахла, используйте ООП

    3) Data Transfer Object Is a Shame
    «DTO плохо» взамен предлагается переложить сериализацию/десериализацию на саму сущность, минуя DTO

    4) ORM Is an Offensive Anti-Pattern
    «ORM плохо» взамен предлагается active record и репозитарий для бедных

    5) Objects Should Be Immutable
    «all classes should be immutable in a perfect object-oriented world». эта тема обсосана со всех сторон.

    6) OOP Alternative to Utility Classes
    «Utility классы зло, каждому методу по обьекту». И такой код я тоже видел.
    аргументы: SRP, удобнее писать тесты, «An object-oriented approach enables lazy execution». весьма слабо.

    7) If-Then-Else Is a Code Smell
    if — зло, vrtual dispatch — добро. где-то я это уже видел. может у Фаулера/Физерса/Кириевски?

    8) Singletons Must Die
    синглтоны зло.

    9) Class Casting Is a Discriminating Anti-Pattern
    cast зло

    10) Composable Decorators vs. Imperative Utility Methods
    Why Many Return Statements Are a Bad Idea in OOP
    Разложим мир на микроскопические обьеты.

    Итого: Либо банальные вещи, либо маргинальные экстремистские идеи. Так мы будем писать через 20 лет?


    1. relgames
      01.09.2016 17:51
      +3

      Так мы будем писать через 20 лет?

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


    1. MacIn
      01.09.2016 18:08
      +14

      Мда.

      This is a classical example:
      
      public int max(int a, int b) {
        if (a > b) {
          return a;
        }
        return b;
      }
      


      И пример «хорошего подхода»:
      This is the code in a pure object-oriented world:
      
      public int max(int a, int b) {
        return new If(
          new GreaterThan(a, b),
          a, b
        );
      }
      

      What do you think now?

      Ай финк нау, что это воняет за километр и двухметровой палкой это трогать нельзя. Нельзя гордиться тем, что ты навернул 4 абстракции вместо одной стандартной конструкции. Это технопорно вида «смотри, как я умею» — интересно, но непрактично и нечитаемо. Судя по всему, остальные предложения такие же гениальные.


      1. MacIn
        01.09.2016 18:27
        +2

        Прошу прощения у автора за резкость тона, вспылил. Сильно удивило «предложение о рационализации».


        1. yegor256
          01.09.2016 19:33

          Прощения просить не нужно, это вполне нормальна и типичная реакция. Прочитать стоит книгу целиком, станет понятно о чем это все и для чего.


          1. guai
            07.09.2016 12:49

            Купить и потом сжечь?
            А вы хитрец!


            1. webkumo
              07.09.2016 13:37

              А почём растопка продаётся?


              1. guai
                07.09.2016 14:28

                https://www.amazon.com/gp/product/1519166915/ref=as_li_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1519166915&linkCode=as2&tag=yegor256com-20&linkId=RMGEO4ESPM4CGD3O


        1. Bonart
          02.09.2016 00:28

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


      1. Source
        01.09.2016 21:46
        +3

        This is the code in a pure object-oriented world:
        public int max(int a, int b) {
          return new If(
            new GreaterThan(a, b),
            a, b
          );
        }
        
        Такие примеры кода просто показывают полное непонимание сути ООП и для чего вообще нужна эта парадигма. Недавно обсуждали ООП вдоль и поперёк, начиная от самых истоков и заканчивая практической пользой в настоящем, не охота повторяться…
        Вот тут дело было.


      1. kanu
        02.09.2016 13:42

        new GreaterThan(a, b)
        

        Интересно, а yegor256 смотрел scala? Там как раз сделано гораздо более ООПшно:
        a.<(b)
        


    1. yegor256
      01.09.2016 18:34
      -2

      Спасибо за подборку! Да, я надеюсь, что так мы будем писать через 20 лет. На самом деле, раньше. Уже сейчас так пишут многие, не я один. И если это банальные вещи, то можно посмотреть на Ваш код, где все эти вещи реализованы? Можно увидеть, скажем, 5000 строк Java кода без NULL?


      1. qadmium
        01.09.2016 18:55
        +5

        И если это банальные вещи, то можно посмотреть на Ваш код, где все эти вещи реализованы?

        вы этого не увидите, потому что я не согласен с вами полностью ни по одному из этих пунктов.
        Более менее я стараюсь избавляться от проверок аргументов на null, это решается при помощи code contracts. null как результата функции тоже надо избегать, но все хорошо в меру.
        Синглтон решается любым DI фреймворком. И то, пока проект маленький я даже и не подумаю что-то делать в этом направлении, у меня мало времени на перфекционизм
        Immutable? все хорошо когда, у тебя value object, но как entity может быть immutable?

        Можно увидеть, скажем, 5000 строк Java кода без NULL?

        ну если бы вы читали мои комментарии, то знали бы что я пишу не на яве )) а в дотнете с этим попроще


        1. qadmium
          01.09.2016 18:58
          +4

          Да, я надеюсь, что так мы будем писать через 20 лет. На самом деле, раньше


          серьезно, вы правда думаете, что все будут делать так

          return new If(
              new GreaterThan(a, b),
              a, b
            );
          


          ?


          1. yegor256
            01.09.2016 19:34
            -2

            Я в этом убежден.


            1. mezastel
              01.09.2016 20:33
              +13

              Да ну, нет же. Никаким образом. Вы вместо того чтобы пару тройку инструкций воткнуть начинаете аллоцировать на управляемой куче. А вы не думали что будет если этот код часть итеративного алгоритма, запускается он 100500 раз? Ну тут и даже не по перформансу вопрос, а по логике вещей. Программирование — это математизация природы, а не ее антропоморфизация. Что нам дает одна точка выхода? Вот если бы вы писали статический анализатор — да, возможно это лучше. Но если нет, то вы рискуете превратить весь код в один цепочный fluent вызов, и ради чего? Where's the beef?


              Скажите, а вы вот реально поставляете вашим заказчикам такой код? Это я к тому, что будь я вашим заказчиком то я бы, как вы в вашем подкасте и намекаете, справедливо задал бы вопрос "какого… вы мне код обфусцируете?" и ушел бы прямехонько к вашим конкурентам, рассказав им по пути о ваших протекционитстких практиках который сводят на нет 1) maintainability; и 2) возможность впоследствии передать этот код на суппорт кому-то ещё. Получается жесткий vendor lock без каких либо преимуществ.


              1. MacIn
                01.09.2016 20:41
                +3

                Это вообще «интересный» подход — создавать объекты там, где нужен черный ящик-функция, потому что нет внутреннего состояния.


              1. sentyaev
                02.09.2016 02:25
                +3

                Получается жесткий vendor lock без каких либо преимуществ.

                Это вы очень верно подметили.


              1. franzose
                02.09.2016 05:24
                +2

                Офигенный ответ!


            1. yamatoko
              01.09.2016 21:31
              +5

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


            1. sshikov
              01.09.2016 21:47

              Я бы вообще не был ни в чем убежден на 20 лет вперед. Это попахивает самоуверенностью.


              А то что вы тут делаете, в конкретном примере — это простите, та еще чушь. Позволю себе как-бы похожий пример:


              new If(new NotEqual(b, 0), a/b, b)


              Java — это вообще-то не ленивый язык. Аргументы метода тут вычисляются всегда. Так что деление на ноль произойдет во всех случаях. И вообще исключения при их вычислении никто не отменял. Поэтому такие фокусы в реальной жизни прокатывают только тогда, когда аргументы являются лямбда-выражениями (т.е. в Java 8). Скажем, условный примерчик функциональщины в духе javaslang:


              Try.of(()->Integer.valueOf("xyz")) — т.е. тут аргументом лямбда, которая будет вычислена лениво.


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


              1. yegor256
                01.09.2016 22:46

                Вообще ни в чем не быть убежденным — чистая достоевщина, не находите?) В чем-то все же стоит быть убежденным. Ведь никто не запрещает поменять свои убеждения ровно через неделю)


                1. sshikov
                  02.09.2016 11:10

                  Ну в такой формулировке я могу быть убежден в чем угодно )))


                  Но реально глядя на вещи, и вспоминая скажем для верности 1986 (это правда не 20 лет, а уже 30), я могу твердо сказать, что любые тогдашние предсказания были глупостью. Т.е. тогда у меня были в качестве инструментов EC-1066, с 16 мегабайтами RAM, на которой работало человек 60, VM/SP как ОС, SQL/DS как база данных, REXX и PL/1 как языки разработки (были и другие, много, но они и тогда не заслуживали особого внимания), Script VS как средство подготовки документов, и XEDIT в качестве текстового редактора.


                  Ну и кому сейчас интересна машина с 16 мегабайтами и двумя процессорами, кроме историков?


                  Ну и кто из этих программ сегодня еще живой, так чтобы о них кто-то помнил, кроме ветеранов? Разве что SQL/DS под названием DB2 еще неплохо себя чувствует. Все остальные де факто сдохли, или чисто маргинальные.


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


              1. yamatoko
                02.09.2016 00:10
                +5

                ты что литерал написал в чистом виде? егор тебе этого не простит. срочно заверни в какой-нибудь класс, а лучше в 2.


              1. totally_nameless
                02.09.2016 10:33
                +1

                Я бы вообще не был ни в чем убежден на 20 лет вперед. Это попахивает самоуверенностью.

                Через 20 лет либо падишах помрет, либо ишак :)


              1. kanu
                02.09.2016 14:17
                +2

                new If(new NotEqual(b, 0), a/b, b)
                

                Извините, но это не ООП!
                Вот ООП:
                new If(new NotEqual(b, 0), new Divide(a, b), b)
                


                1. MacIn
                  02.09.2016 14:23
                  +2

                  Не-не-не Дэвид Блейн.

                  new If(new NotEqual(b, new NumericalObjectZero()), new Divide(a, b), b)
                  

                  Какие еще «0»? Автор же говорит — никаких NULL, используйте Null Object design, а с какой стати 0 тогда должен быть? 0 — это специальный случай — ведь на него делить нельзя. Следовательно, мы не можем использовать null 0, мы должны использовать специальный NumericalObjectZero.


                  1. sshikov
                    02.09.2016 20:53

                    Хм. А с отсутствием ленивости вы что делать-то будете?


                    1. MacIn
                      02.09.2016 21:29
                      +1

                      с отсутствием ленивости

                      Ничего — у меня лично отсутствует отсутствие ленивости.


            1. lany
              02.09.2016 05:33
              +3

              Да, так и будет. Просто со временем люди придут к тому, что слишком много раз писать new смысла нет, ведь всё равно всё есть объект и это слово ничего не добавляет. И запятые уберут, они всё равно только загрязняют код. Будут писать просто


              (if (greaterThan a b) a b)


              1. yegor256
                02.09.2016 05:36

                Именно так и будет и называться это будет object composition.


                1. yamatoko
                  02.09.2016 10:23
                  +5

                  уже изобрели. это называется lisp или clojure.


                  1. yegor256
                    02.09.2016 10:53

                    Нет, Lisp и Clojure — это function composition.


                    1. poxu
                      02.09.2016 17:10

                      Ну в примере if и greaterThan — явным образом функции.


                1. relgames
                  02.09.2016 11:11

                  Ну так и стандартные конструкции ведь по сути объекты в AST, которое формируется компилятором.


                1. semenovDL
                  05.09.2016 14:39

                  В данном примере мы исходим из того, что наши классы If и GreaterThan immutable by design и решают только одну задачу.
                  Реализация этого на ruby могла бы выглядеть примерно так:


                  class GreaterThan
                    def initialize(a, b)
                      @a = a
                      @b = b
                    end
                  
                    def call
                      @a > @b ? @a : @b
                    end
                  end
                  
                  class If
                    def initialize(condition, a, b)
                      @condition = condition
                      @a = a
                      @b = b
                    end
                  
                    def call
                      @condition.call ? @a : @b
                    end
                  end
                  
                  a = 1
                  b = 2
                  chain = If.new(GreaterThan.new(a, b), a, b)
                  chain.call # => 1

                  Ок, мы устали писать new, ведь наши классы все равно решают только одну задачу:


                  class GreaterThan
                    def self.call(a, b)
                      a > b ? a : b
                    end
                  end
                  
                  class If
                    def self.call(condition, a, b)
                      condition ? a : b
                    end
                  end
                  
                  a = 1
                  b = 2
                  If.(GreaterThan.(a, b), a, b) # => 1

                  В чем кардинальные отличия этого подхода от FP?


                  def _if(condition, a, b)
                    condition ? a : b
                  end
                  
                  def greater_than(a, b)
                    a > b ? a : b
                  end
                  
                  a = 1
                  b = 2
                  _if(greater_than(a, b), a, b) # => 1


                  1. yegor256
                    05.09.2016 20:16
                    +1

                    Вы совершенно правы, у этого подхода очень мало отличий от FP, однако (это цитата из второго тома «Elegant Object»):

                    We do understand objects well, simply because they are real world entities and exist around of us. The function fibo(7) is exactly as understandable as the object Fibo(7), but objects are more convenient, because they take responsibility to know, what they are. A function lives within the confines of one statement and gives us a result as a successor. Probably a dumb one, which delegates a responsibility on knowing, what it is, to a programmer. This information gets lost in the code as soon as you leave a place of calling the function. In other words, an integer returned from fibo(7) cannot print itself as «Fibonacci number #7: 13» or find the subsequent Fibonacci number. An object (and an object composition) can be instantiated, passed to some function and expose its behaviour somewhere else. It has its own lifecycle, can be asked for its behaviour many times and knows exactly, what it is. Also, in some languages object interactions are way easier to test, thanks to interfaces and fake objects. I can’t remember a language, which allows to define such a separated schema for a function.


                    1. Source
                      05.09.2016 22:28

                      Забавно, когда пытаются что-то объяснить на примерах, оторванных от реальности… Что самое главное в практической работе с числами Фибоначчи? Главное — это возможность мемоизации! Соответвенно, объект Fibo бесполезен чуть менее, чем полностью, и на практике нужен будет единственный на всю программу объект FiboServer, который не будет повторно считать уже вычисленные числа.

                      Also, in some languages object interactions are way easier to test, thanks to interfaces and fake objects. I can’t remember a language, which allows to define such a separated schema for a function.
                      Ахах, т.е. заглушки — это просто, а заменить функцию в pipeline — сложно?
                      Впрочем, спору нет, что благодаря IoC и железной дисциплине в команде можно добиться от объектов того же уровня тестопригодности, который в любом функциональном языке присутствует by design (с нулевыми усилиями).


              1. MacIn
                02.09.2016 14:18

                Лисп и стековые языки потирают руки.


      1. MacIn
        01.09.2016 19:06
        +1

        Чем плох NULL, который является встроенным в язык Null Object design patternом?


        1. mezastel
          02.09.2016 18:55

          Это не так. Null не является Null Object, если бы он им являлся, можно было бы написать Foo foo = null; null.Bar() и это был бы no-op.


          1. MacIn
            02.09.2016 21:32
            -1

            Это только синтаксически. Никто не мешает взять Foo(null).Bar();


        1. Flammar
          05.09.2016 14:46

          Тем, что в отличие от таких design patternов, как «стратегия» и «итератор», его ещё не встроили ни в язык ни в стандартные библиотеки.


          1. MacIn
            05.09.2016 17:58
            +1

            Да ну? А я-то думал, что null определен как минимум в заголовочных файлах. А и то и встроен в язык.


      1. Arlekcangp
        02.09.2016 10:34

        Но только не на java. Вышеприведенный код хорошо будет выглядеть в каком-нибудь clojure но за такой код в java вас ненавидят вполне заслуженно.


    1. yamatoko
      01.09.2016 20:28
      +1

      блин, это же егор 256ой пишет!


    1. Sovent
      02.09.2016 00:33
      +5

      Действительно странно, что кому-то эти статьи рвут какие-то шаблоны. Не знаю, насколько консервативны Java разработчики, но большинство из «откровений» звучат очевидно, а некоторые — просто ошибочно (но никак не претенциозно).
      Ошибочными считаю предложения переносить инфраструктурные механизмы (сериализацию, работу с БД) в объект, это явно противоречит Domain-Driven Design, отголоски которого были слышны в посте «Геттеры\сеттеры — это плохо».


      1. Unrul
        04.09.2016 11:53

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


        1. Sovent
          04.09.2016 13:33
          +1

          Доменный слой — это не только набор интерфейсов необходимых объектов, это ещё и бизнес-сценарии, стоящие за ними. Когда бизнес-сценарии так тесно вплетены в инфраструктуру, коей является БД, это не DDD. В идеале доменная логика контекста должна быть абсолютно независима от инфраструктурных особенностей и быть самодостаточна в любом окружении. Здесь же самодостаточность на уровне подростка-позёра, который выставляет отличный интерфейс, но реализует его за него его папаша SQL.


    1. poxu
      02.09.2016 11:29
      +2

      «ORM плохо» взамен предлагается active record и репозитарий для бедных

      А вот нет. В ещё одной статье написано, что это всё зло.


      1. qadmium
        02.09.2016 14:17
        +1

        вот только там он протеворечит сам себе, потому что то, что он показал это ActiveRecord и repository, и совершенно верно ему об этом рассказали. При этом рассказывает какие-то сказки про active record, очевидно не читав даже определения


    1. Linloil
      05.09.2016 23:00
      +2

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


  1. exvel
    01.09.2016 19:17
    +6

    Прочитав интервью, вдохновившись, потопал читать блог. И, честно говоря, расстроился, потому что, по мировоззрению, как раз попал к тем, кто критикует подобные подходы. Возможно, я чего-то не понимаю доконца, но, если уж самая базова статья (почему null плохо) вызывает категоричное несогласие, то что уж говорить об остальном. Заменять null'ы NULL-объектами для меня крайне сомнительная затея.
    А самое печальное, отсутствие электронной версии книги автора. Это ооооочень странно. Получается желание заработать преобладает над желанием распространить свои идеи и подходы.
    Не хочу никого обижать, но все выглядит как какая-то популистика из разряда «давайте возьмем самые дискутируемые темы из ООП и покажем что все на-самом-деле-не-так».


    1. poxu
      02.09.2016 17:17

      Заменять null'ы NULL-объектами для меня крайне сомнительная затея.

      Это нужно, чтобы вместо


      Bean bean = repository.getBean();
      
      if (bean == null) {
          return null;
      }
      
      Data data = bean.getData();
      
      if (data == null) {
          return null;
      }
      
      return data.getName();

      Можно было написать что-то вроде.


      return repository.getBean().getData().getName();


      1. qadmium
        02.09.2016 17:27

        а почему нельзя просто не возвращать null?


        1. poxu
          02.09.2016 17:37

          Почему нельзя, можно :). Если null не нужен, то конечно Null объект тем более не нужен :)


      1. MacIn
        02.09.2016 18:22

        Можно было написать что-то вроде.

        return repository.getBean().getData().getName();

        А зачем? Зачем нам getData от несуществующих данных? Зачем getName от несуществующих данных? Как отличить ситуацию, когда «имя» = "" и ситуацию, когда оно не найдено? Получается, что мы заменяем невалидный явно объект NULL на объект невалидный неявно — объект-пустышку, только для того, чтобы вызвать код, который по определению не может с пустышкой работать. Это еще не говоря про то, что где-то this может быть пустым и это сработает и так.


        1. poxu
          02.09.2016 19:32

          Мы собираемся вернут пустой объект, если хотя бы один объект в цепочке пустой. Так бы мы проверяли на null и возвращали null в конце концов. А так можно обойтись без проверок. Но это конечно не так интересно, как Optional, который поможет вернуть не null, а что-то кастомное, если хотя бы один объект в цепочке пустой. Или вообще не выполнять какую-нибудь операцию, если объект пустой.


          1. MacIn
            02.09.2016 21:36
            +3

            А так можно обойтись без проверок.

            Зачем две лишние проверки возврата пустоты, если изначально ясно, что операция не удалась? Если следовать стилю автора (в части мячиков, собак, NULL и звонков с вопросом), то это примерно как вместо «дорогая, я забыл купить продукты» протянуть пустой пакет, сказать «свари из этого суп», получить в ответ пустую кастрюлю. Вместо того, чтобы отложить ее, съесть из нее пустоту-воздух ложкой, а потом отметить про себя, что калорий-то не поступило. Ну, да, результат одинаковый, процесс — нет, втч по затратам. Зачем?


            1. poxu
              02.09.2016 22:05

              Зачем две лишние проверки возврата пустоты, если изначально ясно, что операция не удалась?

              Возвраты пустоты для того, чтобы не писать проверки вручную. Код становится читать легче. Затраты — несущественно больше.


              1. MacIn
                02.09.2016 22:09

                По-моему, код становится писать легче, а не читать. Красивая концепция — все в строку.
                Еще вопрос: в стиле return repository.getBean().getData().getName();
                вам нужно поставить breakpoint на вызов getName. Далеко не каждая среда разработки позволит отловить этот конкретный вызов. Уж не говоря о том, что с null мы можем поставиь точку останова именно на момент fail'а операции с целью просмотра каких-либо данных.


                1. poxu
                  02.09.2016 22:18
                  -1

                  Я стараюсь без дебага обходиться. Но можно каждый вызов писать на отдельной строке — я только за. Опять же условный брейкпойнт поставить в джаве несложно. Но я стараюсь не дебажить.


                  1. MacIn
                    02.09.2016 22:22

                    Я стараюсь без дебага обходиться

                    О чем я и переживаю: «По-моему, код становится писать легче, а не читать»

                    Опять же условный брейкпойнт поставить в джаве несложно.

                    Условный — да, а можно ли в Java поставить BP на возврат объекта-пустышки из .getBean() в строке:
                    return repository.getBean().getData().getName();
                    Или все же потребуется
                    data = repository.getBean().getData();
                    return data.getName();

                    ? И можете ли вы ловить именно объект-пустышку, а не null?


                    1. poxu
                      02.09.2016 22:33
                      -1

                      Код становится легче читать, потому, что бессмысленные проверки на null не мозолят глаз.


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


                      1. MacIn
                        02.09.2016 22:38

                        Код становится легче читать, потому, что бессмысленные проверки на null не мозолят глаз.

                        По-моему, читать «математическую» нотацию вида
                        bean = repository.getBean();
                        data = bean.getData();
                        outcome = data.getName();
                        return outcome;
                        

                        легче, чем цепочку, и проверки никак не мешают — это обычный шаблон, который воспринимается совсем буднично, потому что код написан так же, как исполняется машиной, и читая его, ты следуешь ее логике: «получили — ошибка? выходим. Нет, смотрим дальше».


                        1. poxu
                          02.09.2016 22:49

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


                          1. MacIn
                            02.09.2016 23:04

                            Наверное зависит от человека.

                            Разумеется!
                            Просто без этого напоминает старый анекдот: «С утра заехал, купил колодки, потом смотался на другой конец города, купил сцепление, потом заехал на мойку, потом в сервис, поменял колодки и сцепление, потом на техосмотр. Фффух, как бы я это успел, если бы не было машины». Здесь аналогично — если мы говорим, о том, что null это evil, потому что мы не можем с в стиле stream писать, то встает вопрос — а надо ли оно изначально.


          1. Unrul
            04.09.2016 12:03
            +1

            По логике статьи, в конце return repository.getBean().getData().getName() должен быть возвращён не null, а экземпляр класса NotExistingName реализующий интерфейс IName. В этом как раз и заключается фундаментальное отличие от оператора ?..


      1. relgames
        02.09.2016 18:25

        return repository.getBean().getData().getName();
        

        Это же антипаттерн по Егору. Вы не уважаете объект. Лезете в его потроха.


        1. Unrul
          04.09.2016 11:56

          Если getBean(), getData() и getName() возвращают самостоятельные объекты — то всё нормально. Если ссылки на внутреннее состояние — уже неуважение.


      1. exvel
        02.09.2016 18:27
        +2

        Выглядит как костыль над понятием null, которое, как по мне, самодостаточно. Подобное, простейшим образом, решается синтаксическим сахаром. Так, например, в C#:

        return repository?.getBean()?.getData()?.getName();
        


        1. MacIn
          02.09.2016 18:29

          Более, чем самодостаточно: NULL это не 0, это невалидный объект(или структура ака запись). Это уже встроенный в язык NotExistingObject.


          1. poxu
            02.09.2016 19:28

            Нет, это не так. Вам уже ответили тут


            1. MacIn
              02.09.2016 21:38

              Это чисто syntax sugar разница, не более. NULL возвращается в качестве ссылки/указателя и ничем не хуже, чем указатель на существующий валидный объект или указатель на объект-пустышку.


              1. poxu
                02.09.2016 22:06

                Разница в том, что попытка вызова метода у null приведёт к ошибке в рантайме.


                1. MacIn
                  02.09.2016 22:16

                  Если метод не статический.

                  Вы спорите о том, что крокодил длинный, я — о том, что зеленый. Вы говорите о том, что нельзя работать с null как с полноценным объектом, я о том, что null — специальная невалидная сущность (которую можно привести к объекту — и о чудо! это тоже будет полностью невалидный объект, невалидный вплоть до падения), которая в языке есть именно для того, чтобы понять, что результат не получен. Мне непонятно само желание выполнения последующих шагов обработки данных, если уже понятно, что операция не удалась изначально.


                  1. poxu
                    02.09.2016 22:23
                    -1

                    Статических методов у объекта не бывает, они у класса :). Но я не за Null Object, я за Optional, если что. Хотя Null Object всё равно лучше, чем Null, в случае, когда нужно просто написать цепочку вызовов и вернуть Null Object, если хотя бы один зафейлился. Шаги же не выполняются. Происходит несколько вызовов методов пустых объектов и всё. В случае с Optional — несколько вызовов одного метода одного и того же объекта.


                    Вы в дискуссиях про Go участвовали? Помните там обработка ошибок как устроена?


                    1. MacIn
                      02.09.2016 22:29

                      Статических методов у объекта не бывает, они у класса :)

                      Вроде я про статический метод объекта и не писал.

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

                      null ничем концептуально не отличается — так же на каждой стадии при получении null мы можем прокидывать null наверх. Разница в написании в строку, но по мне, это сомнительное преимущество.

                      Вы в дискуссиях про Go участвовали? Помните там обработка ошибок как устроена?

                      Совсем немного.
                      Смотря где, постоянно вижу конструкции вида
                      err, res = function_name();


                      1. poxu
                        02.09.2016 22:46

                        null ничем концептуально не отличается — так же на каждой стадии при получении null мы можем прокидывать null наверх. Разница в написании в строку, но по мне, это сомнительное преимущество.

                        Ну вот есть мнение, что огромное количество кода падает от того, что программист забыл проверку на null в цепочке. Которая вообще-то нужна только потому, что с null всё упадёт. Вон в С# целый оператор для этого придумали. ?.


                        Смотря где, постоянно вижу конструкции вида
                        err, res = function_name();

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


                        b := bufio.NewWriter(fd)
                        b.Write(p0[a:b])
                        b.Write(p1[c:d])
                        b.Write(p2[e:f])
                        // and so on
                        if b.Flush() != nil {
                            return b.Flush()
                        }

                        Принцип тот же. Вот ссылка на статью целиком, если я мутно написал.


                        1. MacIn
                          02.09.2016 22:54
                          +1

                          Ну вот есть мнение, что огромное количество кода падает от того, что программист забыл проверку на null в цепочке.

                          Так это вообще-то замечательно — мы увидим, что есть ошибка(stacktrace прилагается), и исправим ее. В случае нульобджекта вы просто тихой сапой ничего не сделаете.

                          Которая вообще-то нужна только потому, что с null всё упадёт.

                          Да нет — это, например, просто символ ошибки операции. Вовсе не только потому что иначе упадет. Это может быть
                          someting = foo.bar();
                          if(something==null){
                            doThis();
                            doThat();
                            reportSomething();
                            return;
                          }
                          

                          это может быть
                          data = foo.bar();
                          if(data==null){
                            data = new Data;
                          }
                          


                          1. poxu
                            03.09.2016 09:39

                            С Null Object можно делать точно так же. Проблем не будет никаких.


                            1. MacIn
                              03.09.2016 15:32
                              +2

                              NullObject — лишняя сущность.


                              1. poxu
                                03.09.2016 16:23

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


                        1. MacIn
                          02.09.2016 23:00

                          По Go — это все же несколько иное. Я бы сказал, это синхронный vs асинхронный метод обработки ошибки. Не совсем точное определение — да, там все синхронное, но принцип частично похож — разнесение операции и контроля ошибки в разные места. То же самое «бросить исключение вместо кода ошибки» — отсюда же.


                    1. webkumo
                      03.09.2016 03:45

                      Статические методы класса вызванные по ссылке объекта. В чём проблема-то? Для статического метода в Java следующее выражение бует вполне корректно:
                      SomeClass someObject = null;
                      someObject.someStaticClassMethod();//code smell but works


                      1. poxu
                        03.09.2016 09:42

                        Проблема в том, что статические методы не вызываются по ссылке объекта. Компилятор в процессе компиляции определяет, какой у объекта класс и заменяет


                        someObject.someStaticClassMethod();

                        на


                        SomeClass.someStaticClassMethod();


                        1. MacIn
                          03.09.2016 15:32

                          А это смотря где. Да, я не говорю, о том как можно писать — за это надо руки отрывать — а о том, как физически возможно. Если метод статический по сути, а не по объявлению (да и если по объявлению), можно сcast'ить null в объект и вызвать этот метод.


                          1. poxu
                            03.09.2016 16:27

                            Где-то вызов у объекта метода со спецификатором static не будет заменён компилятором на вызов метода у класса?


        1. poxu
          02.09.2016 19:33

          Вы совершенно правы (в том, что ?. решает тот кейс, который я привёл в пример). Единственное что это сильно зависит от точки зрения. По мне так синтаксический сахар, который вы показали это костыль, которым пытаются заменить Optional.


          1. qadmium
            03.09.2016 03:56
            +2

            простите но у нас Nullable вместо Optional, в чем разница?


      1. Ununtrium
        02.09.2016 21:57

        Наброшу. В С# есть такая вещь как null conditional operator — "?.".
        Поэтому там можно писать
        repository.GetBean()?.GetData()?.GetName();

        Без всякого нытья, какой null плохой.

        Так-то.


        1. poxu
          02.09.2016 22:08
          -1

          Об этом уже говорили. Действительно решает проблему, но Optional лучше.


          1. Ununtrium
            02.09.2016 22:21
            +2

            Лучше чем именно?


            1. poxu
              02.09.2016 22:53
              -1

              Тем, что позволяет вернуть что-то отличное от null.


              object.getData().getOrElse("Bad Data");


              1. Ununtrium
                03.09.2016 00:37

                Офигеть! То есть мы ожидаем строку, и если пришла «Bad Data», то падаем? А что, надежно.


                1. poxu
                  03.09.2016 09:27

                  Да нет, не падаем. Просто дальше работаем с этой строкой.


                  1. Ununtrium
                    06.09.2016 14:09

                    Как работаем? Вот надо 404 кинуть если нет результатов.


                    1. poxu
                      06.09.2016 14:31

                      В данном случае цель кода — вернуть строку в любом случае. Если мы знаем, что отсутствие data ведёт к исключительной ситуации, то мы напишем


                      object.getData().orElseThrow(IllegalStateException::new);


                      1. Ununtrium
                        06.09.2016 19:27

                        А теперь вопрос: что дешевле — кинуть эксепшн или вернуть null?


                        1. poxu
                          07.09.2016 08:56

                          Это вопрос из другого холивара :). В данном случае, если волнует дороговизна эксепшна — можно вернуть пустой Optional — по цене это тоже самое, что вернуть null, но дальше по цепочке есть все возможности, предоставляемые Optional.


                          1. Ununtrium
                            08.09.2016 13:40
                            +1

                            Все что угодно, лишь бы не признать что С# решил проблему лучше :)


                            1. onikiychuka
                              09.09.2016 16:57

                              Пишу одновременно на java и c# :)
                              В Java луше тк простой мапинг данных сделать в C# сложно
                              что-то из серии

                              Optional<User> user = ...;
                              Optional<UserName> name = user.map(u->new UserName(u.FirstName, u.LastName))
                              


                              В C# будет выглядеть как

                              var user = ...
                              UserName name = null;
                              if(user != null) {
                                  name = new UserName(u.FirstName, u.LastName);
                              } 
                              


                              Ну и в Java версии явно видно — может быть пустое значение или нет


            1. warlock13
              07.09.2016 09:39

              Optional лучше ровно одним: с ним сигнатура функции явно подчёркивает, что функция может не вернуть результат, так что неучёт этого программистом выявится уже на этапе компиляции. Использование null отодвигает проверку на этап выполнения, но всё равно помогает выявить ошибку — если конечно код не напичкан бездумными "проверками на null" "на всякий случай".


          1. qadmium
            03.09.2016 02:59
            +1

            repository.GetBean()?.GetData()?.GetName() ?? «Bad Data»

            все уже давно есть ))


            1. poxu
              03.09.2016 09:37

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


              А знаки вопроса эти на тернарный оператор похожи, будь он неладен. Хотя часть проблем снимают конечно. Но с таким подходом наверное лучше особый синтаксис делать для мест в которых null не может вернуться — их меньше.


              1. qadmium
                03.09.2016 11:31

                В Optional ещё можно лямбду выполнить если там пусто и ещё много чего можно


                все тоже самое, там должно быть просто выражение

                Кроме того Optional в сигнатуре медота означает, что метод может вернуть пустое значение. Синтаксис чище выходит. Не надо гадать, может там быть пустое значение, или нет.


                да, это плюс

                Но с таким подходом наверное лучше особый синтаксис делать для мест в которых null не может вернуться — их меньше.


                в дотнете ровно все наоборот, обычно это нежданчик когда тебя null отдали, но в тех местах, где это есть, обьёмы кода впечатляют


          1. sentyaev
            07.09.2016 08:50

            Special Case же. Уже давно придумано.


  1. konsoletyper
    01.09.2016 21:48
    +8

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


    А всё потому, что он приводит короткие красивые примеры, где всё выглядит хорошо, но на практике, когда система начинает усложняться, писать, как он предписывает — равносильно самоубийству. Примеры? Пожалуйста (спасибо одному из комментаторов, дал хорошую подборку):


    3) Data Transfer Object Is a Shame
    «DTO плохо» взамен предлагается переложить сериализацию/десериализацию на саму сущность, минуя DTO

    Да, вот только есть ещё такой подход, как single responsibility principle, такой важный, что является частью SOLID, и статьи, расписывающие преимущества SOLID, не менее логичны, чем статьи Егора. Вот только практика (именно практика, а не маленькие игрушечные примеры) показывает, что SOLID работает, а подходы Егора — нет.


    Другой пример — Егор предлагает заменять utlity-методы объектами, т.е. вместо CollectionUtils.sort делать класс SortedList, и сортировать список, создавая экземпляр этого класса. Я не вижу никакой разницы, т.к. всё равно ничего не инкапсулируется, и более того, конструктор — это фактически и есть вызов статического метода (называемого <init>). Ну а уж по поводу критических по производительности кусках кода я вообще промолчу.


    Так вот, проблема в том, что действительно, приходится писать не самые "чистые" вещи в коде. И это проблема не глупых разработчиков, это проблема глупых средств разработки. Были бы языки программирования повыразительнее, можно было бы включить перфекционизм на 142% и писать бескомпромиссно чистый код. Однако, тут проблема в том, что излишне выразительные языки программирования обладают тем недостатком, что их сложно выучить и сложно эффективно реализовать компиляторы и тулинг, но что ещё важнее, — они слишком непредсказуемые.


    1. Source
      01.09.2016 22:37

      Были бы языки программирования повыразительнее
      Посмотрите Common Lisp или Racket. Выразительность ничем не ограничена. Описанных недостатков вроде не наблюдается.


      1. konsoletyper
        01.09.2016 23:29

        Как раз Common Lisp — это плохой пример. В нём ровно две фатальные проблемы: динамическая типизация и макросы. Именно они делают код на CL совершенно нечитаемым и трудноподдерживаемым, уж не говоря о его минималистичном синтаксисе.


        1. Source
          02.09.2016 14:55

          Это не проблемы. Это та самая неограниченная выразительность, позволяющая хотя бы теоретически писать код, который идеально отражает намерения программиста.
          Ну а если код получился трудночитаемым даже на нём, то это уже «разруха в головах» (с).
          Многим программистам нравится, когда выразительность искусственно ограничена, это помогает им структурировать свои мысли. Дальше всего по этому пути пошёл Go.


          1. u1789
            02.09.2016 18:54

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


            1. Source
              02.09.2016 22:24

              Это во многом миф, удобство чтения кода в большей мере зависит от автора кода, чем от ЯП. При этом чем выше уровень автора кода, тем бессмысленные ограничения выразительности.


            1. Hronom
              05.09.2016 13:37

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


              1. Source
                05.09.2016 19:44
                +1

                Обоснуйте! Каким образом по-вашему это проявляется в масштабах экосистемы?
                Например, я вижу в экосистеме Go большую тягу к велосипедостроительству… Это выражается в том, что для решения одной задачи создаются порой десятки вариантов решений, т.е. отсутвует консолидация усилий…
                В языках, где можно легко и быстро включиться в разработку, наоборот преобладают тенденции к созданию де-факто стандартных пакетов под каждую задачу.


                1. Hronom
                  05.09.2016 20:40

                  Я не программировал на Go, но заметил, из hello world тутора, что в языке уже вшиты Egyptian brackets т.е. если бы я программировал на Go, и читал чужой код, то, как минимум, в этом вопросе у меня вопросов/боли не возникло бы.

                  Мне эта идея нравится, когда в язык вшивается стиль, представьте язык, в который вшит, к примеру, гугло-джава-стиль https://google.github.io/styleguide/javaguide.html

                  А что касается функционала, если я правильно понял, в Go существует из коробки эдакий менеджмент зависимостей(я про import с git репозиториев) мне эта идея тоже нравится.


                  1. Source
                    05.09.2016 22:42

                    Автоформаттер — это про читаемость кода, но совсем не про выразительность языка… К тому же не так много языков страдает от наличия конкурирующих style guides. И тут я за более мягкие решения вопроса, типа Hound CI

                    если я правильно понял, в Go существует из коробки эдакий менеджмент зависимостей(я про import с git репозиториев) мне эта идея тоже нравится.
                    Поверьте, import тупо master-ветки с git репозиториев — это далеко не лучшая затея. Я давно не следил за прогрессом Go в этой области, но по крайней мере раньше у них даже не было штатного менеджера зависимостей. А когда у вас куча зависимостей на master-ветки репозиториев — это вообще не весело. Поэтому догадайтесь что там происходило пару лет назад… Правильно! Все, кому не лень, писали свои менеджеры зависимостей, коих было не меньше десятка.


    1. Unrul
      04.09.2016 12:30

      На мой взгляд, CollectionUtils.sort и SortedList как раз очень показательные примеры в отношении инкапсуляции и SRP. С CollectionUtils.sort, на первый взгляд, всё нормально. Но мы никогда не используем этот метод сам по себе, мы применяем его к коллекции элементов, после чего она становится отсортированной. И у отсортированной коллекции уже другой набор инвариантов и свойств. Мы, к примеру, можем эффективно получать минимальный и максимальный элементы и производить поиск, но не можем просто добавлять новые элементы в конец списка. И если у нас имеется объект типа SortedList, то все эти инварианты поддерживаются самим объектом, а не хранятся в виде комментария, или вообще неявно, в голове писавшего этот кусок кода программиста.

      Насчёт производительности. В С++, к примеру, исходный список можно не копировать в SortedList, а перемещать. И сам экземпляр класса SortedList можно при необходимости создавать на стеке, а не в куче. В Java, насколько я знаю, выбор, увы, не особенно велик, но небольшие объекты интерпретатор самостоятельно размещает на стеке, а семантику перемещения можно реализовать и вручную.


  1. G-M-A-X
    02.09.2016 00:35

    вся красота ООП

    Можно по пунктам? Или сравнение с текущим ООП.
    Мы же даём программисту в Java управлять файлом на диске — открыли, закрыли. Почему то же самое нельзя делать с памятью?

    Используйте C. Java ж вроде позиционируется как вещь, которой тяжелее выстрелить себе в ногу. Автоуборка мусора и все такое.
    АОП

    В Java нету чего-то типа dll? :)
    И потом все практики за ними должны идти. А мы идём от практики к теории.

    Есть много теоретически хороших, но мертвых языков. :)
    А большинство языков программирования создаётся в битве за популярность. Они понимают, что если дать людям не 4 инструмента, а 14, упрощающих то, что и так делают, то их станут использовать с большим интересом.

    Так ты сам такой. Хочешь разные фишки из коробки.

    А чем плохи геттеры и сеттеры? :)
    То что писал автор — ерунда.
    Хотя я их практически не использую, так как использую ООП не фанатично, поэтому нужды в них нет.

    Кстати, что думаете о goto? :^)

    Там будет про ORM много

    ОРМ — говно. +1

    MVC

    А что в нем плохого? Это всего лишь разделение кода. Или нужно все лепить в кучу?

    Там будет про аннотации

    Аннотации это фигня, код в комментариях, бред.

    Относительно ф-и max. Это оверинжиниринг.

    Основной язык — PHP.


    1. sshikov
      02.09.2016 11:15
      +1

      ОРМ — говно. +1

      Вы просто не умеете их готовить ) Не, серьезно, я знаю один аргумент, за ORM. А точнее даже за DAO. Он очень простой, но он применим далеко не ко всем проектам. DAO и ORM — это некоторый слой абстракции, куда можно засунуть часть логики приложения. И пилить его отдельно от других слоев. Это почти такое же разделение кода, как и MVC. Это позволяет данную (обычно рутинную) часть логики отдать отдельному человеку, сравнительно невысокой квалификации, ускорив таким образом разработку в этом месте.


      Если вы пишете проект в одиночку, вам это скорее всего не нужно. Если у вас проект — репортинг, т.е. больше всего select — то опять же, вам ORM скорее всего не нужны. Но это далеко не все проекты.


      1. G-M-A-X
        02.09.2016 14:37

        По работе он используется.

        Жрет память, иногда строит не совсем оптимальные или даже неадекватные запросы.


        1. poxu
          02.09.2016 17:20

          Зато не надо писать кучу кода. А неоптимальные запросы всегда можно переписать руками.


          1. G-M-A-X
            02.09.2016 17:47

            Зато не надо писать кучу кода.

            Эту задачу решает не только ОРМ

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

            Вот неоптимальные запросы как раз не хочется руками переписывать.
            В одном случае пришлось просто явно разбить запрос на 2 вызова ORM, хотя под капотом там было тоже 2 запроса изначально.
            Руками можно писать запросы, которые сложно выразить через абстракцию.


            1. poxu
              02.09.2016 19:37
              +1

              А что, помимо ОРМ помогает не писать эту кучу кода?


        1. sshikov
          02.09.2016 20:57
          +1

          Кто этот "он", и почему вы его недостатки обобщаете на все реализации?


  1. insensible
    02.09.2016 01:55

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


    1. sentyaev
      02.09.2016 02:31

      Даже если прямо сейчас появится то о чем вы говорите, и даже если мы все накинемся и будем переписывать то что есть…
      Не успеем мы за 20 лет все переписать, так что и ООП будет, и ФП, и все остальное.
      Мы тут навсегда застряли.


      1. yegor256
        02.09.2016 03:08

        Это вы тут навсегда застряли, а я собираюсь выбираться:) Приглашаю со мной.


  1. UbuRus
    02.09.2016 10:35

    Обделили ссылочкой http://jetconf.by/
    Или JET Conf не проплатил? :trollface:


    1. ARG89
      02.09.2016 10:47

      Не нашел видео Егора с JET Conf, вот и ссылки нет.


      1. UbuRus
        02.09.2016 11:44
        +1

        ARG89 Без проблем: https://www.youtube.com/watch?v=-Y4XS7ZtQ2g&index=2&list=PLeI8rYvNSwbX64S1js06pKbgNctnv3Uc7 :)


        1. ARG89
          02.09.2016 11:55

          Вот и добавили.


  1. aibar
    02.09.2016 10:47
    +1

    На самом деле все идеи Егора в том или ином виде уже расписаны в просторах инета. Но у него есть и некоторые новые идеи.

    Правильно было сказано, другие пишут мягко, уважая программиста который пишет «не так», Егор же не уважает программиста, а объект. Мне подход Егора больше по душе, все мы грешники, и об этом надо говорить))

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


    1. qadmium
      02.09.2016 10:57
      +6

      программиста который пишет так выкидывают в окно без выходного пособия


      1. aibar
        02.09.2016 13:51

        Да, с вероятностью в ~100% выгонят. С такими идеями, чтобы тебя не выгнали, надо работать в Долине и быть CTO


    1. relgames
      02.09.2016 11:22
      +5

      У нас в команде был программист, который проповедовал похожий подход — объекты, которые могли ВСЁ — и из базы прочитаться, и по сети передаться, и еще всякое, прямо по Егору.

      Выгнали его — за год он написал дико тормозящего монстра, в котором никто не мог разобраться, кроме него.
      Мы этого монстра убили и за 1 месяц с нуля переписали 80% функционала, со слоями, DTO и JPA. Оставшиеся 20% допилили за еще месяца 4, причем уже не нужно быть супер опытным программистом, все в команде могут работать с этим кодом, в том числе и новички.

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

      Вы видели проект, который Егор приводил в качестве идеала? Как вам?


      1. aibar
        02.09.2016 13:39
        +2

        объекты, которые могли ВСЁ — и из базы прочитаться, и по сети передаться, и еще всякое

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

        Вы видели проект, который Егор приводил в качестве идеала? Как вам?

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


        1. relgames
          02.09.2016 15:00

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

          А без веры угодить Богу невозможно; ибо надобно, чтобы приходящий к Богу веровал, что Он есть, и ищущим Его воздаёт. Евр.11,6


        1. exvel
          02.09.2016 16:09
          +2

          Прочитайте книгу.
          Я бы вот с радостью почитал, да негде. В 21-ом веке не иметь цифровой версии книги — очень странно.


  1. vyatsek
    02.09.2016 14:47
    +2

    Почитал весь этот радикализм, это все от непонимания.
    Программирование сложная инженерная область, потому как разработчик может сделать все что угодно и практически ни чем не ограничен. Единственный ресурс это время. Расходуя это время программист может строить людбые хрустальные замки и велосипеды, цена деньги в час — и все! При такой свободе действий создать шедевр может только гений, разумно используя весь технический арсенал, который со временем расширяется с гигантской скоростью. В шедевре ничего не бывает лишнего, не бывает избыточной красоты, ненужных вещей и красивости, красота в минимальности и простоте, достичь которую очень сложно. (Пример шедевра автоматическое оружие Калашникова)
    Остальная серость, включая меня, ругает инструменты, не достаточно глубоко разбирается в сущности проблемы, назначении инструмента, кругозора инструментов и создает что-то монстроузное.
    В начале 2000 когда язык придерживался только одной парадигмы, было трудно выйти за рамки. Сейчас C#, Java, C++ консолидируют возможности, которые должны быть использованы уместно. null reference это плохо, это не плохо, просто надо знать как им пользоваться и сейчас для этого куча готовых инструментов. If-Then-Else Is a Code Smell, г-но это тогда, когда он не уместно используется и так везде.

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


  1. chabapok
    02.09.2016 21:43

    Посмотрел статью, в которой автор пытается убедить нас, что DTO — это плохо. В качестве альтернативы автор приводит код, в котором все равно неявно используется DTO с сеттерами. Просто названо по-другому, без префикса set. И часть кода автор предусмотрительно опустил — потому что если бы он его привел, то мы бы увидели, что там есть сеттеры и DTO.

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

    Я думаю, идеями автора все же можно пользоваться, но без фанатизма — как и любыми инструментами.

    Посмотрел видео… помоему, у автора просто депрессняк.


    1. Flammar
      05.09.2016 15:14

      У автора вместо DTO используется нечто подчёркнуто иммутабельное, реализующее DTO-образный интерфейс.без сеттеров. В принципе, интересно.

      Не вижу нормального способа создать IOC-контейнером объект с циклическими ссылками без сеттеров в том или ином варианте.
      Через декорирование, проксирование и «одноразовые де-факто-сеттеры», типа ленивых инициализаторов.


      1. chabapok
        05.09.2016 17:37

        Если и без сеттеров — то с геттерами.
        Но автор же максималист. Он на «разборе полетов» утверждал, что геттер — это как если тебе в мозг втыкают электроды и вычитывают оттуда нужную инфу прямиком из мозга. А оопэшно — это если ты сам говоришь эту инфу попросившему ее сказать. То есть, геттеры тоже нельзя. Я его идею понял так.


        1. MacIn
          05.09.2016 18:01

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


          1. chabapok
            05.09.2016 20:17

            это вы у автора спрашивайте


          1. Flammar
            05.09.2016 23:53

            Ну, представьте, геттер возвращает вам список, который вы можете модифицировать. На одной из моих работ чек-стайл ставил предупреждение по такому поводу. Там либо копировать либо декорировать (предпочитаю термин «проксировать»).


            1. MacIn
              06.09.2016 02:00
              +1

              И? Хороший геттер, который вам вернет немодифицируемые данные, скажем, копию списка, не будет геттером?


              1. Flammar
                07.09.2016 17:17

                Если копию — то, наверное, скорее, «провайдером»;-) если readonly-прокси к реальному состоянию — то тут, безусловно, геттером.


                1. MacIn
                  07.09.2016 18:13

                  Видимо, терминологическая путаница. Само понятие «getter», судя по всему, сильно language specific.


          1. spitty
            06.09.2016 23:21

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


            "Хороший, умный и правильный" объект должен наружу показывать лишь те методы, которые от него требуются по контракту (также известному как "интерфейс"). Если разрабатывать архитектуру, отталкиваясь не от данных, а от задач, которые должны решаться, контракты большинства объектов не будут содержать getter'ов в значении "окна во внутреннее представление".


            1. MacIn
              07.09.2016 18:10

              Вы не поняли вопроса. Мое «чем отличается» не значит «геттер-окно ничем не хуже», на что вы и пытаетесь возражать.


        1. Flammar
          05.09.2016 23:48
          +1

          У него в примерах про работу с БД каждое «DTO» реализует readonly интерфейс, состоящий их одних, по факту, геттеров, в названии которых просто нет слова «get».


  1. mou
    03.09.2016 03:22
    +9

    У моей подруги нет аккаунта на Хабре, поэтому она не может оставить комментарий, но он мне настолько нравится, что я даже пожертвую своей кармой.

    Иисус от ООП? Ну пусть сначала умрет за ваши программерские грехи))))


    1. jbaruch
      04.09.2016 07:36
      +1

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


      1. poxu
        04.09.2016 10:27

        который и пророком-то не был.

        Это смотря в какой религии.


        1. jbaruch
          06.09.2016 12:17

          Если я не ошибаюсь, то пророком он назван только у Бахай. У христиан он Бог, у остальных — "основатель кружка рыбной ловли"(с).


          1. poxu
            06.09.2016 12:27

            Зачем сразу кидаться в новомодную экзотику? Я имел в виду старый добрый ислам. Там он вполне себе пророк. Я бы даже сказал один из величайших пророков.


            1. jbaruch
              06.09.2016 12:47
              +2

              Про "добрый" это, конечно, хорошо сказано :)


      1. vladimir_dolzhenko
        04.09.2016 10:39

        скорее то, что он самый известный, которого фактически убили за его взгляды.


        1. jbaruch
          06.09.2016 12:20

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


  1. plotnick
    03.09.2016 12:42
    +1

    когда уже народ поймет что Clojure гораздо удобнее и приятней и практичней?


    1. vladimir_dolzhenko
      03.09.2016 14:26
      +1

      (+ vote 1)
      


      1. witbier
        05.09.2016 05:43
        +3

        Делай это идиоматично, бро

        (inc vote)
        


        1. vladimir_dolzhenko
          05.09.2016 08:39

          спасибо, ты прав — давно не брал шашку в руки


        1. poxu
          05.09.2016 12:01

          Я правильно понимаю, что функция вернёт vote + 1, а сам vote не изменится? Если так, то название inc вносит путаницу. Мне сразу кажется, что она увеличит аргумент.


          1. vladimir_dolzhenko
            05.09.2016 12:30

            это лисп — no side effects — возвратится новое значение, старое останется не тронутым


            1. poxu
              05.09.2016 12:37

              И название типа inc или dec для функции, которая возвращает аргумент, увеличенный или уменьшенный на еденицу там общепринято?


              1. vladimir_dolzhenko
                05.09.2016 12:46

                Прошу прощения — это больше к clojure: inc in clojure без side effect,
                В лиспе incf всё же имеет side effect.


  1. AlexNevskiy
    03.09.2016 15:46

    Похожий подход предлагался уже на хабре для C++ 10 лет практики. Часть 1: построение программы.


    Ещё раз повторю важный момент: структура программы на С++ отличается от С с точностью до наоборот. Там у нас были структуры и общие переменные. Здесь у нас объекты, которые суть чёрные ящики. Каждый объект — сам себе жнец, швец, на дуде игрец…

    Напоминаю, что get/set доступ — это чуть более завуалированный вариант открытого члена класса.… Вместо того чтобы запрашивать данные, просим объект сделать нужное действие самостоятельно. Это необходимое условие стабильности больших проектов на С++.


  1. vladimir_dolzhenko
    04.09.2016 20:46
    +3

    • уже звучало не первый раз, и в том числе и этом интервью — но мне до сих по не понятно — почему нельзя напилить свой язык, в java (как языке) много рудиментов и конструкционно не православных вещей — будь Бендром — сделай свой парк развлечений — как Одерский, Rick Hickey, авторы Kotlin (увы, не знаю их по именам) — инструменты доступны — оттранслировать в jvm не супер сложно (но не за 5 минут). Не нравится ООП в java, boiler plate, и что там еще — да черт бы с ними, покажи мир другой — как говорил Толкиен — не так сложно придумать мир с зеленым солнцем, сколько придумать мир в котором это солнце выглядело бы нормально. Покажи как надо делать правильно — и пусть даже используя новый язык — к чертям все эти компромиссы — я в своё время очень проникся clojure именно за то, что он был как глоток свежего (для меня) воздуха — почти чистый fp без лобызаний и сильных компромиссов — мой парк — мои женщины — что хочу — то ворочу
      • почему нужен новый язык, а не пытаться реанимировать java? — была попытка обсуждения в чатике РП — говорят и на ассемлере можно писать ООП, но это мягко говоря не то удовольствие, которое хотелось бы иметь. Ладно бы в java был только один единстенный недостаток, но в силу истроческих причин их не мало. Не стоит использовать микроскоп для забивания гвоздей, а молоток для изучения бактерий. Не является ли java молотком для выражения идеологического (по Егору) верного ООП? Если существующие инструменты не позволяют выразить идеи — логично, что нужно создать новый инструмент
    • да, я не читал книги Егора — но то, что я вижу в его коде — меня повергает в лёгкий шок — резонный вопрос — если через 5-10-15 минут мне не стало понятно, то зачем я буду тратить время, читая книгу, чтобы понять базовые вещи
    • вполне допускаю, что в голове у Егора есть светлые идеи, но выразить их трудно покуда руки по локти в гавjava, звучит критика, но звучащие предложения не убедительны и в чём-то даже вредны.



    1. r0zh0k
      05.09.2016 13:48

      но мне до сих по не понятно — почему нельзя напилить свой язык

      Так в статье есть вполне понятный ответ на это.


      1. vladimir_dolzhenko
        05.09.2016 13:58
        +1

        внимательный читатель заметит

        уже звучало не первый раз, и в том числе и этом интервью


        объяснения, которые звучат — разумны, но не убедительны


        1. Source
          05.09.2016 20:01

          Вы хотите, чтобы и так печально известный ряд извращений ООП продолжился?

          «C++ is history repeated as tragedy. Java is history repeated as farce.»
          – Scott McKay

          «Java, the best argument for Smalltalk since C++»
          – Frank Winkler


          1. yegor256
            05.09.2016 23:25

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


            1. Source
              06.09.2016 01:04

              Вот профиль Scott McKay на LinkedIn, не знаю где именно он это сказал, но получилось красиво и метко )
              В принципе, можно у него самого уточнить…

              В Вашей коллекции не хватает:
              I'm sorry that I long ago coined the term «objects» for this topic because it gets many people to focus on the lesser idea. © http://c2.com/cgi/wiki?AlanKayOnMessaging

              Ну и несколько статей на тему (хотя возможно Вы их уже читали):
              Ten Things I Hate About Object-Oriented Programming
              The Deep Insights of Alan Kay
              Object Oriented Programming is an expensive disaster which must end
              Fifty Questions for a Prospective Language Designer

              P.S. Лично я считаю, что ООП не вредно, как средство высокоуровневого проектирования. Вред приносят попытки искусственно сделать всё объектами… Во-первых, они довольно корявы во всех мейнстрим-реализациях. Во-вторых, это не даёт никаких практических преимуществ.
              Поэтому мне ближе ООП в том виде, в котором оно существует в BEAM (где в роли объектов выступают легковесные процессы, внутренняя реализация которых насквозь функциональна), а не то, что может предложить JVM.
              Вам же, насколько я понял, нравится придерживаться идеи, что всё является объектами… Поэтому интересно было бы почитать Ваше мнение на тему Smalltalk.


              1. yegor256
                06.09.2016 01:40

                Нет, у меня нет такой идеи. Я не считаю, что все должны быть объектами. Я считаю, что объекты должны быть объектами, а не структурами данных. Вот про мое отношение к объектам.


                1. Source
                  06.09.2016 11:32

                  it is an independent entity with its own life cycle, its own behavior, and its own habits.
                  Я полностью согласен с таким определением объекта (впрочем, точнее было бы называть это субъектом или актором). Но вот дальнейшие примеры в статье показывают профессиональную деформацию от долгого программирования на мейнстрим-языках. Взять тот же файл, это совершенно пасивная сущность, без какого-либо собственного поведения, по сути тупо набор байтов. А XmlParser — это очевидно активная сущность, представляет она человека, читающего и интерпретирующего файл. Другими словами, любая человеческая активность может быть выражена объектом. Похожая метафора с того же OOPSLA97: «An object is a virtual server».
                  Таким образом, годный объект — это виртуальный сервер, обеспечивающий выполнение/автоматизацию некоторой активности, которая могла бы быть выполнена человеком, над некоторым набором данных (состояние объекта), на основании обработки входящих сообщений (аля приказы начальника, просьбы коллеги и т.п.)
                  Фиговые объекты сразу видно по действиям, которые описываются возвратными глаголами (с постфиксом -ся). Например, файл открывается, строка пишется, файл закрывается.


                  1. yegor256
                    06.09.2016 19:05

                    Вам может понравиться вот это выступление, где я анализировал разные определения объекта, от разных авторов. Если кратко, то называть объект «сервером» или «компьютером» мне кажется неправильным.


                    1. Source
                      07.09.2016 03:11

                      Я понял, что Вам это кажется неправильным, но не понял почему Вам так кажется… Единственный аргумент, который Вы привели, что объект-сервер возвращает управление обратно серверу-инициатору сообщения или в main-loop… если быть точнее, то возможен ещё вариант передачи управления следующему объекту-серверу (аля конвеер). Что в этом неправильного? Да и как иначе, сделать 1 единственный объект на всю программу, который никому управление не отдаст, ну ok… вот это как раз и будет процедурное программирование :-)


                    1. Source
                      07.09.2016 03:23

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


            1. Source
              06.09.2016 01:35

              По поводу источника «Java and C++ make you think that the new ideas are like the old ones. Java is the most distressing thing to happen to computing since MS-DOS.» — это из выступления на OOPSLA97


              1. yegor256
                06.09.2016 01:39
                +1

                Спасибо большое, обновил.