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

Ортогональный дизайн - это союз двух принципов: сплоченности и сцепления.

Сплоченность

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

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

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

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

Связь

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

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

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

Два простых примера

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

Пример словаря 1

Приведенный выше пример прост. Мы храним определения в хэше и используем два метода read_dictionary и write_dictionary для управления чтением и записью в файловую систему в виде обычного текста или XML.

Пример словаря 2

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

Анализ

Давайте начнем с рассмотрения этих примеров, используя принцип сплоченности. Выше мы узнали, что общие процедуры, распространенные среди множества контекстов, указывают на низкую сплоченность. В примере 1 есть три общие задачи, которые распределены между несколькими контекстами. Во-первых, и это наиболее очевидно, логика, определяющая формат файла, повторяется в методах read_dictionary и write_dictionary. Во-вторых, задачи форматирования XML распределяются между методами read_dictionary и write_dictionary. И, наконец, задачи форматирования обычного текста также распределяются между методами read_dictionary и write_dictionary. Добавление или удаление формата файла, изменение формата XML или изменение формата обычного текста - все это требует изменения методов read_dictionary и write_dictionary.

Однако в примере 2 логика формата файла, логика форматирования XML и логика форматирования простого текста ограничены своим собственным контекстом. Логика формата файла ограничена методом класса Dictionary instance. Задачи форматирования XML ограничены объектом XMLDictionary. А задачи форматирования обычного текста ограничены объектом TextDictionary. Класс Dictionary, объект XMLDictionary и объект TextDictionary обладают более высокой функциональной связностью, чем методы в примере 1. В результате легче вносить изменения. Нам не нужно было бы выискивать несколько контекстов при добавлении формата файла.

Теперь давайте разберем примеры по принципу сцепления. В примере 1 два метода write_dictionary и read_dictionary связаны вместе. Хотя эти два метода явно не зависят друг от друга, они неявно связаны через формат файла. Любые изменения в логике формата файла потребуют изменения обоих методов.

Однако в примере 2 логика форматирования файлов отделена от форматирования чтения / записи. Вы можете изменить логику формата файла, не изменяя логику форматирования XML или обычного текста. Предположим, например, что требования изменились. Мы хотим принять имя файла без расширения как обычный текст. Вам нужно только изменить метод класса Dictionary.instance. Вам не нужно прикасаться к методам read или write подклассов Dictionary. В примере 1 вам нужно будет изменить метод read_dictionary и метод write_dictionary.

Пример 2 также уменьшил связь между управляющим кодом и объектами модели. Обратите внимание, как управляющий код вообще не заботится о формате файла. Его не волнует, работает ли он с объектом XMLDictionary или объектом TextDictionary. Мы можем легко добавить или удалить формат файла, не внося никаких изменений в управляющий код.

Вывод

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

Эта статья изначально была опубликована на www.jasoncoffin.com.