Pull to refresh

POKA-YOKE проектирование: от «запаха» к благоуханию

Reading time3 min
Views17K
Original author: Mark Seemann
От переводчика. Это перевод серии постов из блога Марка Симана. Я не хочу объединять некоторые из постов, несмотря на то, что они небольшие по размеру, а просто постараюсь соблюсти структуру, предложенную Марком.

Ещё немного от переводчика. POKA-YOKE можно перевести как «дуракоустойчивый» или отказоустойчивый.

Инкапсуляция является одной из самых недопонимаемых концепций в объектно-ориентированном программировании (ООП). Похоже на то, что большая часть людей думает, что, имеющая отношение к инкапсуляции, концепция «сокрытия информации», просто означает, что закрытые поля должны быть раскрыты через публичные свойства (или getter\setter-методы в языках, которые не обладают поддержкой свойств).
Вы когда-нибудь задумывались о том, в чём состоит реальное преимущество в том, чтобы унаследовать такой код, как следующий?
private string name;
public string Name
{
    get { return this.name; }
    set { this.name = value; }
}

Для меня такой код выглядит ужасно избыточным (и автоматические свойства – не ответ, это всего лишь уловка компилятора, который, по-прежнему, будет создавать поле). Никакой информации, на самом деле, не сокрыто. Дерик Бейли написал хороший пост о том, почему такой способ инкапсуляции слишком узок, так что я не буду повторять его умозаключения здесь.
Так что же всё-таки означает инкапсуляция?
Основным преимуществом объектной ориентированности является производство связанных кусочков кода (классов), которые решают заданные проблемы раз и навсегда, таким образом, чтобы программисты могли использовать эти классы, ничего не зная об их внутренних деталях реализации.
В этом и состоит вся суть инкапсуляции: предложение (раскрытие) решения проблемы без требования с потребителя полного понимания предметной области.

Вот список того, что обеспечивают хорошо спроектированные классы:
  • Вы не обязаны понимать внутренние детали потока табличных данных (TDS) для того, чтобы использовать ADO.NET в связке с SQL Server.
  • Вы не обязаны понимать внутренние детали рисования на экране для того, чтобы использовать WPF или WinForms.
  • Вы не обязаны понимать внутренние детали рефлексии для того, чтобы использовать DI Container.
  • Вы не обязаны понимать то, как эффективно отсортировать список для того, чтобы отсортировать список, используя .NET-фреймворк.
  • И т.д.

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

Держите в уме то, что от пользователей не ожидается полное понимание внутренностей реализации класса. Это делает очевидным определение инкапсуляции:
Инкапсуляция это механизм обеспечения отказоустойчивости.

Из этого не следует, что инкапсуляция означает сокрытие сложностей. Всякий раз когда сложность скрыта (как случае с паттерном Provider) время обратной связи увеличивается. Быстрая обратная связь весьма предпочтительна, так что задержек в обратной связи желательно избегать, когда есть возможность.
Инкапсуляция не о сокрытии сложностей, напротив, о том, как раскрыть сложность в отказоустойчивом виде.

В Lean (прим. переводчика: бережливый процесс разработки ПО) это известно как дуракоустойчивость (poka-yoke), я нахожу единственно верным думать об инкапсуляции как о Poka-yoke дизайне: API, которые делают настолько сложным сделать что-либо неправильно, насколько это возможно.
Учитывая то, что компиляция это наиболее дешёвый механизм получения обратной связи, предпочтительно проектировать API так, чтобы код мог только скомпилироваться, если классы использованы правильно. (прим. переводчика. Я думаю, что правильнее сказать: «проектируйте API таким образом (по возможности), чтобы, в случаях его неправильного использования, пользователи получали ошибки компиляции, указывающие на проблему и, если это невозможно, то получали бы уведомление в ходе исполнения программы как можно раньше.)
В серии постов я рассмотрю различные «запахи» проектирования, которые нарушают инкапсуляцию и подготовлю руководство о том, как улучшить спроектированный код для того, чтобы сделать его более безопасным, переходя, таким образом, от «запахов» к благоуханию.
  1. «Запах» проектирования: временная связность.
  2. «Запах» проектирования: одержимость примитивами.
  3. «Запах» кода: автоматические свойства.
  4. «Запах» проектирования: излишний атрибут Required.
  5. «Запах» проектирования: конструктор по умолчанию.

Постскриптум: На границах, приложения не являются объектно-ориентированными.
Tags:
Hubs:
Total votes 36: ↑27 and ↓9+18
Comments16

Articles