Шаблоны GRASP: Low Coupling (низкая связанность) и High Cohesion (высокое зацепление)

    И снова здравствуйте. Меня зовут Владислав Родин. В настоящее время я являюсь руководителем курса «Архитектор высоких нагрузок» в OTUS, а также преподаю на курсах, посвященных архитектуре ПО.

    Специально к старту нового набора на курс «Архитектура и шаблоны проектирования» я продолжаю серию своих публикаций про шаблоны GRASP.




    Введение


    Описанные в книге Craig'а Larman'а «Applying UML and patterns, 3rd edition», GRASP'овские паттерны являются обобщением GoF'овских паттернов, а также непосредственным следствием принципов ООП. Они дополняют недостающую ступеньку в логической лестнице, которая позволяет получить GoF'овские паттерны из принципов ООП. Шаблоны GRASP являются скорее не паттернами проектирования (как GoF'овские), а фундаментальными принципами распределения ответственности между классами. Они, как показывает практика, не обладают особой популярностью, однако анализ спроектированных классов с использованием полного набора GRASP'овских паттернов является необходимым условием написания хорошего кода.

    Полный список шаблонов GRASP состоит из 9 элементов:

    • Information Expert
    • Creator
    • Controller
    • Low Coupling
    • High Cohesion
    • Polymorphism
    • Pure Fabrication
    • Indirection
    • Protected Variations

    В прошлый раз мы обсудили принцип Creator. Сейчас я предлагаю рассмотреть два принципа GRASP, которые имеет смысл рассматривать только в паре, потому что рассмотрение их по отдельности в пределе приводит к явно плохому коду. Эти принципы могут рассматриваться не только в контексте микропроектирования, но и при проектировании, например, микросервисов. Ниже поговорим о Low Coupling и High Cohesion.

    Low Coupling


    Формулировка


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

    Пример нарушения


    Самым ярким примером нарушения этого принципа, с моей точки зрения, является циклическая зависимость (да-да, то, за что обычно отрывают руки на code review):

    public class A {
        private int a;
        private B b;
       
        public A(int a) {
            this.a = a;
            this.b = new B(this);
        }
    }
    
    public class B {
        private A a;
        
        public B(A a) {
            this.a = a;
        }
    }
    

    На UML — диаграмме классов для такой системы можно будет увидеть как зависимость класса A на класс B, так и зависимость класса B на класс A. Почему это плохо? Дело в том, что мы не можем отдать класс A без класса B, также как и класс B без класса A: их нельзя переиспользовать по — отдельности, только вместе. Чем меньше связей между классами — тем лучше, вот о чем говорит нам принцип Low Coupling. Если вспомнить предыдущие разобранные нами принципы: Information Expert и Creator, то можно вспомнить, что соблюдение этих принципов приводит к уменьшению количества ненужных связей между классами.

    High Cohesion


    Формулировка


    Если возвести Low Coupling в абсолют, то достаточно быстро можно прийти к тому, чтобы разместить всю функциональность в одном единственном классе. В таком случае связей не будет вообще, но все при этом понимают, что что-то тут явно не так, ведь в этот класс попадет совершенно несвязанная между собой бизнес — логика. Принцип High Cohesion говорит нам следующее: классы должны содержать связанную бизнес — логику.

    Пример нарушения


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

    @AllArgsConstructor
    public class Data {
        private int temperature;
        private int time;
       
       private int calculateTimeDifference(int time) {
          return this.time - time; 
      }
    
      private int calculateTemperatureDifference(int temperature) {
          return this.temperature - temperature; 
      }
    }
    

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

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

    Пример соблюдения


    Имеет смысл создать 2 класса: один для температуры, другой для времени:

    @AllArgsConstructor
    public class Data {
        private TemperatureData temperatureData;
        private TimeData timeData;
       
       public Data(int time, int temperature) {
           this.temperatureData = new TemperatureData(temperature);
           this.timeData = new TimeData(time);
       }
    
       // тут логика по работе как со временем, так и с температурой
    
    }
    
    @AllArgsConstructor
    public class TimeData {
        private int time;
    
        private int calculateTimeDifference(int time) {
          return this.time - time; 
      }
    }
    
    @AllArgsConstructor
    public class TemperatureData {
        private int temperature;
    
        private int calculateTemperatureDifference(int temperature) {
          return this.temperature - temperature; 
      }
    }
    

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

    Вывод


    Low Coupling и High Cohesion представляют из себя два связанных между собой паттерна, рассматривать которые имеет смысл только вместе. Их суть можно объединить следующим образом: система должна состоять и слабо связанных классов, которые содержать связанную бизнес — логику. Соблюдение этих принципов позволяет удобно переиспользовать созданные классы, не теряя понимания об их зоне ответственности.



    Фабричный метод и абстрактная фабрика


    OTUS. Онлайн-образование
    Цифровые навыки от ведущих экспертов

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

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

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