Хороший доклад Дэвида Уэста.
Предисловие и введение
Термин “объектно-ориентированный” применительно к дизайну, анализу или программированию ошибочен. Лучше использовать “ориентированный на сообщения”, то есть главной сущностью при работе с объектами являются именно сообщения, передаваемые от объекта к объекту.
Итеративный подход в разработке очень важен, но мы по-прежнему работаем не итерациями. Итеративность подразумевает постоянное изменение кода, а значит, писать его необходимо так, чтобы минимизировать стоимость внесения изменений. Мы же пытаемся наращивать новые слои, то есть рассматриваем каждую итерацию как написание нового кода, а не изменение старого. Но даже и в этом случае мы не готовим старый код к расширению, что приводит к плохому дизайну, высокой связанности и высокой стоимости изменений.
Пример формализованного итеративного подхода к разработке - Rational Unified Process (RUP).
Object Thinking
Не должно оставаться никаких сомнений в том, что объекно-ориентированное проектирование фундаментально отличается от традиционного структурного подхода: оно требует других способов мышления относительно декомпозиции и проявляется в архитектурах, весьма далеких от культуры структурного проектирования. - Grady Booch, 1991
Три ключевых момента в этой цитате:
- фундаментальное отличие - в чем проявляется это отличие и в каких аспектах разработки оно более явно или более важно?
- другие способы мышления - не только о декомпозиции, но и обо всех аспектах разработки.
- культура структурного проектирования - подразумевается соответствующей культуры объектов. Культура - это важный фактор в формировании способа мышления.
@fundamental-difference:Фундаментальное отличие
Традиционное представление объекта в виде данных и процедур, инкапсулированных за какой-то общей границей приводит к тому, что объекты ничем не отличаются от процедурных подпрограмм. Более того, ОО-приложения, спроектированные в такой парадигме, превращаются в набор процедурных подпрограмм. Объектное мышление же представляет объекты в одушевленной форме, антропоморфными.
Второй момент - это подход к количеству объектов, необходимых для решения задачи. В ООП есть стремление сократить число объектов (пример про валидацию бизнес-формы - 10-20 объектов в традиционном представлении и 4 в ООП).
Третий момент - отличия в моделировании. Стандартные способы проектирования (и представления полученной модели) сосредоточены на полях (зачастую с требованиями нормализации данных) и методах, а ООП фокусируется на поведении.
@think-as-object:Мыслить как объект
Противопоставление двух способов мышления:
- Мыслить как компьютер - мышление в терминах решения задачи. Последовательность действий, которую должен выполнить компьютер для достижения определенного результата.
- Мыслить как объект - мышление в терминах предметной области, концентрация на взаимодействии объектов как “виртуальных персон (агентов)”. При этом изоморфность модулей (объектов) в плоскости задачи и в плоскости решения рассматривается как основополагающее качество ПО (ООП позволяет сблизить предметную область и код программы, см. Поиск правильных объектов)
@object-culture:Культура ООП
Автор неоднократно упоминает, что главной чертой объектов является поведение и что это однозначно согласуется с принципами проектирования систем, используемыми в XP/agile методиках. Вопрос: какие это принципы?
- Ценности экстремального программирования
- Общение - объекты облегчают использование единого языка коммуникации
- Простота - объектное мышление позволяет обойтись меньшим количеством классов, точнее моделирующих предметную область. Объекты обычно не нуждаются в управляющих модулях и пассивных структурах данных и как правило выполняют только необходимый минимум работы.
- Обратная связь
- Храбрость - мужество противостоять традиционной парадигме. Это преодоление страха изменений, страха ошибок и их распространения по системе.
- Практики экстремального программирования
- Метафоры - все общение в XP основано на метафорах, связывающих сущности в прикладной области с их представлением в коде.
- Простой дизайн - см. “Простота” выше.
- Рефакторинг - распределение обязанностей по совокупности объектов
- Стандарты кодирования - все программисты пишут код в соответствии с правилами, акцентирующими внимание на донесении информации через код.
Технологии не могут заменить теорию
Философский контекст
В начале нового проекта редко стоит вопрос о методе разработки, чаще интересует вопрос выбора языка или конкретной технологии программирования. При этом часто ответ на этот вопрос исходит из неозвученных причин и поэтому никогда не подвергается критическому обсуждению. А на самом деле стоит выбирать тот язык, в основу которого легли те же идеи и принципы, что формируют предметную область.
Языки-наследники SIMULA
пошли по одному из двух путей: производительность и
создание машинно-ориентированного языка (C++, C#, Java), либо выразительность и
возможность описания предметной области в ее же терминах (Smalltalk, Lisp,
FORTRAN, COBOL, Visual Basic).
Из этого следует:
- Истинные отличия языков программирования отражают философские идеи и ценности. Они, в свою очередь, определяют степень, с которой язык просто и естественно выражает концепции проектирования, не прибегая к “надуманности и грубости”.
- Язык, в терминах которого программисты думают о дизайне, может как улучшить, так и значительно ограничить качество проектных решений.
- Если предметная область ПО ограничена самим компьютером (разработка ОС, драйверов, сетевой инфраструктуры), то лучше использовать машинно-ориентированные языки. Если же ПО решает прикладные задачи, то лучше воспользоваться языками, находящимися ближе к предметной области.
Дебаты об объектно-ориентированных языках упираются в следующую проблему: с одной стороны, мало кто исследовал философские основания ОО-языков, а с другой, мало кто понимает объектную философию.
На новые идеи не обращают внимания, пока они не будут явно оформлены в чем-то конкретном, обычно, в новом языке программирования. Рассуждения об идеях тогда превращаются в сравнение достоинств языков. Затем следуют споры о дизайне, анализе, процессе и методе и за всем этим исходные идеи отодвигаются на второй план или вообще забываются.
От философии к культуре
Составляющие культуры: общедоступное знание, приобретаемое в результате социальной активности (нормы, ценности, взгляды на мир), и шаблоны поведения, характеризующие группу людей. В каждой культуре есть свой миф о создании, герои и героини, истории о великих делах и могущественных артефактах, а также основополагающие ценности и убеждения. Для объектной культуры существует четыре базовых убеждения.
@everything-is-an-object:Все является объектом
Объекты - это эквиваленты квантов, из которых состоит Вселенная.
Это убеждение предполагает, что любая декомпозиция (вне зависимости от сложности предметной области) приведет к определению относительно небольшого числа объектов и только объектов, например:
- Связи, обычно моделируются и реализуются по-другому, нежели объекты; в объектной культуре они являются объектами со своими ответственностями и способностями.
- Данные обычно рассматриваются как “пассивное нечто”, фундаментально отличающееся от “активных сущностей”, например, процедур. В объектной культуре любой фрагмент данных обладает также и своим собственным поведением, позволяющим манипулировать конкретными значениями. У некоторых объектов может существовать первичная (но не единственная) обязанность представлять людям отдельные фрагменты информации.
- Процедуры В объектной культуре процедуры рассматриваются как упорядоченные коллекции сообщений, при этом и коллекция, и сообщения - это обычные объекты.
Более того, в качестве объекта рассматривается даже Человек (Human), взаимодействующий с системой, несмотря на то, что этот объект никогда не будет воплощен в коде. Такой подход позволяет упростить интерфейс взаимодействия с человеком и отразить необходимость в услугах, которые предоставляют системе люди.
@domain-model-as-object-source:Модель предметной области как источник объектов
Это особенность подхода к декомпозиции системы на составные части. Идея декомпозиции восходит к Платону, который утверждал, что (1) это трудно, (2) декомпозиция, не приводящая к нахождению рекомбинируемых частей, бесполезна, и (3) разделение должно происходить в местах “естественного сочленения”. См. также противопоставление двух видов анализа в науке Два вида анализа в науке.
Декомпозиция достигается с помощью абстракции. Абстракция предполагает выбор одного конкретного аспекта некоей сложной системы и концентрацию на нем. Отличия в этом аспекте используются затем в качестве критериев для дифференциации (см. Отличия фрагментов кода как источник абстракций).
Декомпозиция с помощью данных и функций нарушает третье утверждение Платона и приводит с
сложному, хрупкому, нетестируемому и не переиспользуемому дизайну, т.к. связи между данными и
функциями односторонни и неявны
Неявное связывание данных и функций в процедурном подходе. В качестве
критерия для декомпозиции остается поведение.
Согласно Британнике, три преобладающих когнитивных деятельности в процессе познания: дифференциация (в нашем случае по поведению), классификация (поиск схожих черт и отнесение на их основе к какой-либо группе) и композиция (сложные вещи состоят из более простых). Объектное мышление в полной мере опирается именно на эти виды деятельности, таким образом объектное мышление является наиболее естественным.
Важное уточнение: дифференциация по набору атрибутов и по значениям атрибутов - это две очень разные дифференциации, которые часто путают (пример с полосатой домашней кошкой и тигром - значения атрибутов разные, но сам набор атрибутов одинаков, и это недостаточное основание для дифференциации).
Эксперты в предметной области уже имеют некий набор объектов, которые, как правило, являются вполне естественными. Программистам нужно выявить и описать эти объекты, их восприятие пользователем и его ожидания от взаимодействия с ними.
Возможность комбинировать объекты
Возможность составления сложного объекта из простых - это мера качества проведенной декомпозиции. Качественная декомпозиция удовлетворяет следующим требованиям:
- Назначение и способности объекта (в терминах предметной области и с точки зрения потенциальных клиентов объекта) указаны явно. Решение о том, подходит ли объект в каждом конкретном случае принимается только на основе этого указания.
- Способности объектов описываются на языке предметной области.
- Способности объектов не изменяются в зависимости от контекста. Это не отменяет создание узко специализированных объектов, пригодных для использования только в одном контексте, тем не менее такие объекты должны быть явно помечены.
- Специализация объектов в некоторой таксономии объектов должна достигаться за счет расширения поведения, а не его переопределения (см. Liskov Substitution Principle и Open-Closed Principle)
@distributed-interaction:Распределенное взаимодействие и коммуникация
В объектно-ориентированном дизайне нет места центральному управляющему модулю, вся работа выполняется децентрализованно с помощью объектов, обменивающихся сообщениями.
Соответствие принципов построения ПО и объектного мышления
Общепринятые принципы и аксиомы, определяющие качество ПО:
- “Разделяй и властвуй”. Сложные задачи решаются путем их разбиения на более мелкие и более простые. Это принцип модульного дизайна. Объекты должны быть специализированными, то есть, задачи разбиваются на все более мелкие до тех пор, пока не станут настолько маленькими, что каждую из них сможет решить какой-то один объект.
- Приспособление к ограничениям человеческого сознания. Это принцип концептуальной ценности, предполагающий использование ограниченного числа концепций, а также принцип интеллектуального контроля, предполагающий использование абстракций. Объекты должны быть небольшими, чтобы их было можно легко понять, и количество классов также должно быть небольшим.
- Корректность программ не изменяется при переходе между эквивалентными контекстами. Это принцип переносимости (выраженный, например, в кросс-платформенности). Объекты инкапсулируют свое внутреннее устройство, что позволяет переносить их между контекстами, сохраняя поведение их клиентов.
- Корректность не изменяется при замене эквивалентных компонентов. Это принцип гибкого дизайна, предполагающий возможность комбинировать отдельные компоненты по-разному. Небольшой размер объектов + инкапсуляция деталей реализации позволяет комбинировать объекты в самых разнообразных сочетаниях.
объектное мышление позволяет разобраться с присущей сложностью ПО.
Взаимодействие культур - ООП - шаг в эволюции разработки ПО
Метафоры
Метафоры как средство моделирования - важность метафор как средства проектирования и дизайна.
Метафоры определенным образом влияют на объектное мышление:
- Обнаружение новых объектов и свойств через аналогии.
- Принятие проектных решений (пример с удостоверением личности - отдельный объект, идентифицирующий другой объект).
- Напоминание о принципах ООП.
- Избегание старых способов мышления.
@integrated-circuit:Печатная плата
Метафору придумал Брэд Кокс (Brad Cox). Программные модули - как электронные компоненты, стандартизированные (стандартные хорошо описанные интерфейсы) и взаимозаменяемые, вплоть до создания сетевого хранилища компонентов, которые можно использовать, скажем, по подписке. Однако эта метафора - это видение конечного результата, и мало помогает при поиске и определении объектов в предметной области.
@lego-bricks:Блоки ЛЕГО
Сочетаемость, простые интерфейсы и малое число форм. Переиспользование в разных контекстах. Отделение процесса определения и создания объектов предметной области от процесса конструирования ПО. Возможность оценить пригодность компонента только по его внешним характеристикам. Объекты должны быть простыми, их число должно быть ограничено. Для удобства конструирования ПО объекты можно объединять в компоненты (их может быть гораздо больше, чем объектов; они могут значительно отличаться из-за разных подходов их авторов). Быстрое прототипирование и обратная связь (ценности XP).
@object-as-person:Объект как личность
Объект - действующее лицо, способное предоставлять заданный набор услуг. Он обладает знаниями, механизмами (навыки) и ресурсами (инструменты). У человека есть резюме, описывающее его способности, - это аналог контракта объекта. Объекты - специалисты; объекты - лентяи. Эти два факта приводят к тому, что практически любая работа выполняется коллективом (без излишнего микроменеджмента). Ещё одна вариация - объект-агент (представитель) - но у агентов нет требуемой поведенческой целостности. Эта вариация приводит к разделению агента на внутреннюю (присущую, intrinsic) и сервисную (контрактную) части. Внутренняя часть включает то, что позволяет осуществлять функции агента (навигация, знание и доступ к ресурсам), контрактная часть состоит из других объектов (цели, правила, результаты и т.п.), плюс существует некий набор скриптов, описывающих взаимодействие частей.
@theater-actors:ПО - театр, программисты - режиссёры
Кастинг - поиск и отбор актёров (объектов), затем сценарий (скрипты взаимодействия), затем репетиции (тестирование) и наконец выступление (эксплуатация). Интерактивность софта - аналог импровизации на сцене.
- Суть театра не зависит от количества актёров или продолжительности пьесы. Так и принципы дизайна ПО одинаковы на любом уровне, будь то отдельные классы или целые системы.
- Замена одного актёра не приводит к переписыванию сценария.
- На сцене случаются неожиданности, актёры импровизируют. Объекты тоже должны уметь справляться с исключительными ситуациями, импровизировать.
- У пьес есть жанры, у ПО - типовые архитектуры и наборы паттернов (клише сценариев?)
@ants-not-autocrats:Объекты как муравьи
“Слепая” координация вместо иерархии и централизованного контроля. Слепая в том смысле, что объекты не должны знать о существовании других объектов и рассчитывать на их существование или особенности функционирования.
@inheritance:Наследование
Метафора наследования является прямым следствием особенности мышления, которая заставляет людей объединять схожие сущности и создавать древовидные таксономии. Эта метафора может быть использована неправильным образом, если выпустить из внимания ценности ООП. Класс-потомок расширяет поведение родительского класса, а не его внутреннее устройство (ДНК, как предполагает метафора). Лучше считать, что потомки наследуют “активы” (ресурсы, необходимые для осуществления своего поведения), тогда метафора сохраняет свою целостность.
@responsibility:Ответственность
Мы ожидаем от объектов определенного поведения, другими словами, мы считаем объекты ответственными за это поведение. Если объект заявляет (посредством своего интерфейса), что он способен предоставлять определенную услугу, то он должен быть способен предоставлять ее в любых обстоятельствах и результаты должны быть согласованными. Ответственность предполагает самоконтроль. Объект должен поддерживать свое состояние и целостность, уведомлять заинтересованные стороны об изменениях состояния и отвечать на запросы предоставления услуг.
Расизм и сексизм - это ошибки, вызванные подходом на основе характеристик, а не поведения.
Словарный запас ООП
Объектное мышление предполагает использование особенного набора слов, так как язык во многом определяет мышление, см. Взаимосвязь языка и мышления - взаимосвязь языка и мышления.
Единая философия важна для успешной реализации
Прежде всего, словарный запас ООП сформирован другой философией и новыми метафорами (см. предыдущие разделы). Новый словарный запас прежде всего является техникой, помогающей не думать о решениях в ключе старых ментальных привычек.
Основополагающие термины
Эти термины заключают в себе значительную часть объектной философии.
@object-term:Объект
Все является объектами. Объект - это нечто (что угодно), способное предоставить ограниченный набор полезных услуг. Объекты определяются семейством (классом), набором услуг (протоколом) и состоянием (только тем, которое сам объект сочтет нужным раскрыть). Каждый объект имеет доступ к любому необходимому для оказания услуг знанию (это не означает, что объект содержит на него ссылки). Объект - это что-то, естественным образом существующее в предметной области решаемой задачи, в отличие от модуля, который является логическим объединением элементов пространства решения. Модуль - это то, что конструируют, а объект - это результат моделирования. Таким образом, объекты - предметно-ориентированны.
@responsibility:Ответственность
Это та услуга, которую объект обещает оказать, обычно рассматривается с точки зрения клиента, потребителя. “К кому я могу обратиться за этой услугой?” - вопрос, помогающий найти ответственных, не зная ничего об их внутреннем устройстве и структуре. Поведенческий подход к моделированию предписывает сначала распределить ответственность по объектам и лишь затем определить, что объекты должны для этого знать. Четыре основных вида услуг:
- Предоставлять информацию по запросу. Например, объект “Описание”, являющийся по существу словарем.
- Осуществить вычисление.
- Изменить состояние или сообщить о своем состоянии. Это обычно реализуется через подписку на события.
- Координировать деятельность других объектов. Принцип “слепой координации”, когда объекты не знают, зачем и для чего они выполняют свои функции, как муравьи.
@message:Сообщение
Это формальная коммуникация между потребителем, запрашивающим услугу, и объектом, эту услугу предоставляющим. Возможные типы сообщений:
- Повелительное (imperative) - указывает объекту изменить что-либо в своем состоянии. Ответ обычно не ожидается, и никогда не требуется. Предполагается, что объект осуществил необходимые изменения.
- Информирующее (informational) - также не требует ответа, но при этом не ожидается изменений в состоянии объекта или его реакции на сообщение.
- Опрашивающее (interrogatory) - запрос на оказание услуги. Объект всегда возвращает другой объект, инкапсулирующий запрошенный результат.
@protocol:Интерфейс (протокол)
Метод, процесс и модели
@object-cubes:Объектный кубик
Производное от CRC-карточек единое связное представление объекта. Помогает мыслить объектно при декомпозиции, дизайне и даже в некоторых аспектах реализации.
- Классическая CRC-карточка. Содержит название класса, экземпляром которого будет моделируемый объект; список его ответственностей; ссылки на всех требуемых “напарников” (collaborators).
- Текстовое описание природы объектов, представленных этим классам. Здесь же должны быть указаны стереотипы класса и любые примечания, полезные при реализации.
- Контракты, разделенные на публичные, приватные и защищенные. Отражают намерения создателя класса относительно того, кто и какие сообщения может посылать экземпляру этого класса.
- Требуемое знание. Конкретные фрагменты данных, которые понадобятся объекту для выполнения своих обязанностей. Каждому фрагменту нужно присвоить описательную метку, идентификатор источника и имя класса, который будет содержать эти данные.
- Сообщения. Сигнатуры сообщений, на которые будет отвечать объект.
- События. Названия и описания событий (изменений состояния объекта), которые могут быть интересны другим объектам.
Обнаружение объектов
Причины ошибок на старте проектов
Антропология предметной области
Ссылки на другие источники:
- Wirfs-Brock, Weiner and Wilkerson’s Objected Oriented Design
- Rebecca Wirfs-Brock, Alan McKean Object Design
- Richard Pawson, Robert Mathews Naked Objects
- Wilkinson’s Using CRC cards
- McBreen, Peter Software Craftsmanship: The New Imperative
- West, David “Enculturating Extreme Programmers”, “Educating Xgilistas”
- Beck, Kent “Best Smalltalk Practice Patterns”
- Robert L. Glass Facts and Fallacies of Software Engineering (p.57)
- Peter Coad, книги после Object Oriented Analysis
- Marvin Minsky, Society of Mind