В программировании я постоянно задаюсь вопросом, правильно ли я решаю задачу. Сперва я много кодил в парадигме объектно-ориентированного программирования, и не думал, что можно как-то иначе. MVC, сильная статическая система типов, паттерны, попытки понять подход к построению архитектуры, в которой решения сегодня не станут палками в колёса завтра... В связи со сдвигом в сторону функционального программирования, начавшимся в последние годы, я стал пробовать новые подходы. Scala в этом плане была отличным выбором — горазде больше возможностей, при том же уровне уверенности в коде, которую даёт система типов. Мультипарадигменность, которая позволяет начать с "java без точки с запятой" и постепенно наращивать используемый арсенал приёмов — анонимные функции/замыкания, неявные параметры, вытекающий из них ad-hoc полиморфизм, моноиды, монады, множественное наследование с хитрыми правилами линеаризации трейтов... При всём этом необходимо уметь быстро разбираться с большими базами кода, быстро по ним перемещаться, игнорируя нерелевантые участки и быстро понимать релевантные. Это похоже на чтение книги по диагонали, с целью понять и удержать в голове одну сюжетную линию, протекающую на фоне сотен других — навык, которому я учился не один год... Если так посмотреть, программирование кажется очень сложной дисциплиной, и я тут просто выпендриваюсь тем, какой я умник. Но я хочу сказать другое — я считаю, что за исключением тех случаев, когда нужна высочайшая производительность и максимально эффективное управление памятью, всё программирование совершенно зря переусложнено. Для того, чтобы получить список уникальных друзей пользователей, поставивших посту лайк, не нужно знать, что монада это моноид в категории эндофункторов, и не нужно иметь десяток зависимостей по 500к строк кода. Для того, чтобы писать многопоточное приложение, не нужно рвать волосы на голове из-за того, в каком порядке надо блокировать ресурсы так, чтобы всё приложение не зависло в ожидании самого себя. Почему я так думаю? Потому что я знаю, как можно иначе. Ни Scala, ни Kotlin, при всех своих функциональных фичах и сильной типизации, не решают фундаментальных проблем, которые делают программирование таким сложным — проблемы мутабельности и состояния. В программах постоянно передаются туда-сюда изменяемые объекты, и они постоянно меняются, и за всем этим надо следить, но это невозможно. Все навороченные системы типов нужны нам, чтобы хоть как-то помочь в том хаосе из постоянно изменяющихся объектов, которые нас окружают. Последние полгода я изучаю Clojure, и писать на ней намного проще, чем на чём-либо, что я до неё пробовал. В Clojure любые данные иммутабельны. Программа состоит из набора преимущественно простых функций, которые принимают иммутабельные данные и возвращают новые, иммутабельные данные. Такой подход, конечно, вызывает сомнения — не слишком ли сильная будет нагрузка на сборщик мусора? Не слишком ли много придётся тратить времени на создание промежуточных классов, которые необходимо будет создавать при трансформации и аггрегации данных? Clojure отвечает на это так: за счёт того, что данные не изменяются, при создании изменённого объёкта можно часть данных не копировать, а просто взять из предыдущего объекта. Что касается бойлерплейта с промежуточными классами, то Clojure... таких не имеет — это динамический язык со слабой типизацией, и данные (по большей части) представляют из себя листы и мапы. На первый вгляд, программирование без классов кажется безумием — как тут за чем можно уследить, если нам и с типами и поддержкой IDE трудно писать программы?! Мало нам JavaScript'а?! Но за счёт иммутабельности и того, что функции по большому счёту везде чистые, даже несмотря на динамичность языка, в Clojure всё равно проще понимать программу — нет скрытых зависимостей состояния данных, нет необходимости дежрать в голове все места, где ещё меняются объекты, с которыми я сейчас работаю. Так же оказывается, что когда программа состоит по большей части из иммутабельных данных и функций, изменяющих эти данные, то она не только проще, но и намного короче. Речь идёт о сокращении кода не в 2-3 раза, как это может рекламировать Scala или Kotlin по отношению к Java, а в десятки раз. Мне это кажется невероятным и потрясающим, и я могу ещё долго говорить про Clojure... В программировании я постоянно задаюсь вопросом, правильно ли я решаю задачу, и я по-прежнему не всегда могу с уверенностью ответить на этот вопрос, но изучение Clojure существенно расширило мой кругозор, и дало ещё одну точку зрения на то, что и как я делаю, и это применимо ко многим популярным сейчас языкам, будь то Java, Scala, Kotlin, Swift, C# или что ещё. В связи с этим у меня есть совет. Если ты ООП-программист, заинтересованный в расширении кругозора, то изучи Clojure, этот язык предоставляет интересную и более простую точку зрения на то, как можно решать проблемы написанием кода.