Бертран Мейер. Объектно-ориентированное конструирование программных систем


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

    Основная сложность при изучении объектно-ориентированного программирования (или любой другой парадигмы программирования) заключается в том, что весьма сложно подобрать формальные критерии, которые бы сказали: «ок, теперь я знаю ООП и стану писать более клевые (читай модульные, реюзабельные и легкие в сопровождении) программы». Например, при изучении языков программирования мы относительно быстро замечаем, опа, level-up, я, кажись, перешел на новый уровень понимания идиом и конструкций языка программирования и могу использовать его более интересным образом, да еще и другим рассказывать, где они не правы.


    Когда же речь касается изучения ООП, то здесь проявляется проблема, которую Мейер называет mOOzak effect или buzzword effect. Сводится она к следующему: человек знакомится с некоторым понятием или термином и начинает интенсивно использовать его в повседневной (рабочей) жизни, не придавая значения тому, что сам он его до конца не понимает. Если прислушаться к обсуждениям в коллективе (или на форумах), то можно заметить употребление множества «страшных слов», типа инвариант, инкапсуляция, полиморфизм, ковариантность, контрактное программирование и многие другие, при этом очень часто они могут употребляться без полного понимания того, что же они означают.

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

    Однако зря.

    В последнее время появилась тенденция описывать все, что происходит в нашей с вами компьютерной жизни разными метафорами, идиомами и паттернами. Сейчас, если вы не знаете все GoF-овские паттерны, не знакомы с принципами S.O.L.I.D., и не осилили архитектурные паттерны, то вы УГ, которому за проектирование не стоит даже браться. Нисколько не умаляя заслуги всего перечисленного, я отношусь ко всему этому со здоровым прагматизмом. Во-первых, запоминание всех этих принципов и паттернов слишком утомительно, во-вторых, значительно проще получить определенные базовые знания, из которых вытекает многое другое, нежели тренировать память и из года в год стараться запомнить всякие новомодные словечки.

    ПРИМЕЧАНИЕ
    Именно о пользе таких фундаментальных знаний шла речь заметке Повторное использование знаний. Книга Мейера – это замечательный способ устаканить в голове множество, казалось бы разрозненных фактов, чтобы получить более цельное представление о разработке ПО вообще и об объектной технологии в частности.

    Мейер в своей книге упоминает о паттернах проектирования и описывает довольно большое количество принципов. Некоторые из этих принципов довольно известны (например, принцип открыт-закрыт, (‘O’ из принципов SOLID), «это придумано не здесь» (NIH – Not Invented Here), принцип разделения команд и запросов (CQRS – Command-Query separation principle), и т.д.), другие принципы весьма специфичны (например, принцип Унифицированного Доступа, который позволяет обращаться к полю и процедуре одинаковым образом). Но в отличие от многих других книг, ничего из этого не ставится во главу угла, из этого не делается серебряной пули, способной решить все проблемы. Лишь принцип открыт-закрыт упоминается относительно часто, поскольку играет очень важную роль в наследовании – ключевом аспекте ООП.

    Главное же преимущество книги – это продуманный и формальный подход к вопросам объектной технологии и таким фундаментальным вопросам, как модульность, повторное использование, сопровождение, наследование, связь классов с абстрактными типами данных. Не последнюю роль в книге играет и принцип проектирования по контракту, который позволяет формализовать взаимоотношение между классами и делает некоторые общеизвестные принципы излишними.

    Несколько лет назад из недр Microsoft Research вышла библиотека Code Contracts, которая добавила поддержку контрактного программирования на платформу .NET. Можно прочитать документацию и кучу статей, но некоторые аспекты ее поведения все еще будут непонятными. Конечно, «библиотечный способ реализации» контрактов дает о себе знать, но Code Contracts (как и многие другие реализации «контрактов») практически полностью следует принципам, заложенным в этой книге, так что для их нормального понимания и использования лучшего источника информации, чем первоисточник просто не найти.

    То же самое можно сказать и о наследовании. Это весьма непростая техника, которая может помочь в создании понятного, расширяемого и простого в сопровождении ПО, но при неумелом обращении интенсивное использование наследования может привести к тяжеловесным иерархиям, способным под собственной тяжестью похоронить любое приложение. Только лишь правильному использованию наследования уделено 55 страниц, на которых описаны 10 (!) видов наследования (большая часть которых недоступно в таких языках без множественного и закрытого наследования, таких как C# или Java).

    Помимо этого есть главы, посвященные персистентности, многопоточному программированию, обучению объектной методологии, культуре повторного использования. Мейер касается даже таких «мирских вопросов» типа правила именования и рекомендации по написанию комментариев (обратите внимание на раздел 26.4 Комментарии в заголовках: упражнение на сокращение).
    К великому сожалению у книги есть и ряд недостатков. Первый недостаток – это 1200 страниц с огромным количеством информации на каждой из них. Эту книгу не осилить лежа на диване под любимый сериал или передачу; на нее придется потратить приличное количество усилий, причем не факт, что одного прохода для этого будет достаточно. Книга довольно сухая, формальная и местами довольно жесткая.

    Во-вторых, все примеры даются на языке Eiffel. Сам по себе язык очень интересный и тот факт, что за последние 20 лет в него не внесли никаких концептуальных изменений, говорит о том, что язык с самого начала был очень хорошо продуман. Но поскольку большинство современных ОО-языков не поддерживают некоторые ключевые ОО-возможности (с точки зрения Мейера), то далеко не все описываемые концепции удастся пощупать на практике (в основном это касается отсутствия множественного наследования и проектирования по контракту).

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

    Оценка: MUSTHAVE(*)

    З.Ы. Книга доступна на сайте intuit.ru в виде двух курсов: Основы объектно-ориентированного программирования и Основы объектно-ориентированного проектирования.

    Ссылка на озон.


    (*) На всяк случай поясню, Must Have – это самая высокая оценка книги, которая только может быть; она означает, что книгу не просто нужно прочитать, ее стоит держать под боком на удобном вам носителе и периодически к ней возвращаться.
    Поделиться публикацией

    Комментарии 42

      +3
      Кто-нибудь кроме автора топика читал этот 1200-страничный Must Have? Поделитесь пожалуйста отзывами.
        +8
        Я читал, но у меня есть оправдание — был в армии. Очень хороший труд, рекомендую всем программистам.
          +1
          Я прошла оба интутовских курса по книге (это считается?). Понравилось. Думаю, что надо бы повторить.
            –5
            «Complete Code» Файлера Вы, естественно, тоже не читали? :-)
              –4
              Фаулера :-)
                +5
                МакКоннелла :-)

                P.S. Что-то меня сегодня глючит…
                  0
                  «Code Complete» если уж на то пошло:-)
                +3
                Язык Эйфель — отстой.

                Идея дизайна по контракту — неплохая, но не тогда, когда контракты встроены в язык.

                1. Когда начинается взаимодействие с внешним миром, для качественного описания контракта приходится написать очень много кода.

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

                Майер предложил идею маркировать типы специальным образом; с помощью этой насадки можно реализовать потоковую модель наподобие Microsoft COM Apartment, но у неё есть известные ограничения. Когда на CSA Russia в ЕКБ пару лет назад аудитория начала говорить ему об этом, он психанул, бросил на пол ноутбук и выбежал из аудитории :-)
                • НЛО прилетело и опубликовало эту надпись здесь
                    +1
                    В обычном ОО-языке есть, условно говоря, правила гигиены и шаблоны, по которым надо проектировать конкурентный доступ.
                    1. Состояние, разделённое (shared) потоками, должно быть как можно меньше.
                    2. Доступ к разделённым данным должен производиться через как можно меньшее количество входных точек.
                    3. Работа с разделёнными данными должна быть либо блокирующей, либо неблокирующей.
                    3.1. Если работа блокирующая, надо проектировать в терминах последовательностей операций, не нарушающих заранее определённые инварианты.
                    3.2. Если работа не блокирующая, надо чётко определять гарантии работы кода в плане доступа к протухшим данным.

                    В Эйфеле проблемы возникают с пунктом 3: описанные инварианты (собственно инварианты, постусловия, предусловия) обеспечивают корректность только для неразделённых данных.
                      0
                      > инварианты (собственно инварианты, постусловия, предусловия) обеспечивают корректность только для неразделённых данных.

                      CAS знаете?
                      • НЛО прилетело и опубликовало эту надпись здесь
                          0
                          Ну и пусть говорят. Еще можно настаивать на отдельности бит в машинном слове.
                          CQRS, на самом деле, всего лишь частный случай требования правильно именовать методы и не вводить неочевидных побочных эффектов.
                          CAS же по способу употребления — однозначно mutator. CAS без цикла еще заслуживает приставки «try-», но CAS внутри своего обычного цикла — mutator в чистом виде, команда с гарантированным эффектом.
                  +1
                  Я прочел в оригинале. И всем советую.
                  Майер поэтичен и кэролловски элегантен. Его должен переводить, как минимум, Заходер. А Заходер умер.
                  +3
                  Слушал его лично, будучи студентом.
                  Может быть сейчас было бы иначе, но тогда – не впечатлил совершенно.
                    +1
                    Когда я был студентом, меня тоже многое не впечатляло. Дошло позже.
                    0
                    Что-то на Amazon не очень много фанатов, я бы не определил что это must have, скорее на любителя (классика же)
                      0
                      Кстати позволю себе заметить, книга переведена на русский язык коллективом преподавателей факультета ПМиК Тверского Государственного Университета.
                        +9
                        Плюсую за это

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


                        жаль тех кто не понимает этого.
                          –1
                          Эй, а как же Банда Четырёх? Тут на амазоне она намного популярнее.
                            +7
                            Конечно популярнее, ведь это приятно когда тебе дают готовый алгоритм, который ты можешь использовать без понимания. То, что описано в статье дает фундаментальные знания, как я понял. А это гораздо важнее всех паттернов, т.к. паттерн это всего лишь формализация идеи, которую многие слепо используют. А потом начинается спор о том кто круче может паттерн «мост» релизовать, и кто правильнее его понимает. Забывая то, что никакого эталона не существует и любые формализации паттернов есть лишь воплощение идей конкретных авторов и ваше видение может отличаться. Это как с кодом: можно копирастить с SO, а можно самому придумывать алгоритмы.
                              0
                              поддерживаю. а «мост» то заполнился :)

                                0
                                заполнился — > запомнился
                                  +2
                                  Конечно, статей 5 на хабре было. Я, правда, ни одну из них не читал, но сам факт запомнился.
                            +4
                            Основная сложность при изучении объектно-ориентированного программирования (или любой другой парадигмы программирования) заключается в том, что весьма сложно подобрать формальные критерии, которые бы сказали: «ок, теперь я знаю ООП и стану писать более клевые (читай модульные, реюзабельные и легкие в сопровождении) программы».

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

                            Единственная польза — структуризация программы. Но того же эффекта можно достичь просто грамотно разделяя продцедуры на модули в процедурном программировании. Да хотя бы просто логически сгрупировать процедуры в исходнике — абсолютно тот же эффект без оверхэда на булшит.

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

                            p.s. Да, я в курсе что я ещё не просветлел, у меня мало опыта и вообще низкий уровень интеллекта. И, разумеется, зря противоречу постулатам, которые намертво выжжены в подкорке опытных С++ и джава программистов.
                              0
                              похоже тэги в комментах не работают, первый абзац делал курсивом

                              s/намертво/необратимо/
                                0
                                Единственная польза от этого это то, что можно определить базовый класс и от него наследовать.


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

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

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

                                  А то, что ООП так популярен — так это заслуга популярности языков программирования на нем. Здесь вообще все просто — больше популярности, дешевле использование. Становится JS популярнее — и прототипное программирование, вдруг, стало актуально как никогда.
                                    0
                                    Цитата:
                                    В вашем комментарии словосочетание «объектно-ориентированное программирование» можно заменить на любую другую изучаемую технику

                                    В том то и дело что не любую другую. Многие другие технологии имеют рациональный инженерный и научный подход. И решают какие-либо проблемы. ООП не решает никакие проблемы, только создаёт. Это сугубо гуманитарная штука, как отмечено в комментарии ниже.
                                      0
                                      Я рекомендую полистать эту книгу; вот что что, а назвать формальное изложение Мейером ООП гуманитарным подходом язык никак не поворачивается.
                                        0
                                        «Не решает никаких проблем» о технолгии, являющейся мэйнстримом как-то слишком громко сказано. Вроде как, основная задача ООП — это уменьшение сложности кода, а инкапсуляция, наследование, полиморфизм и т. п. лишь выбранные для этого инструменты. Может не идеальные, но основную задачу они решают.
                                          +1
                                          Да, да, я в курсе что это единственно верная, дефолтная технология и вообще нечего перечить мейнстриму.
                                    +5
                                    В таких статьях не хватает magnet-ссылок.
                                      +1
                                      >Основная сложность при изучении объектно-ориентированного программирования (или любой другой парадигмы программирования) заключается в том, что…

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

                                      По факту же в тех же явах и C#-ах мы имеем диспетчерезацию по первому параметру, какую-никакую статическую типизацию, и кучу спорных синтаксических штук вроде необходимости размазывать мультиметоды по коду. И кучу заученных приемов обхода всех этих синтаксических выкрутасов, которые называются «ООП-паттернами».
                                        0
                                        Да, большинство изложений методологий разработки тяжело назвать формальным, но у Мейера очень формальный подход. Так что рекоменую хотя бы ознакомиться с этой книгой. Мейер показывает, что ООП методология может быть весьма формальной.
                                          +1
                                          Так вот почему я нифига не могу разобраться в этом ООП…
                                            0
                                            мне кажется вся суть не в красоте и правильности кода с точки зрения какой-то концепции…

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

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

                                              Цитата:
                                              А ООП тут при том что мы оперируем объектами, что является достаточно природным для нашего мировозрения.

                                              Согласен, в каждом руководстве по ООП или С++ написана эта глупость.
                                                0
                                                ну как это не связано… разве не добавляет удобства повторно использовать код ОО-принцип? Разве не природно отнаследоваться от какого-то функционального класса, переопределить нужные методы, добавить что то свое и получить новый класс, часть поведения которого унаследовано (повторно используется) от написанного ранее класса?

                                                Цитата:
                                                Согласен, в каждом руководстве по ООП или С++ написана эта глупость.

                                                Обоснуйте почему это глупость? Разве не легче создавать сущности из таблиц бд (может не самый лучший пример, но все же) и потом оперировать ими как реальными объектами, строить взаимодействия и т.п. чем писать какой то процедурный код, где все будет не так природно?
                                                  0
                                                  Не связано, потому что об этом в самой парадигме не говорится.

                                                  p.s.
                                                  извините за некрокомментинг :)
                                          • НЛО прилетело и опубликовало эту надпись здесь

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

                                            Самое читаемое