You get a bonus - 1 coin for daily activity. Now you have 1 coin

2.4.9 High Cohesion Pattern - 2.4 Patterns of behavior

Lecture



Это окончание невероятной информации про паттерны поведения.

...

objects;

  • from simple commands, you can assemble composite ones, for example, the MacroCommand class, discussed above. In general, compound commands are described by a linker pattern;
  • adding new commands is easy since no existing classes need to be modified.
  • Structure

    2.4 Patterns of behavior

    Figure 2.41 Command Pattern Structure

    In the following diagram (Fig. 2.42), you can see how the Command breaks the connection between the initiator and the recipient (as well as the request that the latter must fulfill).

    2.4.9 High Cohesion Pattern

    Title

    High Cohesion (weak gearing)

    Problem

    In terms of object-oriented design, cohesion (or, more precisely, functional gearing) is a measure of coherence and focus of class duties. An element is considered to have a high degree of engagement if its duties are closely related to each other and it does not perform exorbitant amounts of work.

    2.4 Patterns of behavior

    Figure 2.42 Command Pattern. Object Interaction

    In the role of such elements may be classes, subsystems, etc. A class with a low degree of engagement performs many disparate functions or unrelated duties. It is undesirable to create such classes because they lead to the following problems.

    • Difficulty of understanding.
    • Difficulties with repeated use.
    • Difficulty of support.
    • Unreliability, constant exposure to change.

    Classes with a weak link are usually too “abstract” or perform duties that can be easily distributed among other objects.

    Decision

    Distribution of duties, maintaining a high degree of engagement.

    results

    • Clarity and simplicity of design solutions are enhanced.
    • Simplified support and refinement.
    • Often weak binding is provided.
    • Reusability is improved as a class with a high degree of engagement performs a specific task.

    Example

    To analyze the High Cohesion pattern, you can use the same example as for Low Coupling. Suppose you need to create an instance of the Payment object and associate it with the current sale. What class should fulfill this duty? Since in the real subject area, payment information is recorded in the registry, according to the Creator template, you can use a Register object to create an instance of the Payment object. Then an instance of the Register object will be able to send the message addPayment to the Sale object, passing as a parameter a new instance of the Payment object, as shown in Fig. 2.43.

    2.4 Patterns of behavior

    Figure 2.43 An example interaction diagram. Low gearing

    With this distribution of responsibilities, payments are made by the Register object, i.e. The Register object is partially responsible for performing the system operation makePayment.
    In this particular example, this is acceptable. However, if you continue to assign to the Register class responsibilities for the implementation of new and new functions associated with other system operations, then this class will be too overloaded and will have a low degree of hooking. Suppose an application must perform fifty system operations and all of them are assigned to the Register class. If this object performs all operations, it will become excessively “bloated” and will not have the property: link. And the point is not that one task of creating an instance of a Payment object in itself reduced the degree of hooking of a Register object; it is part of the overall picture of the distribution of responsibilities.

    2.4 Patterns of behavior

    Figure 2.44 An example interaction diagram. High gearing

    Figure 2.44 presents another version of the distribution of responsibilities. Here the function of creating a payment instance is delegated to the Sale object. Due to this, a higher degree of linking of the Register object is maintained. Since this variant of the distribution of duties provides a low level of binding and a higher degree of engagement, it is more preferable. In practice, the level of engagement is not considered in isolation from other responsibilities and principles provided by the Expert and Low Coupling patterns.

    When not to use a pattern

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

    Другой пример слабого зацепления имеет отношение к распределенным серверным объектам. Поскольку быстродействие системы определяется производительностью удаленных объектов и их взаимодействием, иногда желательно создать несколько более крупных серверных объектов со слабым зацеплением, предоставляющих интерфейс многим операциям. Эта ситуация связана также с шаблоном Coarse-Grained Remote Interface (Укрупненный удаленный интерфейс), в рамках которого создаются укрупненные удаленные операции, выполняющие больше функций. Такое проектное решение объясняется повышенным влиянием удаленных вызовов на производительность сети. В качестве альтернативы вместо удаленного объекта с тремя операциями setName, setSalary и setHireDate лучше реализовать одну укрупненную удаленную операцию setDate, работающую с целым множеством данных. Это приведет к уменьшению числа удаленных вызовов и, как следствие, к повышению производительности.

    2.4.10 Паттерн Don't Talk To Strangers

    Title

    Don't Talk to Strangers (не разговаривай с незнакомцами). Известен, так же, под именем Law of Demeter (Закон Деметры)

    Description

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

    • Объекту this (self).
    • Параметрам метода.
    • Атрибуту объекта this (self).
    • Элементу контейнера, являющемуся атрибутом this (self).
    • Объекту, созданному внутри метода.

    Все перечисленные объекты называются прямыми объектами. Все остальные – непрямые. Отсюда можно сказать, что в соответствии с паттерном Don't Talk to Strangers, метод объекта может посылать сообщения только прямым объектам и некому более. Для выполнения этого требования прямым объектам могут понадобиться новые операции, которые выступают в роли дополнительных операций, позволяющих избежать разговора с незнакомцами.

    Consider an example. Предположим, что в приложении розничной торговли экземпляр класса POST, имеет атрибут, ссылающийся на объект Sale, атрибут которого, в свою очередь, ссылается на объект Payment (см. рис. 2.45).

    При способе взаимодействия объектов, представленном на рис. 2.47, мы имен нарушение условий паттерна Don't Talk to Strangers. Объект POST посылает сообщение объекту Payment, хотя по условиям паттерна он не должен этого делать.

    Во втором случае, условия паттерна выполняются. Но, для этого нам пришлось добавить в интерфейс объекта Sale еще один метод (paymentAmount). Такой ход называется обеспечением интерфейса (promoting the interface) и является общим решением данной проблемы.

    results

    Благодаря паттерну Don't Talk to Strangers нет необходимости обеспечивать видимость непрямых объектов, что в свою очередь повышает зацепление и понижает степень связности объектов.

    Нарушение закона

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

    2.4 Patterns of behavior

    Рисунок 2.45. Система POST. Фрагмент диаграммы классов

    2.4 Patterns of behavior

    Рисунок 2.46 Способов взаимодействия объектов, нарушающий закон Деметры.

    2.4 Patterns of behavior

    Рисунок 2.47 Способов взаимодействия объектов, не нарушающий закон Деметры.

    2.4.11 Паттерн Polymorphism

    Title

    Polymorphism (полиморфизм).

    Task

    С помощью полиморфных операций позволяет обеспечить изменяемое поведение без проверки типа. Данный паттерн является обобщением нескольких GoF-паттернов.

    Decision

    Условная передача управления – основной элемент любой программы. Если программа разработана с использованием условных операторов типа if-then-else, или switch-case, то при добавлении новых вариантов поведения приходится модифицировать логику условных операторов. Такой подход усложняет процесс модификации программы в соответствии с новыми вариантами поведения, поскольку изменения приходится вносить сразу в нескольких местах программного кода – там, где используются условные операторы.

    Паттерн Polymorphism описывает такой способ построения системы, при котором зависящие от типа варианты поведения реализуются посредством виртуальных операций.

    Example

    Рассмотрим все ту же систему розничной торговли. Предположим, что оплата в этой системе может проводиться несколькими способами: наличными (CashPayment), чеком (CheckPayment) или по кредитной карте (CreditPayment). Согласно шаблону Polymorphism необходимо распределить обязанности по авторизации каждого из типа платежей. Для этого можно использовать полиморфную операцию authorize (см. рис. 2.48). Реализации каждой такой операции будут различны. Например, объект CreditPayment должен взаимодействовать со службой авторизации кредитных платежей и т.д.

    2.4 Patterns of behavior

    Рисунок 2.48 Структура паттерна Polymorphism (пример)

    results

    • Паттерн позволяет легко расширять систему, добавляя в нее новое поведение и не изменяя при этом клиентов, относительно этого поведения.

    2.4.12 Паттерн Pure Fabrication

    Title

    Pure Fabrication (чистая синтетика)

    Task

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

    Decision

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

    Example

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

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

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

    Естественным решением данной проблемы является создание нового класса, ответственного за сохранение объектов некоторого вида на постоянном носителе. Этот класс не выявляется из деловой среды, его там нет, он является продуктом нашего воображения и не более.

    Естественно, организация хранения состояния объектов в БД – далеко не единственная задача, для решения которой может пригодиться паттерн Pure Fabrication. Многие GRASP паттерны построены на этой идее – Adapter, Visitor, Observer. Подводя итог применимости Pure Fabrication можно сказать, что с помощью этого паттерна обеспечиваются решения задач, не имеющих аналогий в деловой среде, но возникающих при программировании.

    Pure Fabrication относится к абстракциям поведения (напоминаю, это вторые по полезности абстракции после абстракций сущностей).

    results

    Обеспечиваются паттерны Low Coupling и High Cohesion.

    2.4.13 Паттерн Controller

    Проблема

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

    Системное событие (system event) — это событие высокого уровня, генерируемое внешним исполнителем (событие с внешним входом). Системные события связаны с системными операциями (systemoperation), т.е. операциями, выполняемыми системой в ответ на события.

    Например, когда кассир в POS-системе щелкните на кнопке Оплатить, он генерирует системное событие, свидетельствующее о завершении торговой операции. Аналогично, когда пользователь текстового процессора выбирает команду Орфография, он генерирует системное событие "выполнить проверку орфографии".

    Контроллер (controller) — это объект, не относящийся к интерфейсу пользователя и отвечающий за обработку системных событий. Контроллер определяет методы для выполнения системных операций.

    Decision

    Делегирование обязанностей по обработке системных сообщений классу, удовлетворяющему одному из следующих условий.

    • Класс представляет всю систему в целом, устройство или подсистему (внешний контроллер).
    • Класс представляет сценарий некоторого прецедента, в рамках которого выполняется обработка всех системных событий, и обычно называется <Прецедент>Наndlег,<Прецедент>Coordinator или <Прецедент> Session (контроллер прецедента или контроллер сеанса).
    • Для всех системных событий в рамках одного сценария прецедента используется один и тот же класс-контроллер.
    • Неформально, сеанс — это экземпляр взаимодействия с исполнителем. Сеансы могут иметь произвольную длину, но зачастую организованы в рамках прецедента (сеансы прецедента).

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

    Benefits

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

    Контроль состояния прецедента. Иногда необходимо удостовериться, что системные операции выполняются в некоторой определенной последовательности. Например, необходимо гарантировать, чтобы операция makePayment выполнялась только после операции EndSale, для чего необходимо накапливать информацию о последовательности событий. Для этой цели удобно использовать контроллер, особенно контроллер прецедента.

    Раздутый контроллер

    Плохо спроектированный класс контроллера имеет низкую степень зацепления: он выполняет слишком много обязанностей и является несфокусированным. Такой контроллер называется раздутым (bloated controller). Признаки раздутого контроллера таковы.

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

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

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

    Продолжение:


    Часть 1 2.4 Patterns of behavior
    Часть 2 2.4.9 High Cohesion Pattern - 2.4 Patterns of behavior


    Comments


    To leave a comment
    If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
    To reply

    Object oriented programming

    Terms: Object oriented programming