Жизнь без объектов

http://skipoleschris.blogspot.co.uk/2012/04/life-without-objects.html
  • Перевод
(Перевод)

Последние несколько лет я провел в изучении и экспериментах со многими языками программирования. В частности, я начал использовать Scala как основной язык, стараюсь использовать функциональный стиль везде где это возможно. Меня также весьма заинтересовал Haskell (чистый функциональный язык) и Clojure (современный диалект Лиспа).

Таким образом, я постепенно отказываюсь от объектно-ориентированной парадигмы, несмотря на то, что использовал в основном её последние 17 лет моей профессиональной деятельности. У меня появляется чувство, что объекты это то, что мешает нам писать лапидарный, структурированный и повторно используемый код.


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

Обещания ООП


В начале девяностых объекты были новыми и интригующими. Приверженцы этой новой парадигмы обещали возможность создания повторно используемых классов и паттернов, и это звучало заманчиво. Возможность комбинировать эти классы в многократно используемые и настраиваемые бизнес компоненты казалась Святым Граалем индустрии ПО. Разработчики новых языков, таких как C++ и позднее Java, поддержали пропаганду ООП как способа делать классное ПО.

Бизнес компоненты нельзя использовать повторно

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

Единственный способ сделать повторно используемые бизнес компоненты на этом уровне — сделать их сверх-настраиваемыми путём добавления таких штук как движки правил и встраиваемые языки. Такую модель я бы не стал называть моделью компонента. Скорее моделью очередного экземпляра bloatware. Обещание о повторном использовании ушло, люди либо покупали огромные bloatware системы(неудачники), или разрабатывали свои специальные бизнес объекты в своих собственных проектах.

С паттернами не сделать структурированное ПО

Следующая вещь которую мы поняли — надежды на паттерны проектирования не оправдываются. Паттерны не приводят к хорошей структурированности. Напротив, они приводят к чрезмерному усложнению программ, трудностям в понимании кода и дороговизне сопровождения. Некоторые паттерны стали даже анти-паттернами (например, паттерн singleton приводит к невозможности создания модульного тестирования).

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

Фреймворки классов и компонентов не очень эффективны для повторного использования

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

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

Наследование приводит к хрупкому ПО

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

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

Нарушение инкапсуляции

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

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

Появились даже антипаттерны, которые позволяют создавать объекты с инкапсулируемым состоянием без поведенческих методов (Java Beans, Data Transfer Objects и т.п.). Если мы делаем такие объекты, почему бы не использовать просто структуры вместо объектов?

Изменяемое состояние — причина проблем

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

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

Жизнь без объектов


Итак, можно ли отбросить свой 17 летний опыт и задуматься о жизни без объектов? Я пока не уверен, что дошёл до полного просветления на этот счёт. Но использование мультипарадигменного языка Scala позволяет мне обойти многие ограничения ООП.

Например, наличие в Scala такой фичи как mixin traits позволяет полностью отказаться от наследования реализации. Использование немутабельных значений и коллекций делает код более простым в понимании и отладке.
Функции как обобщённые абстракции и классы типов для расширения поведения позволяют писать хорошо структурированный и повторно используемый код. Принцип single responsibilities в этом случае выполняется идеально.

Фактически, я понял что стараюсь как можно больше использовать простые объекты в форме case classes для представления структур данных. Методов у таких классов мало, они предназначены только для облегчения работы с данными. Для группировки функций я использую mixin traits. Компоненты, которые я проектирую, просто собирают различные связанные по смыслу функции, которые преобразуют данные из одной формы в другую.

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

(Примечание переводчика: в этой статье хотелось бы акцентировать внимание на отношение опытного ООП программиста к ООП. Я не знаком с языком Scala, а соответственно и со специфичными для Scala терминами.

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

По поводу возможностей Scala. Видимо, они действительно покрывают весь спектр случаев, с которыми приходится иметь дело в ООП. Хотелось бы добавить, что возможности Erlang или Haskell делают это ничуть не хуже.
)
Метки:
Поделиться публикацией
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 226
  • +38
    Наконец кто-то в этом признался!
    • 0
      Поддерживаю!
      • 0
        Придется согласиться — ООП действительно излишне сложен.
        Единственное, что в нем просто — точка входа.
        Обманчивая простота ООП больше привлекает начинающих программистов, нежели «сложное» функциональное программирование.
        Так что обучение, думаю, все равно будет идти по пути «процедурное программиование — ООП — функциональное программирование».
      • +4
        Мне кажется, выбор парадигмы программирования сугубо личное дело.
        Лично для меня таскать структуры туда-сюда, как например в C, тоже не комильфо.
        Для других, возможно, ОО-подход сравним с демонизмом.
        • +6
          Согласен, просто как бы это двусмысленно не звучало — надо знать меру. Конечно, на мой взгляд, не все надо делать объектами просто потому, что большие дяди так сказали. Хотя, безусловно, дядей надо слушать и много читать, но и своя голова на плечах должна быть.
          • +3
            Возможно, это потому, что вы не вышли за пределы императивной парадигмы.
          • +8
            Перестаньте писать классы — практическая реализация жизни без ООП.
            • +4
              Есть куда более ясное послание, старое как божий день:

              Почему объектно-ориентированное программирование провалилось?

              Впрочем, опытные программисты всё это давно знают и само — чисто по своему опыту.
              • +1
                Отсылка к эфиру испортила все впечатление.
                • 0
                  М-м, а то, что «всё в математике заканчивается аксиомой» вас не насторожило?) А я-то, наивный, всегда думал, что аксиомы и неопределяемые понятия служат основой для доказательств. А оно вон как)
            • +12
              Не могу сказать что полностью согласен с автором. Бесспорно — ООП вышло не такой конфеткой как его преподносили изначально, но как по мне — многие задачи решать удобнее используя именно ООП, хотя и далеко не все.

              Главное не бить себя в грудь и доказывать «ООП рулит»\«ООП говно», а четко понимать цель той или иной задачи и грамотно выбирать инструмент.
              • 0
                Пожалуйста также укажите свой опыт в годах в ООП.
                • 0
                  Меньше чем у автора топика. Порядка 5 лет.

                  Это имеет значение?
                  • 0
                    На мой взгляд, как-то странно мерить опыт использования парадигмы (да и в принципе опыт) в годах.

                    Человек за месяц может столкнуться с таким набором различных задач, который у другого наберётся лет за 10 (утрирую).

                    Автор, к слову, не упоминает очевидный факт — в своё время он отказался от функционального подхода в пользу ООП, на котором «просидел» 17 лет.

                    Я же соглашусь и чуть дополню Vendolin — для решения разных задач разумнее использовать подходящие для этого средства, а не тупо следовать «принятой» веры методологии.
                    • 0
                      А, да, если вас интересует мой опыт ООП в годах — 10 лет.
                      • +1
                        простите, вы уверены что от функционального а не процедурного он отказался? До ООПа доминирующей, если я правильно помню, была парадигма процедурного программирования (c, pascal, etc), а функциональное вроде никогда в мейнстриме не сидело…
                        • 0
                          Ошибся, но суть не в этом, а в том, что в своё время автор отказался от используемой им парадигмы в пользу ООП.
                  • +2
                    Mixins тоже являются частью ООП и с ними, как заметил автор, жизнь становится легче. Так что в целом от ООП отказываться смысла нет, но сделать ЯП более гибкими не помешало бы.
                    • +36
                      М, хотелось бы конкретики и примеров. Вроде «вот такая штука сделана на ООП и она не работает, а вот штука сделана на Scala и она правильная и хорошая». Может не сюда, в виде отдельной статьи. Неужели все многочисленные стандартные библиотеки для ЯВУ, сами ЯВУ в основе которых лежит ООП, фреймворки для создания графических интерфейсов, веб-приложений, ещё море библиотек, которые в подавляющем кол-ве случаев написаны на ООП и которые используются очень широко, и продукты написанные на которых отлично работают и развиваются, что все они «неправильные», все «не работают»? С трудом в это верится.

                      Гораздо легче поверить в то что ООП не решает те проблемы, которые разработчики сами выдумали (неоправданные завышенные ожидания), но что само ООП вполне годная концепция разработки ПО (не панацея, конечно).

                      Ну а если это действительно так и ООП это одно расстройство — хотелось бы примеров что бы убедиться в этом, и что бы другие разработчики в этом убедились, что бы в конечном итоге настало светлое будущее без гадкого ООП :)
                      • +1
                        Любая штука работает на ООП. Проблема в том, что код при этом многословен и запутан. По сравнению с другими парадигмами. Нет ни одного примера «тут не работает, а вот тут работает».
                        • +2
                          Речь не о том, работает ли по факту или нет. Думаю, что race1 под «работает» имел в виду именно «приносит конкретные бенефит».

                          То, что «под на ООП запутан и многословен» — абсолютно ни к чему не привязанное утверждение. Есть задачи для ООП, а есть те, которые с ООП не нужно пытаться решать.
                          • +1
                            «Любая штука работает на ООП. Проблема в том, что код при этом многословен и запутан.»
                            А можно примеры? Того, что _любая_ штука на ООП многословна и запутана.
                            • –3
                              Я не говорил что любая штука на ООП многословна и запутана. Но исходя из опыта я считаю что чаще всего это так. Как минимум ещё несолько человек считают так же. При желании посмотрите ссылки что привели комментаторы выше, очень интересный материал.
                              • +2
                                Ссылки — это «why OOP failed»? Этому тексту стопятьдесят лет, и он с тех пор не стал более аргументированным или менее демагогским.

                                «Но исходя из опыта я считаю что чаще всего это так.»
                                Примеры-примеры-примеры. Без примеров это все пусто.
                                • –2
                                  В первой ссылке вроде примеры.

                                  Но я подозреваю что «примеры слишком маленькие, мощь ООП раскрывается на масштабных проектах» и «просто автор примеров плохо знает ООП и его код плох».
                                  • +1
                                    «Первая ссылка» — это «перестаньте писать классы»?

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

                                    Так что за примеры того, что «чаще всего это так» не работает.
                              • 0
                                Александр Степанов эту сложность объясняет примерно так:

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

                                Тоже самое и с программированием: сначала вы должны начинать развивать алгоритмы, и только в конце этой работы приходите к тому, что вы в состоянии сформулировать четкие и непротиворечивые интерфейсы. Именно из-за этой неразберихи в ООП так популярен рефакторинг — из-за ущербности парадигмы вы просто обречены на переписывание программы, уже в тот самый момент, когда только задумали её спроектировать в ООП-стиле».
                                • +2
                                  Я не очень понимаю, на чем он основывает свою аналогию.

                                  Ну и надо понимать, что в реальности «программирование» начинается с определения задачи, а она может определяться в различных терминах, и далеко не всегда это термины алгоритмов. Бизнес вообще редко мыслит алгоритмами.
                                  • 0
                                    Но реализовываете-то вы любой бизнес именно алгоритмами?
                                    • 0
                                      *реализуете(?)
                                      • +1
                                        бизнес как-бы с алгоритмами и рядом не стоит ;)
                                        компания может придерживаться жёстких правил, а может и «в свободном плавании» жить ;)
                                        • 0
                                          «Но реализуете-то вы любой бизнес именно алгоритмами?»
                                          Совершенно не обязательно. В частности, декларативно программирование — это не реализация алгоритма.
                                      • +1
                                        Оффтопик, но что-то я не припомню, чтобы в математике все _заканчивалось_ аксиомами — не задавшись набором аксиом, можно получить все, что угодно, хоть 2*2=100500.
                                        Касаемо ООП — в моей практике были и те, и другие примеры проектов. Т.е. которые, соответственно, хорошо или плохо ложатся в ООП парадигму, 50:50 где-то. Причем независимо от того, бизнес проект это или pet.
                                        • 0
                                          Речь не идет о том, как преподают некую теорию в ВУЗах, там да, сначала нам дают набор аксиом, после чего на основе их выстраивают стройную теорию. Дело в том, аксиомы получались не сразу, но после того как приходится работать с математическими объектами. Как пример, операции сложения и умножения, их коммутативность и ассоциативность появились задолго до того, как были написаны аксиомы поля над вещественными числами; были известны некоторые свойства вероятноти — такие как вероятность объединения 2х событий или пересечения — до того как сформулирована аксиоматика Колмогорова.
                                          Т.е. цель свести все к стройной системе, построенной из каких-либо независимых автономных блоков, очень сложно достижима на начальном этапе.
                                  • +6
                                    Поддерживаю. Такие заявления без практических примеров ничего не стоят. Слишком абстрактно все.
                                    • +5
                                      Не будьте столь категоричны. Любую программу можно написать на ассемблере (и даже будет работать), вопрос в удобстве.

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

                                      Да, там есть замыкания (и в java будут), там есть лямбды, но каждый раз создавая лямбду вы можете полагать (и будете почти правы), что используете синтаксический сахар для упрощенной записи анонимного наследника FunctionN с реализацией метода apply.

                                      И так со всеми функциональными конструкциями (даже patern matching в 2.10 сделают сахаром, преобразуемым в набор вызовов определенных методов).

                                      Некоторые (например я) считают, что scala гораздо удобнее, чем java, но даже если принять такую точку зрения, то я не представляю как тут можно сделать вывод о провале ООП.
                                      • +1
                                        Scala несет себе много фундаментальных отличий и большое количество улучшений, синтаксического сахара.
                                        Но, к сожалению, в Enterprise системах ее еще несколько больно использовать. В частности из-за еще относительно малого количества стабильных библиотек, которые были написаны специально для Scala. А использовать Scala вместе с Struts2, Spring Jdbc, Hibernate. Это будет намного больнее и уродливее, чем написать это просто на Java.
                                        • 0
                                          Чем это использование Hibernate в Scala больно и уродливо?
                                          • +1
                                            Например конвертацией Java'шных коллекций туда и обратно. Я знаю, про implicit конвертацию из/в java'шные коллекции. Но это тоже больно. Приплюсуем сюда struts2 с желанием итерироваться из JSP с помощью тега <s:iterate /> и получим совсем не клевую ситуацию, где нам приходится или проходить путь:
                                            java collection -> scala collection -> java collection. Или же в каждом конкретном случае смотреть, стоит ли коллекцию конвертировать из Java в Scala или нет.

                                            Помимо того добавим сюда тот факт, что на прямую мы не можем использовать Scala'шный Option и поэтому в POJO нам приходится изворачиваться и писать что-то в роде:
                                            import java.math.{BingInteger => JBigInt}
                                            import java.lang.{Long => JLong}
                                            
                                            class Pojo {
                                              <hh user=BeanProperty> var id: JBigInt = _
                                              <hh user=BeanProperty> var name: String = _
                                              <hh user=BeanProperty> var count: JLong = _
                                            }
                                            


                                            вместо желаемого

                                            class Pojo {
                                             var id: Option[BigInt] = _
                                             var name: Option[String] = _
                                             var count: Option[Long] = _
                                            }
                                            


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

                                            Но, к сожалению, я не очень хорошо ориентируюсь в Scala мире. Возможно есть фреймворки, которые либо грамотно оборачивают вышеуказанных монстров (Hibernate) либо же предлагают хорошую альтернативу (я слышал о веб-фреймворках Lift и Play, но, к своему сожалению не успел познакомиться с ними еще, так что не могу прокомментировать).
                                            • +1
                                              Очень рекомендую обратить внимание на Play 2.x. Он изначально проектировался как скала фреймворк.
                                              Работа с БД там не через ORM, у них своя прослойка в функциональном стиле:

                                              — Using JDBC is a pain, but we provide a better API
                                              — You don’t need another DSL to access relational databases, SQL is already the best DSL
                                              — A type safe DSL to generate SQL is a mistake
                                              — Take Control of your SQL code

                                              Если вас не оттолкнули эти принципы, то по ссылке подробней о каждом: www.playframework.org/documentation/2.0.1/ScalaAnorm
                                      • +1
                                        Отличнейший пример валидации в функциональном стиле с помощью Scala + scalaz gist.github.com/2660512
                                        А теперь представьте, сколько кода надо было бы написать в обычном стиле на типичном ЯП, чтобы добиться такого же результата.
                                        • 0
                                          С первого взгляда не очень понял что там и почему в обычном стиле это не будет просто :)
                                          • 0
                                            Комментарии в коде все доходчиво объясняют ;)
                                          • 0
                                            Не лучший пример.
                                            Всего-то раза в 2 больше, не более того.
                                            А при увеличении количества валидаций разница в количестве строк становится несущественной.

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

                                            И даже в случае с ФП: на java можно писать в ФП стиле используя анонимные классы. И даже суррогат замыканий там можно делать самому.
                                            Это будет многословно, это будет не красиво и противоестественно для тех, кто знаком с ФП языками. И разные библиотеки будут создавать разное ФП. Даже разные программисты на одном продукте могут, не заметив, создать разные наборы классов для реализации элементов ФП.

                                            Хотите хороший пример? Напомните про guava. Вот только надо еще доказать программисту, использующему guava, что он пишет с использованием ФП. После этого останется только показать как то же самое пишется с поддержкой ФП в языке.
                                        • НЛО прилетело и опубликовало эту надпись здесь
                                          • +2
                                            Что забавно, так это то, что, если ООП код писать, следуя принципам SOLID, то в конечном итоге мы приходим именно к функциональному программированию :-)
                                            • +5
                                              А если покопаться в ФП скалы, то мы поймем, что там везде ООП. Причем в самом классическом его понимании.

                                              Противопоставлять ФП и ОПП — это как сравнивать теплое с мягким. Они ни как друг на друга не влияют.
                                              • +2
                                                Ну так вся фишка скалы — в конвергенции ООП и ФП. Чего еще ждать от языка который бежит поверх ВМ в которой все пронизано объектами, при этом желая интеграции с существующим кодом?
                                          • +2
                                            Года четыре назад я тоже увлекался функциональными и прочими языками программирования, и понял, что не смогу смириться с их отдельными недостатками. И пока я буду писать приложения на стероидах, они будут на С++ с правильными классами и широким использованием паттернов.
                                            • +6
                                              С каждым разом все больше убеждаюсь, что подобные статьи читать в непрофессиональном переводе нет никакого смысла. Формулировки вроде понятны, а чтобы добраться до смысла, приходится перечитывать по два раза. Прочитал первую треть, плюнул и пошел читать оригинал.

                                              За ссылку спасибо, за перевод не зачет.
                                              • –1
                                                К сожалению так почти с любым переводом, в любой области.
                                              • +2
                                                Вопрос не в том какой инструмент использовать, а как понимать задачу. Плохой код можно писать на любом языке. К тому же, использование функций вместо объектов, приводит к излишней фрагментарности кода.
                                                • –5
                                                  Согласен с автором ) мы загоняем себя в жесткие рамки, а потом сидим и чешем репу, как же их обойти не написав кривой кастыль :(
                                                  • +1
                                                    А с автором оригинальной статьи можно как-то связаться?
                                                  • +8
                                                    Мне лично ООП помогает поддерживать код. Плюс показывает, насколько хорошо я понимаю предметную область, насколько структурно мыслю.

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

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

                                                    А паттерны — это просто кусочки, вырванные из контекста. Вот смотрите, есть у нас принцип — инкапсуляция. Есть рекомендация, вытекающая из него — низкая связанность. Есть два принципа SOLID, в паре работающие на низкую связанность прямым образом — это DIP и SRP. И из этих двух принципов вытекает конкретный паттерн стратегия, который решает вполне четкую __локальную__ задачу, но является частью СИСТЕМЫ.

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

                                                    • 0
                                                      «показывает, насколько хорошо я понимаю предметную область»
                                                      вы не могли бы в двух словах — но поподробнее эту мысль раскрыть?
                                                      • +2
                                                        Если я не могу разложить по DDD классы сущностей и отношения между ними — значит, пора учить матчасть.

                                                        То есть если не ясно, какие есть объекты и отношения между ними, то суть не схвачена.

                                                        Пример. Если вы пишете Crm, и у вас еще нет ощущения, что нужна сущность клиент, причем сложная (составная) — прекратила писать код и получше изучите предметную область.

                                                        Не все можно смоделировать инструментами ООП, но очень многое
                                                        • +1
                                                          В старые времена, когда не было такого термина «Code First» мы разлагали предметную область на таблицы БД и связи между ними — это называлось ER диаграммами. Обратите внимание, что в большинстве, как мне кажется, систем, таблицы и классы-entity мапятся один к одному. Так что, когда вы разлагаете предметную область на entity, это не ООП, точнее не обязательно ООП.

                                                          Вы упомянули о бизнес-процессах. Есть такой «процессный подход к управлению», я думаю вы знаете об этом, был популярен в консалтинге какое-то время назад (может и сейчас). Там в основе всего – процессы (процесс Заказа, процесс Отгрузки и т.п.). Такие вещи, как записи в базе данных или бумажные документы, считаются артефактами процесса. В связи с использованием ООП (и других частных методологий типа DDD) внимание сместилось в сторону артефактов (1С, например, называет себя «документо-ориентированной» системой). В результате в системе вы можете найти таблицу «Заказ», но вы нигде не найдете «Процесса Заказа», он размазан по всей системе.

                                                          И еще важный момент — модель (не смотря на спекулятивное использование этого термина) — это не entity — это некий набор алгоритмов, функций.
                                                          • 0
                                                            Есть ещё мнение, что некоторые программисты любят привязаться к старой методологии потому что та методология была первой что они узнали и от старого коня отказываться трудно, но прогресс ушёл вперед. Раньше были первичны данные(те же таблицы) и тогда и до сих пор некоторые отталкиваются от них. И это было правильно на тот момент. Примерно также, как то, что землю можно было считать плоской. А теперь мы знаем что земля круглая и плоской она кажется лишь потому, что мы очень маленькие. И теперь первичные не данные, а предметная область в целом, которая рождает две низкосвязанные части: базу данных и её связи (сделанные по принципам построения БД) и модель предметной области(домен) в коде по принципам ООП (в т.ч. и процессы и сущности и агрегаты) Но т.к. всякие сайты визитки слишком просты, чтобы изучать подобный подход, а старые системы те вообще и ООП-то используют лишь наминально, то появляется большое кол-во споров, причина которых — недопонимание сути вопроса.
                                                            • +2
                                                              В свое время писал отталкиваясь от данных, несколько лет писал по книжкам DDD, даже считал это подход вполне адекватным. Но — полезно знать много технологий, чтобы сравнивать и делать выводы. Разработка набора entity в DDD и разработка таблиц БД практически не отличаются по сути — как я уже выше сказал — модель базы данных раньше и называлась ER диаграммой (Entity relationship). А процесс разработки этих самых entity начинается с анализа того, что происходит в бизене — то есть с процессов. Я не заметил в DDD методике фокуса на процессы — во всей книжке Эванса нет ни одной activity диаграммы или workflow.
                                                              Да, так что я хотел сказать. Из тех технологий, с которыми я работаю, программные сущности больше всего отвечают реальным сущностям в такой штуке как OLAP кубы. В базе данных может быть legacy структура таблиц, по большому счету руководству предприятия плевать какие там классы в программе. Но когда менеджер таскает dimensions и measures в сводной таблице excel — они не могут не соответствовать его бизнесу — иначе он не поймет данных отчета.
                                                              Многое в ООП — это не плохо, но это чисто инфраструктурные вещи и ошибка полагать что DDD помогает лучше понять или отобразить предметную область — это просто еще одна разрекламированная patterns and practices.
                                                              • +2
                                                                да можно вообще писать всю логику в БД. та же Postgre это позволяет.

                                                                а веб будет просто дергалка хранимок.
                                                              • 0
                                                                Почему «слишком просты»? Данные домена проецируются на данные БД один к одному, наоборот идеальная ситуация для изучения, имхо.
                                                              • 0
                                                                1. Да, согласен. Но иногда от БД надо отвязаться — быть может, завтра у вас бэкэндом будет не реляционная БД, а какой-нибудь Монго

                                                                2. честно, хз. я плохого мнения об образовании по менеджменту в РФ. у нас нет гениальных школ, таких, как сделали в GE люди с Джеком Уэлчем, и выдающиеся бизнесмены типа Галицкого пока не преподают в вузах (и вряд ли будут).
                                                                равно как и кейсовый подход.

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

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

                                                                то, что вы описали, мы применяем в отделе. фокус, конечно, на процессах, и показателях этих процессов (KPI).

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

                                                                3. вообще за слово «модель» нужно оторвать кому-то руки.
                                                                я поэтому сейчас за DDD. там есть четкие понятия. есть сущность — объект без состояния, это тупо класс со свойствами и базовыми методами (к примеру, у комплексных чисел метод — принять другое комплексное число на вход и отдать результат умножения новой сущностью на выход — хотя если «ооп ради ооп», то нам уже нужен оператор умножения N комплексных чисел), есть класс-коллекция, есть storage, который по заданным условиям вернет коллекцию объектов-сущностей.

                                                                а MVC это спорный паттерн. щас попробую топик зарядить.
                                                                • 0
                                                                  Вот видите, вы все без меня знаете на самом деле :)
                                                        • +2
                                                          Особенно доставляет, когда адепты Java говорят адептам C#, например: «создавать инстанс генерика в обобщенном типе» неправильно и не по дзену — «если в c# так можно, это не значит, что это _правильно_». — а нужно всего лишь выделить абстрактную фабрику.)
                                                          • +4
                                                            Многие так называемые паттерны — лишь набор задокументированных ворк-араундов вокруг лимитаций наложенных языком. Так что я бы забил и радовался, если C# позволяет такое писать.

                                                            У меня в Java такого нет и, поэтому, я буду дальше продолжать писать абстрактные фабрики. Не потому что это _правильно_, или клево, или мне это нравится, или я получаю удовольствие от усложнения кода, а потому что язык, на котором я пишу каждый день накладывает на меня такие ограничения.
                                                          • +1
                                                            Главное заблуждение статьи, что она названа «Жизнь без объектов», а критикуются в ней ООП. Абсолютно неверно. И в конце еще приводится фраза, применять mixin traits вместо наследования. Так к чему их применять?

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

                                                            Как мне кажется объекты очень хорошо решают задачу модульности данных и функций, например, в реляционных базах данных это задача сопряжена с трудностями. Например, имея объект студент, мы можем его спокойно поместить в коллекцию студентов в объект Группа. В реляционном подходе нам необходимо менять сущность студент, для того чтобы приписать его к некоторой группе (создание отдельной таблицы — неуклюжее решение).
                                                            • +2
                                                              Какой-то маркетинг булшит (если посмотреть на профиль афтора можно увидеть что он консультант, специализирущийся на Scala и Clojure).

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

                                                              Говорится что ООП это плохо, при этом как писать без ООП не говориться.
                                                              • –4
                                                                Говорится что ООП это плохо, при этом как писать без ООП не говориться.

                                                                Так, как писали до ООП. Модульность не в C++ придумали.
                                                                • 0
                                                                  Было бы странно если автор это имел ввиду, приводя в пример Scala, который даже если не учитывать что сам объектно-ориентированный, вдобавок ещё стоит на JVM, которая объектно-ориентирована вообще насквозь.
                                                                  • +2
                                                                    В чём состоит «объектно-ориентирована насквозь» для работчика, который использует всё это просто как библиотеку? Если Вы хотите использовать функцию из libc, то это можно сделать в ассемблере, в Си или в руби, какая разница, как эта функция реализована внутри?
                                                                    • 0
                                                                      Есть разница какой интерфейс она имеет, особенно если язык с этим интерфейсом напрямую работать не может, ну нет у него в синтаксисе понятия функция, есть только методы, принадлежащие классам.
                                                                      • 0
                                                                        Да, разница в синтаксисе, согласен. Но и только: если надо вызвать некоторую функцию X из модуля Y, то программист просто сделает `result = Y::X(args)`, а не будет задумываться, мыслил ли автор X концепциями объектов и сообщений, или же просто использовал классы как модули. Какое это имеет значение для того, кто просто вызывает библиотечную функцию?
                                                                  • –4
                                                                    Ну вообще, методами написания совта до C++, софт получался сильно дороже и намного менее надежным, чем сейчас. Вспомните windows, word, и прочую хренотень.
                                                                    • +4
                                                                      Парадигма программирования — далеко не самое важное, что влияет на цену и надёжность. Чёткие спецификации, хорошая архитектура, автоматическое тестирование — всё это не зависит от парадигмы.
                                                                      Но если уж на то пошло, то и до плюсов были целиком объектно-ориентированные языки, тот же Smalltalk.
                                                                      • –4
                                                                        Я не имел ввиду конкретно C++, а ООП в целом. Прсото C++ это первый широко используемый объектно ориентированный язык.
                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                          • 0
                                                                            Скажите об этом Алану Кэю
                                                                      • +2
                                                                        Модульность, это важно, но не самое главное. Вообще, странно приводить в пример Scala, которая обладает как раз очень мощной объектной системой в статье с таким названием. Зато если взять Clojure, то там как раз действительно не будет объектной системы в привычном по ++/#/J понимании. Взамен этого будут полиморфные функции, мультиметоды/протоколы и прочее. Отказ от ООП не означает возврат к процедурному стилю, не путайте его с ФП.
                                                                        • 0
                                                                          Это спор о терминологии. Очень долго термин «ООП» означал именно такую реализацию, которая привычна по C++ и Java. Только в последнее время, в связи с широким использованием Javascript в вебе и вне него, начинают говорить, что ООП бывает разное.
                                                                          • 0
                                                                            Вы же сами упомянули выше про Smalltalk. Неужто там такое же ООП как в C++/Java?
                                                                            • 0
                                                                              Как сказал Алан Кей, автор Smalltalk'а:
                                                                              Actually I made up the term «object-oriented», and I can tell you I did not have C++ in mind.
                                                                      • 0
                                                                        под понятием реюзабельный подразумевается что написанный класс использовать при написании 10 раз. Однако даже при легком изменении логики все иерархию как правило переписывают. В итоге бенефит сомнительный. Для использования пары повторяющихся методов выдумывают сложные иерархии классов. Настала версия 2.0 и все полностью переписывают заново. В этом смысле примеси немного облегчают жизнь, да.
                                                                        • –2
                                                                          Если вы не умеете пользоваться ООП для реюзабельности, не означает что ООП плохо. Просто им, как и всяким инструментом надо уметь пользоватсья.
                                                                          • 0
                                                                            Тут скорее не в инструментах дело, а в предвидении будущих задач, которые зачастую ещё не существуют. Когда разрабатывается одновременно два похожих проекта, то выделить общую часть для всех проектов такого класса не сильно сложно. А когда проект один и он первый в своем классе, то можно только гадать какая его часть может оказаться востребованной для повторного использования и имеет смысл тратить ресурсы на её универсальность и изоляцию (или хотя бы иметь в виду такую возможность), а какая будет уникальна и эти ресурсы будут потрачены зря.
                                                                            • –2
                                                                              То что вы говорите не зависит от парадигмы программирование. Если проект пишется кое как, не думая о развитии, и реюзе, какую парадигму авторы бы не использовали, хоть объекто-аспектно-функциональное программирование, получится говнокод.

                                                                              И наоборот, если понимать требования, куда проект будет двигаться дальше (присутствует стратегия развития), то даже на асме можно добиться реюза, но все таки лучше если это будет современный ОО язык.
                                                                              • 0
                                                                                Так я и говорю, что не от инструментов (в том числе парадигм). Но суть в том, что даже думая о развитии и реюзе можно не угадать направление в котором проект будет развиваться и какие его части, как и где будут реюзаться. Предусматривать всё — явный оверхид, не предусматривать ничего — сложности при малейшем изменении или попытке реюза. Требуется именно угадать что будет меняться, а что повторно использоваться, чтобы не тратить ресурсы зря на оверинженеринг при начальной разработке и на рефакторинг при развитии и повторном использовании.
                                                                                • +2
                                                                                  Именно поэтому, широко известные в узких кругах гуру советуют делать везде, где только можно минимальную реализация и пользоваться рефакторингом для дальнейшего развития. Так и говорят: «Если у кого и получается предсказывать будущее, то ему очень повезло. А я по старинке»
                                                                                  • 0
                                                                                    Не предусматривать ничего. Сложности возникают при несоблюдении процесса — отсутствии рефакторинга. Если же с ним всё хорошо, то:
                                                                                    1. Потраченное время на предугаданную вещь в случае угадывания равно приблизительно времени, которое потратится позже. Когда возникнет потребность.
                                                                                    2. Потраченное время на предугаданную вещь, которая не потребуется (не угадали) остается зря потраченным временем. Плюс к этому добавляется время на поддержку ненужного кода «на всякий случай». Или выпиливания.

                                                                                    Когда процесс налажен, то рефакторинг и тесты писать не сложно и менять код в случае небольших изменений тоже. Ведь если не предугадывать, то код всегда самый простой. А когда люди предугадывают, то у них и мышление построено так: не буду убирать код, который уже написан и еще не понадобился — вдруг понадобится. Тут не до рефакторинга. Получается дедушкин чердак со всяким хламом, а не код.
                                                                                    • 0
                                                                                      А по мне, так не всё так просто. Одно дело, когда речь идёт про то, как раскроить иерархию классов, да распихать методы по интерфейсам. Другое — когда принимаются те или иные ключевые архитектурные решения, изменения которых аффектят 90% написанного кода. Ну, например, на начальном этапе принимается решение использовать некое средство X (например, средство доступа к БД). На этот средство завязывается весь код. А потом выясняется, что полученный продукт должен работать на порядок быстрее, и это самое средство X является бутылочным горлышком. Итоговый рефакторинг — это переписывание большей части кода (по сути — всё пишем заново). Но можно было бы поступить и иначе — для средства X написать фасад, и использовать только его. И потом (когда возникнет неприятность с производительностью) — только его и переписать. По-моему, затраты несопоставимые.
                                                                                      • 0
                                                                                        Как-то нелогично, когда много работы связывается не с задачами, а с инфраструктурными средствами. Значит средство плохое, если не дает достаточной развязки. Почему код связи с БД должен влиять сильно на остальной код, который на него завязывается? Хотя, бывает, но всё таки не вижу выгоды и здесь в предугадывании. Придет новое требование — перепишем. Гораздо чаще на моей памяти проблемы возникали, когда наоборот — угадывали. Исходя из предположений: а вдруг база поменяется и т.д. Ни разу не менялась база, а вот код доходил до точки, когда у людей, его писавших возникало желание его с нуля переписать. Программисты же всегда оптимисты, если не пишут тесты и рефакторинг. Они всегда переоценивают свои силы. И происходит потому, что не верят, что напишут баги. И вот в «разработке архитектуры» по умолчанию думают, что код будет сразу верный и лучше предугадать и создать нужную гибкость. Я думаю, что даже в случае, описанном вами, когда вначале код завязался на что-то, а потом надо переписать, в большинстве случаев такой вариант окажется менее затратным. Чем поддерживать излишне гибкий код, когда даже угадали и пришло изменение требований и переписывать не надо.
                                                                                        Кто бы такие такие замеры времени делал и делал сравнения? Сплошной оптимизм в планировании. А выводы в случае неудачи планирования всегда обратные: не в том, что планировали преждевременно, а в том, что неправильно угадали.
                                                                                        • 0
                                                                                          На самом деле всё просто. :) Всё сводится к оценке рисков и вероятностей. Понятно, что для проектов «сделал и забыл» подходит принцип «Чем проще, тем лучше». Для проектов, которые предполагают длительный период развития, несколько релизов и т. п. — уже нет. Очевидно, что если переписывание кода «потом» будет менее затратно, чем сделать прослойку «сейчас» — то и вопросов нет. Код as simple as possible + тесты. Если же будущий рефакторинг может быть более затратный — то риски просто необходимо оценивать, исходя из текущей ситуации и предположений. И уже по результатам таких оценок принимать решения. И универсальных рецептов тут нет.

                                                                                          Про БД — пример то прост. Ну, например, «сейчас» код пишется с использованием прямых SQL-запросов к базе. Положим, MySQL. А то и SQLite. Прошло некоторое время, нагрузка выросла, выбранная БД не справляется. Что делать? Переписать весь код, который завязан на работу с БД. А это чуть меньше, чем вся бизнес-логика. Это большой рефакторинг или маленький? Было бы лучше, если бы сразу было принято решение использовать какой-нибудь ORM?
                                                                                          • 0
                                                                                            Мы сейчас начнем спорить исходя из собственных вкусов и примеров, которые каждый себе представляет :) Скажу только, что я был такого же мнения как и Вы. Но со временем мнение изменилось. Просто по опыту, что случалось, а что нет. У вас может быть другая статистика.
                                                                                            Все эти методики работают только при определенных навыках работы с кодом. Я и в сложных проектах вижу только такой путь — чем проще тем лучше. Не могу себе представить, где это не работает.

                                                                                            Можно в личной переписке погонять какие-то примеры. А то не сможем обоснований найти.

                                                                                            С примером с БД не вижу проблем. Тут надо смотреть. Если логику всю выполняет база с помощью запросов, то видимо слой будет, который эти запросы хранит. Не будут же они размазаны по всей иерархии? Ну и это не является какой-то хитрой архитектурой. После двух запросов и рефакторинга может выделиться объект, который оборачивает запросы в методы.
                                                                                            Далее, если база не справляется, это задача оптимизации. Стандартно и смотреть, как можно это оптимизировать. Кстати, правильный путь — базу грузить работой. Как раз предугадывание того, что база не справится — и попытка на этапе проектирования разгрузить — потенциальные проблемы. СУБД создают для работы. Для запросов. Для масштабируемости. Пусть и делают то, за что ей деньги платят ))
                                                                                            Когда тормозит, то:
                                                                                            1. Пытаемся решить железом. Дешевле.
                                                                                            2. Если не выходит первое, то пытаемся кешировать. Замеры, попытки кешировать, вплоть до того, что что возможно выделится слой кеша на апп-сервере, который будет фреймоврком Unit Of Work.
                                                                                            Можно и второй этап сразу с конца сделать — выбрать подходящий фреймворк (если замеры говорят, что база много где тормозит). Ну и переписывать не должно быть так уж много. Методы уже возвращают списки сущностей или принимают на вход. Переписывается ровно то, что тормозит — логика работы.

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

                                                                                            И на счет ORM. Какие-то объекты-сущности нужны. По условию, ORM не выбрали, потому как руками писали запросы. Но надеюсь, что какие-то генераторы классов были. Нет, то следующий шаг — сделать. Или может уже выбрали ORM, но тогда запросы в хранимках хранились, а не в коде.

                                                                                            Сразу же выбрать такую ORM, которая будет брать на себя функции СУБД, я бы не стал. Всё нормально с примером.
                                                                                            • 0
                                                                                              > Все эти методики работают только при определенных навыках работы с кодом. Я и в сложных проектах вижу только такой путь — чем проще тем лучше. Не могу себе представить, где это не работает.

                                                                                              Собственно, дополняя этот тезис, хочу сказать, что не только при определённых навыках, но и просто не во всех ситуациях. Факторов, на самом деле, много (характер задачи, размер команды, опыт членов команды, перспективы задачи и т. д. и т. п.), и то, что прекрасно работает при одной комбинации этих факторов, перестанет работать при другой. А так… Безусловно — у каждого свой опыт. Мне приходилось работать и в ситуациях, когда постоянный рефакторинг был возможен (и оптимален), а также в ситуациях, когда принятые «сейчас» решения уже нельзя было отменить, или это было ну ооооооочень дорого.
                                                                                      • 0
                                                                                        По-моему возвращаемся к необходимости угадывать будем данный кусок кода рефакторить или нет. Если 100% будем — покрываем его тестами или, хотя бы, пишем так, чтобы тестами было легко покрыть. А это иногда (часто?) приводит к усложнению кода. Хотя, конечно, сложность кода понятие относительное. Например, инкапсулированная агрегация может проще с одной точки зрения и сложнее с другой. Создать объект для присваивания приватному свойству в конструкторе просто, отследить эту зависимость нет, а изменить её без модификация собственно кода класса зачастую невозможно или очень-очень сложно. Передавать этот объект параметром конструктору сложнее немного, отследить эту зависимость проще и изменить тоже.
                                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                              • +1
                                                                                для работы с ФП нужна более качественная подготовка программиста как в области математики так и в области теории программирования.

                                                                                Некоторые примеры показывают, что нужно просто другая качественно подготовка, а не более качественная. При условии если мозг не испорчен императивщиной как у меня :) Более того, ФП более легко ложится на школьную математику без вводящих в ступор «математиков» выражений вроде x = x + 1;. Сами понятия «переменная», «поток выполнения», «ветвление», «цикл» очень плохо вводится без обращения к архитектуре компьютера. «Функция», даже «ФВП» более естественны что ли.
                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                  • –2
                                                                                    Напрасно вы так Haskell дискредитируете. Не нужна там теория категорий.
                                                                                    • НЛО прилетело и опубликовало эту надпись здесь
                                                                            • +1
                                                                              Самое интересное — почему стал возможен такого рода пост. Почему никто не говорит «долой функциональное программирование» к примеру. Как было сказано в посте — это была разрекламированная вещь. Некий продукт мог иметь в 90-е «конкурентные преимущества» уже только потому, что на коробке было написано «ООП». Да и сейчас, если вы устраиваетесь на работу в корпоративный сектор, паттерны спрашивают как катехизис на собеседовании. В этом что-то есть от сетевого маркетинга.

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

                                                                              А что касается самого по себе ООП, я думаю, уже никто не использует его в чистом виде в новых проектах. Посмотрите open source проекты на C# например — очень многие активно используют возможности ФП в C# (как сказано в посте «Такие тяжелые фреймворки быстро умирают и замещаются более легковесными библиотеками и наборами легковесных библиотек»).
                                                                              Да и многие ООП паттерны — на самом деле реализация тех возможностей, которые есть в ФП из коробки (strategy например). Паттерн Entity-Service-Repository — тоже нельзя назвать чистым ООП: entity слишком плоские, сервисы и репозитории тоже трудно назвать полноценными объектами — скорее контейнерами с процедурами/функциями.
                                                                              • –2
                                                                                C# идет по единственно правильному пути, на мой взгляд. Дорогу гибридным языкам!
                                                                              • 0
                                                                                Иметь доступ ко всем значениям объекта — неправильно, если мы говорим про инкапсуляцию. Кому нужны мои почки и правое легкое, чтобы общаться со мной? :)
                                                                                • +2
                                                                                  Врачу?
                                                                                  Телепорту? Или прийдется ждать пока Вы начнете поддерживать интерфейс телепортации.
                                                                                  • 0
                                                                                    Врачу отдельный интерфейс, доступ к которому он получает, применив метод «Наркоз». Телепорт… ну давайте помечтаем :)
                                                                                    • +1
                                                                                      Мне кажется телепорт упомянули в качестве неожиданного, заранее не предвиденного использования объекта. С другой стороны, в этом случае лучше дописать поддержку интерфейса телепортации для объекта. Другое дело, что не нужно везде реализовывать все возможные интерфейсы иначе код превратится в раздутую помойку.
                                                                                • +10
                                                                                  Очень странный набор умозаключений.

                                                                                  ООП противопоставляются такие вкусные и полезные вещи, как:
                                                                                  1) ФП. Учитывая приводимую в пример scala ФП и ООП не исключают друг друга.
                                                                                  2) stateless. Среди принципов «инкапсуляция», «наследование», «полиморфизм» нет слова «изменяемость». Если добавить в ООП удобные immutable структуры оно не перестанет быть ООП.
                                                                                  3) Поведенческие классы и классы с данными. Да, не канонический подход, но удобный и давно используемый в ООП.
                                                                                  4) mixin traits. Это удобная реализация множественного наследования. Чем она противоречит принципам ООП?
                                                                                  5) Функции как first-class citizen. Да, удобное и компактное представление для паттерна «стратегия», а так же некоторых других. Да, в ФП языках принято забывать некоторые паттерны, так как их реализация заложена в самом языке. Но это ни как не противоречит ООП подходу и не отменяет наличия в ФП языках своих паттернов (якобы их меньше, но не в этом суть).

                                                                                  Я бы согласился с тем, что ООП + immutable + ФП + некоторые другие вкусности, это лучше, чем ООП без всего перечисленного, но не понимаю каким образом это делает ООП подход устаревшим и не удобным.
                                                                                  • 0
                                                                                    Инкапсуляция инкапсулироует именно изменяемые данные. Причём незаметно и неизвестно как изменяемые.
                                                                                    • +3
                                                                                      Почему это?
                                                                                      С тем же успехом можно инкапсулировать неизменяемые данные.

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

                                                                                      Простой пример: многие immutable коллекции в scala скрывают свою реализацию и при преобразованиях просто возвращают измененную копию.
                                                                                    • 0
                                                                                      C трудом представляю себе ООП с неизменяемыми переменными…
                                                                                      • +1
                                                                                        Я тоже с трудом представлял, а потом открыл для себя scala.
                                                                                        Теперь не представляю как работать с многопоточностью не имея в языке удобной поддержки неизменяемых данных. Да и не многопоточный код зачастую становится проще для понимания.

                                                                                        Но я согласен, что полный отказ от изменяемых данных зачастую неудобен (хотя иногда жизнеспособен, взять хотя бы xslt). Авторы ФП языков тоже понимают, потому изменяемые данные тоже поддерживаются.
                                                                                        • 0
                                                                                          Спасибо за комментарий, задумался. Правда меня зацепил erlang, на scala уже времени нет)
                                                                                          • 0
                                                                                            Это не исключающий случай, эрланг очень маленький и концептуально целостный и требует относительно мало времени на изучение. Чего не скажешь о scala.
                                                                                            • 0
                                                                                              Erlang/OTP целостный, но времени отнимает кучу и есть куда копать (в сторону веб дева например). Невозможно постоянно учить новые языки, Asm, C, Ruby, Erlang, JS — что еще может поместиться в голове помимо этого? Есть Clojure, Haskell, Scala и куча других интересных вещей, но увы.
                                                                                              • 0
                                                                                                Опять про Groovy забыли…
                                                                                                Но вообще в голове всё поместится, было бы время и желание. Чем больше языков изучаешь, тем легче это даётся, потому что начинаешь понимать как все языки строятся из фич и что во многих из них очень много этих самых одинаковых фич. А чтобы выучить сам синтаксис — где ставить скобочку а где точку — вообще много времени не надо.
                                                                                                • +3
                                                                                                  Проблема не в синтаксисе а в инфраструктуре. Сами языки учатся чем дальше тем легче, но это разве что в академических целях. Но если работаете С++ программистом — изучите Boost, JS программистом — ориентируйтесь в популярных библиотеках типа JQuery/Backbone/etc (и как на них не просто писать, а писать красиво и общепринятым способом). Платят не за абстрактное знание языка а за умение быстро и понятно написать рабочий код без велосипедов, а это требует долгого времени изучения каждого стека.
                                                                                                  • 0
                                                                                                    Ну я конечно соглашусь здесь с нами, но всё равно, когда знаешь уже несколько языков/фреймворков, остальные даются всё легче и легче, ОСОБЕННО когда речь идёт о фичах в разных языках предназначенных для одного и тоже. (А не так что сравнивается assembly и jQuery).
                                                                                                    К примеру если взять PHP, Python и Ruby — и скажем вам сейчас надо написать вебприложение. Вы скорее всего начнёте изучать django/rails/{одна из десятков альтернатив для PHP}, и хоть все языки очень разные с разными стеками приложений и утилит, всё равно сами MVC фреймворки очень похожи, просто потому что разрабатывались для одной цели. Поэтому когда нужно будет изучать grails для Groovy, это уже пойдёт гораздо быстрее, вы просто будете узнавать все фичи.
                                                                                                    (но за пару дней конечно можно изучить лишь синтаксис, для эффективности требуется время, независимо от языка).
                                                                                                    • –2
                                                                                                      всё равно сами MVC фреймворки очень похожи, просто потому что разрабатывались для одной цели.

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

                                                                                                      P.S. django и rails альтернативы не php, а symfony/yii/zend/cake/kohana/… Альтернативы php — python и ruby.
                                                                                                      • 0
                                                                                                        (PS) я это и имел ввиду «django/rails/{одна из десятков альтернатив [django или rails] для PHP}»

                                                                                                        Как раз насчёт того что легко перейти на другой MVC фреймворк легко (а не на другую архитектуру и вообще другой проект/цели) я и писал. О чём мы спорим?
                                                                                                        • 0
                                                                                                          Цель у веб-фреймворков одна — выдать клиенту html (xml, json и т.п. опустим). Но вот подходы к её достижению могут быть разные. MVC один из них, пускай и доминирующий, но не единственный. Взять микрофреймворки типа sinatra или silex — MVC в них нет. Да и если цель другая, например, десктопные приложения, то переход в рамках MVC (не вебом единым) будет проще.

                                                                                                          Собственно хотел уточнить, что не то, что цель одна облегчает переход, а то, что архитектура одна.

                                                                                                          P.S. наверное надо было написать: «одна из десятков альтернатив на PHP»
                                                                                            • 0
                                                                                              Если найдете время на scala, то обнаружите знакомые моменты. В частности модель акторов в scala полностью заимствована из erlang.
                                                                                          • Такое ООП есть в OCaml.
                                                                                          • –1
                                                                                            >1) ФП. Учитывая приводимую в пример scala ФП и ООП не исключают друг друга.
                                                                                            ООП и ФП не очень уживаются друг с другом. Например отваливается полный тайп инференс, и систему типов приходится делать намного сложнее. Вспомните ужасные? extends и? super из Java. Вобщем-то из вещей на которые часто жалуятся в Скале, самое распространенное это сложная и замедляющая компилятор система типов.

                                                                                            >3) Поведенческие классы и классы с данными. Да, не канонический подход, но удобный и давно используемый в ООП.
                                                                                            Что вы подразумеваете под поведенческими классами и классами с данными? По моему, в ООП уже давно принято все классы разделать на 2 категории, value objects, immutable объекты и entities, которые mutable.

                                                                                            • +1
                                                                                              1) В скале выведение типов отвалилось только в параметрах конструкторов и методов. В любом случае их бы указывали явно для документирования, как сейчас указывают тип возвращаемого значения даже если он выводится.
                                                                                              «ужасные? extends и? super из Java» заменены на ковариантные и контравариантные типовые параметры. Они дают всю необходимую гибкость и при этом сохраняют все прелести статической типизации.
                                                                                              Вообще система типов в скале далеко не самая большая проблема скорости компиляции (неявные параметры дают большую фору), а сложной она становится только при написании сложных библиотек вроде коллекций начиная с 2.8 и не усложняет их использование.

                                                                                              >Что вы подразумеваете под поведенческими классами и классами с данными?

                                                                                              Не более чем последний абзац в пункте «Нарушение инкапсуляции», а именно выделение объектов с данными с простым интерфейсом и нескольких объектов с поведением, обрабатывающие эти данные. Вместо перегруженного интерфейса у объектов с данными «на все случаи жизни».
                                                                                              • –1
                                                                                                >«ужасные? extends и? super из Java» заменены на ковариантные и контравариантные типовые параметры. Они дают всю необходимую гибкость и при этом сохраняют все прелести статической типизации.
                                                                                                ? extends и? super это фактически урезанные existential types, они по своей мощности сильнее in и out параметров.

                                                                                                >Не более чем последний абзац в пункте «Нарушение инкапсуляции», а именно выделение объектов с данными с простым интерфейсом и нескольких объектов с поведением, обрабатывающие эти данные. Вместо перегруженного интерфейса у объектов с данными «на все случаи жизни».
                                                                                                Так а зачем перегружать интерфейс? Неужели нельзя писать в нормальном стиле?
                                                                                                • +1
                                                                                                  Так, стоп. О чем мы спорим?

                                                                                                  Можно ли писать хороший софт на Java? Можно! Удобно? Многим удобно.
                                                                                            • 0
                                                                                              Берем ООП + immutable + ФП + некоторые другие вкусности и получаем C# ;)
                                                                                              • +1
                                                                                                И вы правы, но все зависит от того что считать «другими вкусностями».

                                                                                                Начнем с immutable: var в C# есть, а вот val как-то не добавили. Всегда можно писать static, но надоедает.
                                                                                                Так же immutable и ФП тесно связаны с рекурсивными функциями, а в C# нет возможности контролировать преобразуется ли рекурсия к хвостовой.

                                                                                                Так же среди вкусностей в C# нет кортежей (не очень-то и нужны, но out параметры с immutable не дружат), нет pattern matching, нет встроенного механизма акторов, нет call by name, нет удобной записи для указания цункции в качестве типа параметра или возвращаемого значения, нет упрощенного синтаксиса для частичного применения, нет механизма, упрощающего карирование.

                                                                                                Но все это не отменяет того факта, что scala под CLR не актуальна, а Kotlin даже не пробовал ввязаться. У C# разработчиков есть уже довольно многое, и разработчики языка не дремлют: в последнем релизе добавили ковариантность и dynamic.
                                                                                                • 0
                                                                                                  И вы тоже правы. Но нектороые вещи из перечисленых вами всетаки есть.
                                                                                                  Теже кортежы (Tuple), Func — вполне удобно итд., но не буду вдаваться в детали.

                                                                                                  С основной вашей мыслью я полностью согласен — и ФП и AOP и другие парадигмы ни в коем случае не отменяют ООП. И вполне себе используются вместе.
                                                                                                  • 0
                                                                                                    Посыпаю голову пеплом.
                                                                                                    Программирую на C# и не знаю о System.Tuple. Оправданием мне может служить только то, что появились они только в 4.0 и использовать кортежи без pattern matching не удобно.
                                                                                                  • +2
                                                                                                    C# замечательный язык. Но, не все удобно в области ФП:
                                                                                                    new Dictionary<string, Func<string, string, Expression<Func<MyEntity, bool>>>>
                                                                                                    это из реального проекта.
                                                                                              • 0
                                                                                                Функции как first-class citizen. Да, удобное и компактное представление для паттерна «стратегия»


                                                                                                Исторически было ровно наоборот — функции как first-class citizen появились ещё в 1955 году, а паттерн «стратегия» придмали лет на 30 позже, именно для представления функции как объекта первого класса.

                                                                                                Вообще, лучше попытайтесь выбросить из головы все эти «дизайн-паттерны» — что немцу (швейцарцу Эриху Гамме (вслед за Иммануилом Кантом)) здорово, то русскому смерть. Вообще немецкоязычные люди, по моей практике знакомства с их бизнес-проектами в области ИТ, обладают замечательным свойством за счёт своей дисциплины долго поддерживать проекты с сильно запутанной или давно устаревшей архитектурой. «Дизайн-паттерны» — это разговор на изачально сильно изращённом языке, о чём ещё в 1996, сразу после «классической» книги, написал Питер Норвиг и в 2002 — Пол Грэхэм, с истоками происхождения этого языка.

                                                                                                «Дизайн-паттерны» — это, в общем, переложение на ОО-парадигму примеров из книжек начального уровня по обучению фнукциональным языкам.
                                                                                              • +2
                                                                                                Автор данной статьи говорит о той боли, с которой я и многие другие разработчики сталкиваются каждый день на работе.

                                                                                                Но полностью избежать изменяемого состояния нельзя, но я стараюсь на сколько это возможно редуцировать изменяемое состояние.
                                                                                                • 0
                                                                                                  Что изменяемые, что неизменяемые состояния — лишь абстракция. Всё изменяемо. В тоже время, объектов тоже не существует. Спор и головная боль крутятся вокруг абстракций, и это более чем удивительно.
                                                                                                  • 0
                                                                                                    Это как раз неудивительно. Что толку спорить над объективной реальностью ( данной нам в ощущениях :) )? А вот абстракций над ней можно наворотить много и разных.
                                                                                                    • +1
                                                                                                      Да. Т.е. у вас есть желание иметь объект, шаренный между разными потоками и смотреть, вылавливать какой поток в какой момент изменит его состояние, что приведет к крешу? Иметь stateful service(тогда когда это нафиг не надо), который время от времени крешится потому что потоки что-то не поделили? Отлавливать dead lock'и на продакшне? У меня такого желания нет. Я видел много разного говна. Большая часть трудноотлавливаемого говна, что я видел была связана с имзеняемым состоянием и многопоточностью. Так что философия в данном вопросе насчет абстракций и изменяемых состояний, на мой взгляд, немного не к месту.
                                                                                                      • 0
                                                                                                        Я не знаю каким местом думает тот человек, расшаривая объект между разными потоками, не позаботившись о разделении ресурсов. Учитывая, что вы видели много разного говна, думаю не трудно догадаться, про какое место идёт речь.

                                                                                                        Приходилось бороться с dead lock-ами на продакшене, и причиной всегда служил не язык программирования или среда, а отсутствие внимательности или мозгов проектировщика/программиста. Не надо перекладывать проблемы с больной головы. С таким же успехом можно заявить, что вообще весь мир не совершенен, зато вот в моём придуманном мире всё тип-топ.

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

                                                                                                        Если требуется написать высоконагруженное приложение с обязательным распаралеливанием процессов, это можно одинаково эффективно сделать что на Haskell, что на .NET (C#, F# в связке). Не надо морочить людям голову. Особенно молодым и неопытным.
                                                                                                        • +1
                                                                                                          Я и не говорю, что ООП — это плохо/хорошо.

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

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

                                                                                                          При тупом использовании ФП везде и всюду (если конктрено, то в узких местах) лучше жить не становится, а скорее даже хуже (говорю конкретно про Java/Scala).

                                                                                                          Так же как и при тупом использовании ООП там где оно нафиг не нужно.

                                                                                                          Автомагически можно получить себе только перформанс проблемы, долгие вечера дебугированя и раннюю потерю волос.
                                                                                                  • +7
                                                                                                    > У меня появляется чувство, что объекты это то, что мешает нам писать лапидарный, структурированный и повторно используемый код.

                                                                                                    Использование одной парадигмы для всех задач — то, что мешает нам писать лапидарный, структурированный и повторно используемый код.
                                                                                                    • +1
                                                                                                      ООП нужно для моделирования жизни.
                                                                                                      Для математики оно, очевидно, не нужно.
                                                                                                      • 0
                                                                                                        Для моделирования жизни хватит СУБД.
                                                                                                      • 0
                                                                                                        Со своей колокольни C(всякие постфиксы) программиста, поглядываю в сторону функционального программирования. И как-то у меня не складывается пазл, вот если мне допустим нужно реализовать некую структуру данных. Я понимаю, что многое конечно уже есть в функциональных языка, и да сях уже никто это сам не пишет. Но… эфективная реализация возможна? Ведь данные неизменяемы, а значит нужно копировать весь список, словарь и т.п. вещи?!
                                                                                                        • +1
                                                                                                          С точки зрения памяти менее эффективно. Но зато неизменяемость даёт доступ к распараллеливаемости, ну и в целом снижает вероятность ошибки.