Зачем нам ООП и что это такое

    Всем привет.

    Неделя статей на хабре посвященная ООП. Последняя статья вызвала у меня кучу эмоций и, к сожалению, очень плохих эмоций. Мне очень не понравилась статья. Почему? Потому что в ней передаются какие-то отрицательные эмоции об использовании ООП. Эмоции вызваны лишь тем, что человек не до конца понимает всю силу ООП и хочет убедить всех в том что ООП зло. Самое печальное что люди начинают прислушиваться и кидаться ужасными доводами, не имеющими ничего общего с действительностью. Я думаю что студентам такие статьи противопоказаны больше чем GoF, которых я бы давал как можно раньше. :)

    Начнем.

    Что такое ООП. ООП — это и ОО программирование и проектирование. Одно без другого бессмысленно чуть более чем полностью. Создано ООП для проектирования/программирования программных продуктов. Не для моделирования процессов. Не для проектирования протоколов, а именно для программных продуктов, для их реализации. Для упрощения системы, которая будет реализовывать протокол или бизнес-процесс или что-то еще.

    Когда вы начинаете использовать ООП, первое что вы должны сделать — это начать использовать объектное мышление. Я уже когда-то говорил что это самая большая проблема ООП, научиться мыслить объектно очень сложно. И очень важно учиться это делать как можно раньше (GoF с аналогиями типа мост, конструктор, фасад очень в этом помогут). Используя объектное мышление, вы легко сможете проектировать сложные системыИспользуя объектное мышление вы легко можете решить любую задачу (очень важно что любую задачу проектирования/программирования, если ее в принципе можно решитьабсолютно любую) оперируя объектами и взаимодействием между ними. Т.е. ООП без объектного мышления не позволит вам начать использовать всю силу и мощь ООП.

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

    Как же эти инструменты работают? Да проще пареной репы, потому что это все основано на привычных нам вещах. Люблю простые примеры из жизни:

    1. Наследование. Есть пекарь. Есть печь электрическая и газовая. Ваша задача смоделировать процесс приготовления пищи пекарем в каждой из печи. Решая задачу в лоб, у нас будет много дублирования кода из-за того, что сам процесс передачи пищи в печь и сама работа с печами идентичны для обеих печей. Но если мы включаем объектное мышление, и вспоминаем про инструмент наследование, то получаем примерно следующее (диаграмму лень рисовать, сорри):
    Есть печь (абстрактная печь). У нее есть поведение — включить, выключить, увеличить или уменьшить температуру, положить чего-то, достать чего-то и состояние — температура в печи, включена или выключена. Это отличный пример абстрактного объекта в котором соблюдены принципы инкапсуляции (при реализации я их обязательно буду соблюдать). И есть пекарь, конкретный такой пекарь Иван. Он умеет работать с абстрактной печью. Т.е. смотреть температуру, включать выключать и т.д. вы поняли. Сила наследования в том, что нам не придется переписывать нашего Ивана для каждой из печей, будь то электро или газовая печь. Я думаю всем ясно почему? Получается что инструмент применен правильно.
    2. Полиморфизм. Печи ведь по-разному работают. Газовая потребляет газ, электро печь — электричество. Используя полиморфизм мы легко меняем поведение в наследниках абстрактной печи.
    3. Инкапсуляция. Основная фишка инкапсуляции в том, что я не должен знать, что происходит внутри моей печи. Допустим, я вызываю не метод включить печь, а меняю ее свойство включена на значение true. Что произойдет в этот момент? Если принцип инкапсуляции не соблюден, то я буду вынужден печи сказать начинай потреблять горючее, т.к. я тебя включил. Т.е. пекарь знает, что печь потребляет горючее, знает, как печь работает. Или, например, мы не можем установить температуру печи ниже или выше определенного уровня. Если не соблюдать принцип инкапсуляции, то мы должны будем говорить печи проверь-ка текущую температуру, пойдет те такая? Т.е. пекарь опять слишком много знает о печи. Геттеры и сеттеры это средства языка, которые помогут нам легко реализовать отслеживание изменений состояния. Все. Если геттеры и сеттеры пустые, значит так надо на моем уровне абстракции. Геттеры и сеттеры — не могут мешать реализации инкапсуляции, криво реализовать инкапсуляцию может проектировщик/программист.

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

    Еще стали добавлять абстракцию, как еще один столп ООП. Я думаю, что это скорее верно, но уж очень попахивает КЭПом.

    Высказывания про типизацию меня тоже зацепили. Дело в том, что никаких проблем в том, с кем вы сейчас работаете из наследников нет. Если на текущем уровне абстракции вам важно именно использовать печь, то вам не важно какая она. Вы получаете печь? Вы решаете свои задачи? То то и оно… Почему вы считаете что это динамическая типизация мне не понятно. Вы хотели печь? Берите. Вам нужна электрическая? Ну извините, газовая вам уже не подойдет.

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

    Отдельно про DTO. DTO — это паттерн. Он позволяет создать объект, который передаст информацию другому слою, другой системе, короче куда-то чего-то передаст. Почему он не может быть рассмотрен мною как объект для меня вообще загадка. Где противоречие то? Является контейнером только? Ну и что?? Это же объект в рамках рассмотренной мною объектной модели на заданном уровне абстракции, где DTO — объект и часть декомпозиции.

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

    Еще говорят что некоторые вещи нельзя представить в виде объектов и их взаимодействия. Я уверен что это не так. Просто необходимо выбрать уровень абстракции верно. Будь то реализация протокола, слоя доступа к БД, подключения плагинов, менеджера задач, бизнес процесса, системы проектирования бизнес процессов т.е. все что угодно можно представить как объекты и их взаимодействие. Все можно реализовать как объекты и взаимодействие между ними. Хорошо это или плохо чаще всего зависит лишь от вашего умения мыслить объектно.

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

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

    Подробнее
    Реклама
    Комментарии 469
    • +14
      Сколько разных объяснений ООП читал, но про пекаря — никогда.
      • +1
        Мои студенты обожают. :)
        • +16
          Но ведь ужасная аналогия: «Он умеет работать с абстрактной печью...», «я не должен знать чего происходит внутри моей печи». Никто не умеет работать с абстрактной печью. Знание поведения конкретных моделей печей и отличие газовых от электрических и дровяных является одним из ключевых знаний для пекаря, и этот факт ломает всю аналогию к чертям. Почему её обожают?
          • +4
            Позвольте мне ответить:
            Пекарь должен знать, что умеет делать печь, как ей управлять, и ее характеристики. Как работает конкретная печь (ее механику и электронику) ему знать не нужно. Этот пример хорош тем, что он моделирует работу пекаря, аппроксимируя ее до управление посредством общего интерфейса…
            Это не аналогия а моделирование :)
            • 0
              Не знаю всей специфики приготовления в печи, поэтому буду говорить про плиту

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

              Можно придумать много другого, но одно из главных ограничений ООП проблема внесения изменений без изменения а) структуры классов б) интерфейсов класса. Условно говоря иногда для обобщения нужно добавить некий базовый класс, который не был предусмотрен заранее или удалить метод, который стал не нужен или изменить логику применения метода. ООП подходит для академического решения задачи (решили и забили/не трогаем), в реальности такого никогда не бывает!
              • +4
                Народ. Ну вы чего? В зависимости от поставленной задачи выбирается уровень абстракции. Если мне надо учитывать больше, то я буду учитывать больше. Вы сейчас просто изменили требования к системе пекарь-печь.

                Но! Изменение требований системы везде влечет полный ппц, какую бы методологию вы не использовали. Но ООП отлично приспособлено к внесению изменений при правильной декомпозиции и правильном проектировании, с учетом возможных изменений.
                • 0
                  Есть базовый класс — плита, в классах наследниках — газовая плита, электроплита, индукционная плита, создаем дополнительные методы в случае необходимости, или запрещаем вызывать те методы, которые несовместимы с выбранной плитой.
                  • 0
                    > создаем дополнительные методы в случае необходимости
                    в базовом классе? оО
                    • 0
                      Внимательно перечитайте комментарий еще раз, пожалуйста.
                  • 0
                    «Запрещаем вызывать» — это в каких ЯП доступно?
                    • 0
                      в любых, где можно кидать exception
                      • +3
                        Сурово. Хорошо, что вы не хирургом работаете.
                        • 0
                          Ибо нечего :) Вот в розетку тоже можно палец сунуть, но будет неприятно.
                          • 0
                            Палец не влазит, там несовместимость на уровне интерфейса.
                            А вот шпильки влазят…
                            • 0
                              Если наследник класса «человек» — «ребенок», то пальцы вполне могут влезть.
                              • 0
                                суровые у вас розетки. Даже у новорожденного пальцы существенно толще
                          • –3
                            Вариант — игнорировать вызов — переопределить метод пустым.
                            • +1
                              Напоминает защиту от лишних исключений (С++) : try { /* очень полезная работа */ } catch (...) { /* а это чтоб не ругалось */}
                              • –1
                                Плохая аналогия. Мы не скрываем что-то, а наоборот демонстрируем готовность выполнить :)
                              • 0
                                жестко )
                                ни эксепшины, ни пустой метод — не выход. Это значит, что неверно смоделировали.

                                на то ООП и нужно, чтобы его не хакать ))
                                class Oven
                                {
                                    public virtual Food Cook(List<FoodProduct> products) ....
                                }
                                


                                Нет?

                                В крайнем случае есть паттерны разные, вроде стратегий. Если не хочется заставлять саму печь готовить, а только пользоваться ею, нажимая на кнопки по разному.
                                • 0
                                  Что значит модификатор virtual?
                                  • 0
                                    Это я так написал, как псевдокод. Пишу на шарпе, там уместнее был бы модификатор abstract. Но виртуал более понятный другим (например, С++).

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

                                    Должна ли печь за это отвечать или только методы предоставить — включить, зажечь газ и т.д. — это зависит от задачи. Моделировать же один к одному реальный мир нет смысла.
                                    Если по задаче отдельно методы можно дергать и отвечать за готовку будет не печь, а повар, скажем, то можно применить другие, более сложные способы. Паттерн Стратегия, например. В зависимости от того, какую печь будет использовать повар, у него меняется взаимодействие с печью.
                                    • 0
                                      А-а, я привык к модификатору final для методов, которые нельзя переопределять :)

                                      Да, смоделировали неверно в какой-то мере, скажем предусмотрели отдельный метод для активации (включения нагрева) плиты, но не учли того, что могут появиться в продаже плиты с автоактивацией. Но во всём остальном модель подходит — готовит повар, а не печь. Почему бы не хакнуть, до следующего рефакторинга и внедрения той же стратегии.
                      • +10
                        А если мы находимся в открытом космосе на орбите Плутона, то пекарю нужно будет учитывать экстремальные температуры, отсутствие гравитации и кислорода. А у нас это не предусмотрено. ООП отстой!
                        • 0
                          Поставил плюс! :) Но надеюсь что это ирония и не более.
                          • 0
                            Перечитав ветку понял что это ирония. :) Видимо я уже готов ко всему, раз не понял это сразу. :) :)
                          • +2
                            Вот для вас и написана эта статья :)
                            Ну зачем предусматривать ВСЕ нюансы поведения модели и пытаться учесть всё-всё? Вы же при проектировании ПО так никогда не делаете, потому что YAGNI. И невозможно это. К ООП это не имеет никакого отношения. А только к выбору правильной абстракции.
                            • 0
                              Сущности тут разделены немного на другом уровне. Здесь сущность печи/плиты подает газ, зажигает спичку или включается в розетку. Ну или допустим тут адаптер/подмастерье это делает( по одному подмастерью на печь), пекарь лишь дает команду инициализироваться.
                              И если пекарь передает горячую кастрюлю в команду поставить на плиту, подмастерье проверяет и, узнав, что она хородная, выбрасывает исключение, или код ошибки возвращает.

                              Очень трудно найти полную аналогию на реальный мир, сдается мне точных аналогий нет и не будет, надо скорее наоборот — абстрагироваться.
                              • +7
                                Робко поддержу. Не то, чтобы я противник ООП, но есть определённая проблема в этом споре — очевидное преимущество использования ООП перед не-ООП не разъясняется, при этом мы постоянно обсуждаем подробности ООП.
                                Так вернёмся же к сути. Суть любого решения по архитектуре приложения — это ускорение и упрощение написания кода приложения, желательно в наиболее длительный промежуток времени.

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

                                Как минимум из недостатков здесь — затраты времени на этот процесс рассуждений (лично у меня эти рассуждения занимают обычно подавляющую часть времени при работе с ООП), никто не замечает, что всё это моделирование достаточно далеко от решение прямой задачи — реализации приложения «печь», к которому можно было бы приступить изначально. За время рассуждения выпустить печь 0.0.1, выдать своим пользователь новый фунционал бета версии.

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

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

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

                                Сам я использую ООП, но без фанатизма. Практически не использую паттерны. Пишу код с учетом того, что завтра у нас печи начнут не греть, а холодить, а еда вообще станет deprecated :) На длительную перспективу, это очень сокращает общее время разработки проекта — делай только то, что от тебя хотят сейчас, никаких додумок и предположений на будущее. Только одно предположение — завтра абсолютно всё может измениться.
                                • 0
                                  Пишу код с учетом того, что завтра у нас печи начнут не греть, а холодить, а еда вообще станет deprecated :)

                                  и

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

                                  разве не противоречат друг другу? Когда я слышу «а вдруг завтра у нас печи начнут не греть, а холодить, надо нам это предусмотреть», то с ужасом ожидаю очередного приступа ООП головного мозга — моей хронической болезни :)
                                  • +2
                                    Я думаю, в этом заключается основная суть претензий к ООП — труднодостижимая гибкость относительно требований.
                                    Архитектура классов может быть выверенной и вылизанной. Но это в полной мере возможно лишь в идеальных условиях при стабилизированных требованиях и понятной стратегии развития продукта.

                                    Для меня «дзен» ООП — это умение написать с его помощью такую архитектуру классов, которую не придется рефакторить до основания после очередной смены требований. И тут пригодится не сколько умелое применение паттернов, сколько интуиция по поводу того, что реально в будущем может потребовать изменений. И не впасть при этом в over-engineering и не стать архитектурным астрономом.
                                    • 0
                                      Я бы сказал, что это суть претензий к любой парадигме программирования. :(
                                      • +3
                                        ответили вместо меня, спасибо :)

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

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

                                        Когда нужно просто удалить файл, для этого можно написать функцию, которая делает только удаление файла. При этом не будет потрачено времени на осознание того, какие именно файлы функция должна удалять и зачем, кто её должен вызывать. Не будет потрачено излишнее время, не будут выстроены ненужные абстракции и связи, которые при дальнейшем изменении требований не будут мешать.
                                        • 0
                                          Так если нужно лечить или убивать нужно лечить или убивать. Это верно для любой (известной мне) парадигмы. Не предусмотрели возможности изменять тему письма — надо убивать литерал и вставлять вместо него константу, переменную из конфига, а то и процедуру/метод/функцию/кусок кода по получению его от оператора с поддержкой автодополнения. Какое это отношение имеет к ООП?

                                          И не нужно строить красивые системы классов, нужно строить рабочие, и рабочие не во всех ситуациях, которые пришли в голову, а рабочие здесь и сейчас, и ровно в том объёме, что указан в ТЗ (пускай оно и только в голове). Городить абстракции ради абстракций, систему ради системы, возможности замены одного сервиса на лету ради возможности не нужно.
                                          • +2
                                            Говорят, что системы нужно проектировать с учетом возможных изменений… Более того, оценка вероятных изменений должны быть этапом проектирования системы.

                                            Иначе было бы проблемно, в проекте на over 1 000 000 строк, все менять с ASCII на UTF8.

                                            Здесь и сейчас — жадный алгоритм, который, как известно, далеко не всегда является оптимальным.
                                            • 0
                                              Если никаких объективных данных для оценки нет? Если опыт кричит, что ASCII надолго не хватит, а SQLite два одновременных соединения не выдержит, а уже завтра гендир захочет посмотреть что там техдир в новой системе делает — это одно. Но если никто не может сказать какую фичу запросят пользователи после релиза (знали бы — сразу бы зарелизили) — несколько другое. Ну и, главное, программирование к анализу требований, включая оценку перспектив развития, имхо, мало отношения имеет. Это задачи маркетологов, аналитиков и т. п.

                                              • 0
                                                Почти всегда, есть что-то, что вероятно изменится. Для сайтов — новые пункты, языки, СЕО, для ИС — криптография, смена типов базы знаний…

                                                Ну и, главное, программирование к анализу требований, включая оценку перспектив развития, имхо, мало отношения имеет.
                                                Контрпримеры: 1. Программист должен программировать класс String подозреваю, что он может быть не только на char, но и на wchar.
                                                2. Программист должен программировать подсистему отображения набора информации, с учетом того, что информации может быть не 5 единиц, а over 9000.

                                                Другими словами, это не столько оценка требования и перспективы развития, сколько качество системы и уровень адаптации к различным условиям.
                                              • 0
                                                а в чем проблема в проекте на 1 000 000 строк заменить ASCII на UTF8? В зависимости от языка конечно. Даже простая автоматическая текстовая подмена типов вполне работает.
                                                Главное — не забывать — юнит-тесты писать, чтобы потом узнать, сломалось ли что-то.
                                                • +1
                                                  А потому, что в некоторых ЯП, или даже в конкретных реализациях, класс String работает только с символами, которые занимают 1 байт. Замена на 2 байта потребует переписывание множество функций, от getLength до indexOf. И это если есть класс для работы со строками, иначе совсем печаль.

                                                  Более того, в проекте на 1 000 000 может быть ряд системные работ со строками, аля memset.

                                                  Наверное особых проблем нет в большинстве случае, но у меня на пару недель были, при реализации веб-сервера на Delphi 7 для одной крупной КИС.
                                                  • 0
                                                    так в случае мемсетов, нужны с одной стороны юнит тесты. Потом, если в функциях, которые делают что-то другое, а строки там вспомогательные и работает прямое выделение памяти на строку, так оно либо в одном месте один раз было, либо рефакторинг уже давно вынес в отдельное место работу с памятью для строк.

                                                    В С, например, можно не использовать прямо тип, а макрос препроцессора использовать. Захотели поменять, подменили в макросе. В других языках, если что, создаете свой тип, класс. Если же не предусмотрели (и возможно правильно, не было требований), то можно сейчас создать новый тип и подменить текстовой автоматической подменой.
                                                    А юнит-тесты покажут что не так. В общем, я бы из этого проблемы не делал. Потому что это простой автоматический рефакторинг. Да, может оказаться сложным. Но вообще-то, проблема с аски и юникодом довольно известная. И если язык не поддерживает тип юникодов, то можно что-то придумать сразу — написать класс-обертку над стандартным аски-типом. А потом ее подменить.
                                                    • 0
                                                      Автоматические действия с заменой просто сделает все не рабочим. Юнит тесты помогут найти проблемы, но их может и не быть. И даже если есть, решать те проблемы может быть долго и печально.

                                                      Я хотел сказать, что дешевле было бы сделать поддержку строк utf8 сразу, чем потом делать такие исправления.
                                              • +1
                                                Вы всё правильно написали.
                                                Я прихожу к более четкому выражению своей претензии к ООП — при работе с ним очень легко сделать ошибку, которая выльется затем в трудозатраты на её исправление. Изменять менее структурированный код мне лично проще.
                                                Возможно, это мой личный баг :)
                                                А правильное ООП предполагает довольно четкие структуры классов и связей.
                                              • +2
                                                Опять ведь за старое. Это претензия к разработанной вами структуре классов, а не к ООП! И опять же, когда нужно просто удалить файл, для этого можно написать метод, который делает только удаление файла. Зачем, если вы используете ООП, обязательно пытаться всё усложнить и предусматривать ненужные мелочи? А затем всё сваливать на парадигму. Просто решайте поставленную задачу, а правильное применение ООП поможет снизить стоимость переделок.
                                                • +1
                                                  Вы правы, и мой пример с файлом не самый удачный. Тут сложно нагородить огород, пользуясь приёмами ООП.

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

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

                                                  Казалось бы, ребята сделали всё верно. Но!
                                                  1) они потратили уйму времени на обдумывание, обсуждение и реализацию
                                                  2) они получили больше классов, чем было — было 2, стало 3 (добавился абстрактный), появилась иерархия и наследники, т.е. система усложнилась

                                                  Я предложил совсем не ООПшный подход — сделать 1 класс, отличающуюся логику релизовать простым if-ом. Реализовать это в первом классе.
                                                  Убрать второй класс и его использование (трудозатраты на это рефакторинг использования — секундны, решается простой скриптовой заменой использования имени второго класса на имя первого). Это решение было готово через 3 минуты, оно не усложнило систему.

                                                  P.S. два упомянутых мной схожих класса в таком виде живут более 2х лет и с тех пор ни разу не менялись и не планируют.
                                                  • +3
                                                    Мне кажется я реально стал понимать точку зрения вашего лагеря :)
                                                    На хабре недавно проскакивала статья про фабрики фабрик фабрик для производства молотков. Складывается ощущение, что та статья была не шуточной, а в какой-то степени действительно отражала правду.

                                                    По факту, смысл вашего комментария сводится к тому, что следуя ООП ребята впустую потратили 30 минут времени каждого (минимум, 1 человеко-час) и получили такой же выхлоп, как и мгновенное решение с использованием одного if. Здесь даже не поспоришь, это суровая действительность.

                                                    Однако, ребята сами виноваты :) Ещё Фаулер в PoEAA чёрным по белому писал: ребята, transaction script — это быстро, эффективно, но не приветствует изменений и не сильно способствует читаемости кода (в экстремальном случае). Domain model — это на старте ощутимо дольше и дороже. Профит в плане снижения сложности внесения изменений появляется только при достижении конкретного объема модели. До него — transaction script эффективней. По-моему, в книге даже был график. Ребята — сами виноваты. Ваше решение лучше по всем критериям! Только if — это не «совсем не ООПшный подход». ООП не запрещает в логике класса использовать условие. Оно просто говорит, что данный подход немного менее очевидный и понятие, лежащее в основе данного условия мы намеренно делаем менее явным и прячем от взора разработчика. Если окажется, что оно было важным — то epic fail. Если более 2х лет нам на него было начихать — okay.

                                                    Хочу ещё прокомментировать один момент. Вы чуточку не правы про усложнение или неусложнение системы. Наплодив больше классов, мы увеличиваем количественную сложность системы. Да, классов больше. Качественная сложность может даже наоборот снижаться. У нас же есть мощные инструменты — абстракция и инкапсуляция. Ну и что, что за реализацией данного интерфейса лежат ещё 2 класса и куча условной логики. Мне, как клиенту данного кода — жить прекрасно и шоколадно. А разработчику данного кода — что 1 класс, что 2, что 3 — по сути, равноценно. ООП позволило нам разбить программу на подобласти и под-подобласти, в каждой из которой мир просто, понятен и пушист. А то, что в сумме это на самом деле робот для убийства всех человеков — ну, okay :))
                                              • +1
                                                Это не дзен, это колдунство ;)

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

                                                Дзен, это когда вам говорят:
                                                — Почему ты не предусмотрел возможность того, что печь может быть и открытым костром. Это очевидно и завтра мы это будем внедрять.
                                                — Завтра — будет завтра. Зачем нам думать о завтра? Завтра не существует, вчера не существует. Существует только сегодня.

                                                Будет задача, будем рефакторить. Куда нам спешить? Нас не как пророков нанимали, а как программистов.
                                                • 0
                                                  К программистам то вопросов и не будет. А вот к проектировщику да.

                                                  Но все забывают про стоимость рисков. Если вероятность какого то изменения требования (добавления, изменения, удаления не важно) = 0.00001%, и если оно изменится в будущем, я буду вынужден потратить 100500 долларов на его внесение. Но если я сейчас заложу, что называется на берегу, гибкость в данном направлении, то оно мне будет стоить 100$, то я скорее сразу реализую гибкий механизм.
                                                  • 0
                                                    К сожалению, так бывает редко. Существенно чаще бывает так: вероятность изменения — 0,0001, косты изменения «по факту» — $1000, косты «разработки заранее» — $100, падение производительности разработки из-за заложенной универсальности — 10%.
                                                    • 0
                                                      Да, если 10% времени будут стоить больше 1000 долларов, то лучше не реализовывать.
                                                      • 0
                                                        10% времени стоят больше $1000 в любом сколько-нибудь крупном проекте.
                                                        • 0
                                                          Ну я не спорю. :) Но вы ранее это не уточнили. Поэтому я не понимаю чего вы хотите сказать. Вообще не надо думать о изменениях? Или что? Ток не говорите что все зависит от множества факторов и т.д., т.к. это мои слова выше.
                                                          • +1
                                                            Я хочу сказать, что по моему опыту, об изменениях надо думать, но чаще всего бесполезно под них что-то планировать и реализовывать заранее.
                                                            • 0
                                                              Ну спорно, очень спорно. Все зависит от конкретной ситуации.
                                                    • 0
                                                      гибкость в каком-либо направлении означает негибкость в других направлениях. Поддержка преждевременной гибкости несет больше расходов.

                                                      1. Код сейчас принято покрывать юнит-тестами. Это один из самых серьезных методов сокращения багов и какой-то гарантии, что код делает то что надо. Лишняя гибкость — лишний функционал. Лишний функционал тоже покрывается юнит-тестами. При изменении чего-то (часто бывает), тесты являются определенным иногда тормозом. Потому что их тоже нужно менять. Но при этом, тесты дают саму возможность изменений, потому что без них вообще страшно что-то менять в уже работающем коде. Никакой без них гарантии, что всё идет как надо. В итоге изменения с тестами экономят время и деньги из этапа сопровождения.
                                                      т.е. издержки на поддержание лишних тестов. Могут быть довольно серьезными.
                                                      2. Если код простой и соответствует требованиям только на «здесь и сейчас», а также покрыт юнит-тестами, то любые изменения в коде делаются значительно легче делаются изменения. Т.е. это не 100500 долларов на его изменения.
                                                      3. Если вы не угадали направление, кроме всего прочего, далее возможно придется удалять код. Потери.
                                                      4. Если вы угадали направление, то времени и денег вы не так и много сэкономили, если сэкономили вообще. То, что делалось наперед, съело время раньше. А так съест время сегодня. Раньше могли бы заниматься более важными задачами. Обычно их хватает всегда.

                                                      Так что выгода от угадывания не очевидна. А даже наоборот. Человек, который пытается угадывать, имеет и специфическое мышление. Он боится рефакторинга. Потому что тогда придется удалять ненужный код. Если он пишет код, угадывая наперед, то и старый ненужный код ему жалко удалять. У него же кода на авось хватает.
                                                      В результате у таких программистов даже время от времени возникает желание всё переписать с нуля.
                                                      • 0
                                                        Т.е. вы говорите что цена изменения, о котором позаботились ранее, будет либо такой же либо больше, чем то, о котором не заботились и узнали в последний момент?
                                                        • 0
                                                          в среднем — да.

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

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

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

                                                          Вот и у нас в программировании сейчас такая холиварная война происходит, считать себя создателями, творцами и пророками или всё же инженерами, адептами точных наук и матана ))
                                                          • 0
                                                            Всецело поддерживаю, хотя не думал что моя точка зрения на проблему проектирования архитектуры приведёт к тому, что придётся считать себя не творцом :(
                                              • +2
                                                никто не замечает, что всё это моделирование достаточно далеко от решение прямой задачи — реализации приложения «печь», к которому можно было бы приступить изначально.

                                                Вот за это просто сразу плюс в карму. Не то, чтобы проблема специфична только для ООП — в проектировании она в принципе довольно часто возникает — но в ООП она особенно заметна.
                                                • 0
                                                  Если не сложно, поясните, пожалуйста, почему означенная проблема особенно заметна в ООП. Именно этот тезис я извлёк из вашей статьи и именно он у меня вызывал абсолютное непонимание.
                                                  • –1
                                                    Ну, как-то обоснованно и опираясь на твёрдые факты тут не объяснишь — всегда можно будет найти какие-нибудь «но». Тут скорее чувствовать нужно. Тем не менее, попробую объяснить на примере, как раз том, которую использует автор этой статьи:

                                                    Есть пекарь. Есть печь электрическая и газовая. Ваша задача смоделировать процесс приготовления пищи пекарем в каждой из печи

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

                                                    1. Какие у нас есть объекты в предметной области?
                                                    2. Как они взаимодействуют?

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

                                                    3. Как уменьшить дублирование кода?
                                                    4. Как это можно реализовать средствами языка?

                                                    Когда первая аппроксимация системы готова, мы начинаем причёсывать её, а для этого продумываем:

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

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

                                                    Это в ООП. В не ООП мы не ограничиваем решение задачи только моделированием предметной области. У нас есть задача и подзадачи, так почему бы не приступить сразу к решению этих задач? Чтобы подсчитать расход топлива, нам не нужна модель печи — достаточно простых уравнений. Мы можем сразу написать функции для этих уравнений, не тратя время на overhead в виде моделей печи, пекаря, топлива и булочки с маком. Просто решить поставленную задачу. Всё.

                                                    Плюсы и минусы есть у обоих подходов. ООП создаёт накладные расходы, но может помочь лучше структурировать код, сгруппировав по смыслу. Не ООП (а, скажем, процедурное программирование) позволяет сразу сконцентрироваться на задачах, но может быть более слабым в борьбе со сложностью. Многое зависит в т.ч. от самодисциплины и умения подходить к проблеме с разных сторон (в ООП ведь тоже не обязательно пытаться смоделировать предметную область).
                                                    • +1
                                                      Мысль уловил, осознал и даже выглядит разумно.

                                                      Но есть вопрос:

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


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

                                                          У меня вот авто — Subaru. Считается, что она позволяет ездить быстрее 80% остальных авто. У меня нет к ней претензий, потому что хотя велик соблазн почудить, особенно зимой, я включаю мозг и так не делаю! Несколько раз (месяцев) потренировался на закрытой площадке и действительно, когда необходимо — я могу на ней ездить быстрее остальных.
                                                          • 0
                                                            Про авто — отличный пример, надо запомнить :)
                                                      • 0
                                                        Минусы как-то описывались в «как программисты строят дома».
                                                        Примерно — один начал строить этажи, второй шахту лифта. Но тут оказалось что высота и к-во дверей лифта не совпадает с высотой этажей. А про лестницу и дверь вообще забыли. И надо переделывать.

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

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

                                                      • +1
                                                        Тут ограничение только на интерфейс взаимодействия модулей печей и Иванов, а это гораздо более мелкая задача, чем проектирование полной ОО архитектуры. Если подразумевается общая функциональность (которую в ООП вынесли бы в абстрактные печи и абстрактных Иванов), то её вполне можно поместить в отдельный модуль, при этом не закрепляя жёстко объекты в иерархии наследования.
                                                      • 0
                                                        Спасибо! Отвечу вам взаимностью, когда сам наберу достаточно кармы для оценок.
                                                        Также поддерживаю ваше более подробное разъяснение этого моего тезиса habrahabr.ru/post/148015/?reply_to=4996307#comment_4998355

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

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

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

                                                              Еще раз: Универсальной (на все случаи жизни) иерархии классов не существует. Эффективная иерархия классов может быть построена только в контексте конкретной задачи.

                                                              В связи с этим, абстрактные рассуждения про наследование, инкапсуляцию и полиморфизм не имеют никакого смысла вне контекста задачи, и являются обычным псевдоинтеллектуальным бредом. Чем та статья, о которой упоминает автор данной статьи, и является.
                                                              • 0
                                                                Это отличная аналогия для закона дырявых абстракций. Если бы у меня были студенты, я бы обязательно её использовал :)
                                                              • 0
                                                                А виртуальные классы на примере пекаря?)
                                                                Хотя аналогия хорошая)
                                                                • 0
                                                                  Есть продукты и есть функции: поджарить, протушить и нарезать, например. Хотим пожрать. В роли «повара» выступает функция или, если угодно, процесс, который решает, какие продукты использовать и какие действия над ними производить в зависимости от входных параметров (название блюда). В результате получаем готовый ужин.

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

                                                                  А ещё теоретически при таком раскладе один и тот же повар сможет приготовить пять блюд одновременно без необходимости ручной синхронизации, потому что процессы приготовления ни от чего лишнего не зависят. А Ваш пекарь в процессе приготовления блюд сломает стол — и капец! :) Или ингридиенты перепуает :)
                                                                  • 0
                                                                    Как по мне на редкость неудачный пример. Пекарь Должен знать о том что у него за печь, какое горючее потребляет, как ее включать, как использовать именно эту печь, а не абстрактную печь в вакууме. Иначе это очень плохой пекарь, если он не знает своих инструментов. Пекарь Должен хотя-бы ознакомится с особенностями конкретной печи, прежде чем начнет ее использовать. Есть промышленные, есть бытовые печи, духовки и т.д. И технология готовки там отличаются не хило.
                                                                    • +1
                                                                      Это всего лишь пример.
                                                                      Вот оконный менеджер не знает что у вас за приложение — броузер, архиватор или 3D игра, но при этом он знает как свернуть окно, как закрыть приложение, как показать его название и иконку в списке задач. Но ведь приложения разные!

                                                                      А почему так? Да потому что приложения пишутся под менеджер окон, а не наоборот!

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

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

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

                                                                      А они не умеют сортировку пузырьком. Зато наизусть вот знают ваши инкапсуляции-наследования-полиморфизмы.
                                                                      • 0
                                                                        Вы не в кулинарном техникуме преподаёте? :)
                                                                      • +1
                                                                        Точнее обожали, сейчас не преподаю, т.к. переехал…
                                                                        • +1
                                                                          Читал замечательную книжку First Head: Design Patterns.

                                                                          Там готовили абстрактную пиццу на абстракной пиццерии-фабрике. :)
                                                                        • +4
                                                                          Ох, прям ждал подобной статьи!
                                                                          • +3
                                                                            Да, я тоже долго не мог собраться написать… Но прям чуял что напишу. :)
                                                                          • +4
                                                                            Еще говорят что некоторые вещи нельзя представить в виде объектов и их взаимодействия.

                                                                            Несомненно, все можно так представить. Но дело в том, что некоторые вещи существенно проще представить в другой модели.
                                                                            • 0
                                                                              Не спорю. Но что касается разработки ПО, то скорее всего более понятного, именно понятного для других программистов, я не встречал. И давайте пример. :)
                                                                              • 0
                                                                                А давайте, прежде чем мы перейдем к примерам, я спрошу, что вы подразумеваете под разработкой ПО.

                                                                                Потому что для меня «разработка ПО» уже давно — выбор нужных технологий и реализация с их помощью требований заказчика.
                                                                                • 0
                                                                                  А давайте, чего уж там.

                                                                                  Но для меня разработка ПО это тоже самое, но плюс минимальные затраты на само написание кода, расширение и сопровождение.
                                                                                  • +2
                                                                                    плюс минимальные затраты на само написание кода, расширение и сопровождение.

                                                                                    Это уже количественные характеристики, определяющие эффективность процесса.

                                                                                    Так вот, возьмем сначала самый простой пример: менеджер хочет видеть еженедельный отчет по эффективности продаж. В пяти разрезах и с drill-down. Продажи лежат в БД (уже много лет как лежат).

                                                                                    «Очевидно», что самый эффективный способ это сделать — это построить кубик поверх БД, а потом выложить этот кубик в Sharepoint BI или просто в Excel, в зависимости от того, что у нас развернуто и используется (ну или в любую другую BI-систему, просто эти первыми на ум пришли).

                                                                                    Требование реализовано, ни одного объекта не пострадало ни только при разработке, но даже при проектировании системы.
                                                                                    • +2
                                                                                      Блин. Честно не знаю что ответить. Явно вижу что вы абсолютно правы, но явно чувствую что вы меня накололи в определении «разработка ПО». :)

                                                                                      Я все таки понимал нечто большое, чем конфигурирование MOSS и построение кубика… Ну тут то да, вам не нужно использовать ООП. Блин, моя «разработка ПО» гораздо более чем ваша. :)
                                                                                      • 0
                                                                                        Понимаете, на нынешнем уровне сложности бизнес-процессов максимум задач надо сводить именно к таким решениям. Просто потому, что вы иначе не успеете.

                                                                                        Вы думаете, DSL, SOA и прочие умные слова вырастают на пустом месте?

                                                                                        Я могу пропустить этот пример и взять интеграционные задачи. Там тоже ООП не имеет смысла, там сообщения и агенты.

                                                                                        И так далее.

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

                                                                                        • +2
                                                                                          «ООП — это технология уровня реализации» заметьте, я и не говорил иначе, более того, я это подчеркнул.

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

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

                                                                                            Есть уровень реализации бизнес-задач, а есть уровень реализации платформы, например. И это разные уровни.

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

                                                                                            BTW, все большее развитие мультипарадигменности в языках это подчеркивает.
                                                                                          • +2
                                                                                            Это типа вы сейчас сказали, что DSL, SOA и прочее — это какая-то новая парадигма? И сервисы не имеют поведения, не имеют внутреннего состояния, а DSL не оперируют предметной областью и мы на них не описываем поведение объектов этой самой области? И кубик — это не объект с кучей данных, да? И даже когда задача сводится к установке готового продукта, его настройке и интеграции с кучей других — там внутри нет ООП? По-моему, это оно самое — проектирование, объектно-ориентированное. Код тут лишь вершина айсберга, а в его низах кое-что другое, о чём писал автор в статье.
                                                                                            • 0
                                                                                              Спасибо. :)
                                                                                              • +2
                                                                                                Это типа вы сейчас сказали, что DSL, SOA и прочее — это какая-то новая парадигма?

                                                                                                Нет, я этого не говорил.

                                                                                                И сервисы не имеют поведения, не имеют внутреннего состояния

                                                                                                Сервисы в contemporary SOA не имеют внутреннего состояния.

                                                                                                DSL не оперируют предметной областью и мы на них не описываем поведение объектов этой самой области

                                                                                                DSL оперирует предметной областью. Он не обязан быть объектным, так регулярно делают (примеры есть у Айенде).

                                                                                                И кубик — это не объект с кучей данных, да?

                                                                                                Кубик, несомненно, объект. Но его абстракция в голове проектировщика — это многомерные данные, а не «объект».

                                                                                                И даже когда задача сводится к установке готового продукта, его настройке и интеграции с кучей других — там внутри нет ООП?

                                                                                                Никто не знает, и слава б-гу. Это как раз уменьшение сложности.
                                                                                              • 0
                                                                                                Там тоже ООП не имеет смысла, там сообщения и агенты.

                                                                                                В чём принципиальная разница между агентами и объектами? Просто что всегда считал, что ООП — это объекты и сообщения.
                                                                                                • 0
                                                                                                  В чём принципиальная разница между агентами и объектами? Просто что всегда считал, что ООП — это объекты и сообщения.

                                                                                                  Тут есть две точки зрения. С одной из них (современное SOA), в подобной архитектуре нет ничего, кроме объектов и сообщений, и с этой точки зрения оно похоже на ООП (с других все равно не похоже, потому что coarse-grained interfaces и stateless agents). А с другой (enterprise integration patterns), помимо агентов и сообщений есть еще посредники (которые, собственно, и управляют сообщениями), и вот они в ООП ложатся хуже. Хотя, несомненно, они тоже объекты, но вот стройность картины уже теряется.
                                                                                                  • 0
                                                                                                    Приходится вводить пркси, адаптеры и фасады? Вы про это?
                                                                                                    • 0
                                                                                                      Нет — меняется место принятия решения.
                                                                                                      Если объект А посылал сообщение объекту Б — то не важно через адаптер он это делает или нет — он знает про Б.

                                                                                                      Если есть посредник, то объект А посылает сообщение в пустоту — а кто словит, тому и будет. Посредник ловит и отсылает его в Б, а может и в В или куда-то еще в зависимости от изменившихся требований.

                                                                                                      Так вроде?
                                                                                                      • 0
                                                                                                        Прокси, адаптеры и фасады — в ООП — это шаблоны, состоящие из тех же объектов. А в messaging аналогичные им элементы — это first-class citizens.
                                                                                                        • 0
                                                                                                          Не важно как это реализуется. Смысловая разница в чем?
                                                                                                          • 0
                                                                                                            В уровне абстракции. Там, где ООП оперирует двумя понятиями (объекты и сообщения), messaging оперирует существенно большим их количеством.
                                                                                                            • 0
                                                                                                              Ну мне кажется что если вы покажете эти понятия, то на это будут те же объекты.
                                                                                                              • 0
                                                                                                                Deep down, несомненно. Во-первых, потому, что слово «объект» настолько всеобъемлюще, что им можно назвать все, что угодно, во-вторых, потому что если у вас есть молоток, все вокруг выглядит как гвозди.

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

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

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

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

                                                                                                  Вы, видимо, не очень понимаете, что такое разрез (dimension) в аналитических данных, иначе бы вы не говорили, что это паттерн presenter.

                                                                                                  Ну и да, если вы обратите внимание, данные и представление в моей реализации полностью разделены, данными занимается OLAP, а представлением — соответствующий клиент, имя которым миллион.
                                                                                                  • 0
                                                                                                    Чем тут вам не объектный подход? Вы просто использовали другую терминологию.

                                                                                                    С названием паттерна промахнулся. Пардон… Что такое разрез данных я знаю. Вы по сути получаете историю состояний сущности (объекта), которой в базе данных не существует. Одни и те же данные в базе одновременно могут являться данными о состоянии разных объектов.
                                                                                                    • 0
                                                                                                      Чем тут вам не объектный подход? Вы просто использовали другую терминологию.

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

                                                                                                      Вы по сути получаете историю состояний сущности (объекта), которой в базе данных не существует.

                                                                                                      Нет.

                                                                                                      Одни и те же данные в базе одновременно могут являться данными о состоянии разных объектов.

                                                                                                      Тоже нет.
                                                                                                      • 0
                                                                                                        Что нет?
                                                                                                        • 0
                                                                                                          Разрез в аналитических данных — это не история состояний, которой в базе не существует. Это просто измерение аналитического многомерного куба.
                                                                                                          • 0
                                                                                                            Я говорил про то, что сущности в базе не существует. Но это не значит. что данных о ней не существует… Впрочем, я думаю мы друг друга поняли, просто вы решили принять определенную позу… Красиво…
                                                                                                            • 0
                                                                                                              Я говорил про то, что сущности в базе не существует.

                                                                                                              Как это — не существует? Она там вполне есть. ER-диаграммы про нее нарисованы даже. Просто это не объект в терминах ООП. А сущность как раз есть.

                                                                                                              Но когда дело переходит в аналитику, там уже даже сущностями не оперируют, там оперируют массивами.
                                                                                            • 0
                                                                                              Цена технологий кстати чаще не берется в расчет. Копейки, чаще всего, по сравнению с остальными пунктами. Но конечно так не всегда, но чаще.
                                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                                          • 0
                                                                                            :) Чем плох Иван то? :)
                                                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                                          • +14
                                                                                            Я яростный приверженец ООП, но ваша статья мне не очень понравилась. И вот почему:

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

                                                                                            2.
                                                                                            Используя объектное мышление вы легко можете решить любую задачу (очень важно что любую, абсолютно любую)
                                                                                            Даже NP-полную? Это как-то на рекламу смахивает, нежели на что-то разумное :(

                                                                                            3. Очень красиво начали рассказывать про инкапсуляцию, а потом свели все к геттерам и сеттерам. Ну зачем?

                                                                                            4.
                                                                                            И даже есть стандарты, которые могут понять хорошо ли вы выбрали абстракции и верна ли ваша декомпозиция (SOLID).
                                                                                            SOLID уже стандарт? SOLID не имеет прямого отношения к декомпозиции. SOLID скорее для первого приближения грамотности проектирования, нежели для верификации грамотности выбора абстракций и декомпозиций.

                                                                                            Но есть в статье и то, что мне очень понравилось:
                                                                                            1. Акцент на объектном мышлении.
                                                                                            2. Описание полиморфизма и наследования.
                                                                                            3. Качество изложения.

                                                                                            • 0
                                                                                              Спасибо.

                                                                                              1. Отправлю в личку.
                                                                                              2. Ну… Я могу конечно включить в текст статьи исключения задач которые я не могу решить, но я думаю не стоит. Тем более про NP-полную…
                                                                                              3. Да, это связанно с прошлой статьей. Просто сильно меня зацепило. Я вам дам ссылку и потом напишите мнение свое. Мне интересно
                                                                                              4. Да, наверное перегнул. Но SOLID явно может помочь понять в каком направлении идти.
                                                                                              • +1
                                                                                                2. Вы сделали акцент на том, что можно решить абсолютно любую задачу, чего делать не следовало. Я пытаюсь сказать, что если программист не мог решить задачу без ООП, то он не сможет решить задачу и с ООП, за редким исключением. ООП лишь ускоряет разработку и уменьшает сложность программного продукта.

                                                                                                4. Согласен, может. Но я строго рекомендую читать умные книги, а не расшифровку различных аббревиатур.
                                                                                                • +1
                                                                                                  Еще раз спасибо.

                                                                                                  2. Да, я сейчас подумаю как лучше написать эту часть
                                                                                                  4. Это я оставлю, но сделаю формулировку мягче
                                                                                                  • +2
                                                                                                    >ООП лишь ускоряет разработку и уменьшает сложность программного продукта.

                                                                                                    Ну еще оно все-таки упрощает разработку. Разве не может так оказаться, что без использования ООП сложность задачи превосходит возможности данного конкретного программиста, а с использованием ООП — оказывается в пределах возможного?

                                                                                                    Лично я для себя понимаю, что многие из разрабатываемых мной в профессиональной деятельности продуктов я бы просто не решился бы даже начать делать без хороших инструментов — и для меня ООП один из таких хороших инструментов.
                                                                                                    • 0
                                                                                                      Полностью согласен, моя ошибка.
                                                                                                  • 0
                                                                                                    При чем здесь NP-полнота? Как вообще связаны ООП и алгоритмическая сложность?

                                                                                                    Фраза «решить задачу» далеко не всегда трактуется как «придумать алгоритм полиномиальной сложности».
                                                                                                  • 0
                                                                                                    Мимо проходил.

                                                                                                    1. Ну, я думаю имелась в виду статья Я не знаю ООП (действительно очень спорная статья)
                                                                                                    2. А что NP-полные задачи уже нерешаемы? Многие из этих задач действительно можно легко представить в ООП стиле. Другое дело, что они решение будет находиться за продолжительное (в т.ч. нереально продолжительное) время.
                                                                                                    3. Это скорее отсылка к той же статье, где getters&setters названы нарушением (!) инкапсуляции.
                                                                                                    • +1
                                                                                                      Упс. Уже ответили, пока мимо ходил.
                                                                                                      • 0
                                                                                                        Спасибо.

                                                                                                        1 и 3. Именно. Но я посчитал не нужным давать ссылку в статье.

                                                                                                        Про второй пункт спорить не буду. У всех есть своя правда. И решаемы и нет. :)
                                                                                                        • +2
                                                                                                          По поводу ссылки. Извините, если сделал то, что Вы не считали правильным. Просто не казалось, что привести ссылку было бы нетактично.
                                                                                                          • +1
                                                                                                            Ну сделанного не воротишь. :) Ничего страшного, это просто мой бзик.
                                                                                                        • 0
                                                                                                          1. Да, она (уже увидел в личке).
                                                                                                          2. Я несколько в другом контексте критиковал это утверждение.
                                                                                                          3. Это было сложно понять, учитывая, что я не помню уже всей сути той статьи.