Эта короткая статья будет состоять из нескольких разделов:
- Правило построения иерархии
- Обзор иерархии
- Замечания
- Следствия
Правило построения иерархии
Базовое правило для расположения принципов проектирования в иерархию будет следующим: если вы можете следовать принципу А, но отказаться или не знать о приеме B, то A является более базовым принципом проектирования. Например, вы можете разобраться с ООП, но пока не прочитать о шаблонах проектирования Gang of Four—это не помешает вам писать программы с использованием ООП; поэтому ООП является более базовым принципом. Или, например, вы можете отказаться от ООП (или от каких-то его атрибутов—например, наследования и полиморфизма), но, тем не менее, продолжать писать модульные программы на С с четкими интерфейсами модулей и уровнями абстракции. Поэтому модульность и абстракция являются более базовыми принципами, чем ООП.
Обзор иерархии
Итак, некоторые из тех немногих принципов проектирования, известных мне, я предпочитаю располагать на следующих уровнях:
- минимизации технической сложности
- модульность и абстракция; Keep it simple, stupid (KISS); Don’t repeat yourself (DRY)
- процедурное программирование; ООП; test-driven development (TDD); domain-driven design (DDD)
- шаблоны проектирования (Фаулера, Банды Четырех, MVC); SOLID
На картинке это будет выглядеть вот так (картинка включает в себя и иерархические связи, чем выгодно отличается от списка выше):
Замечания
Я предполагаю, что для людей, знакомых со всеми понятиями на диаграмме, логика связей должна быть прозрачной. Тем не менее, я остановлюсь на основных понятиях, связях и важных и скользких моментах.
Минимизация технической сложности
Что такое управление сложностью / минимизация технической сложности (с сохранением необходимого функционала, разумеется) и почему ее можно считать базовым принципом проектирования, можно узнать в прекрасной книжке Стива МакКоннела «Совершенный код» («Code Complete»), глава 5. Обсуждение начинается именно с термина «управление сложностью», но лично мне он кажется менее информативным.
Принцип KISS в каком-то смысле идентичен минимизации технической сложности, но, поскольку для него есть отдельная аббревиатура, я также включил его в диаграмму особым блоком.
Модульность и абстракция, или самые важные слова для инженеров
Многие начинающие программисты (и я сам, чего уж там) с восторгом делятся друг с другом наблюдением о том, что отличия в синтаксисе языков не являются критическими, потому что почти все мэйнстримовые языки в том или ином виде разделяют парадигму ООП. А ведь совершенно аналогичное заявление можно сделать и по отношению к принципам проектирования, будь то ООП или процедурное программирование, а именно: эти принципы схожи в своем стремлении обеспечить средства абстракции данных и операций (структуры и процедуры, классы и методы) и разбиения системы на модули.
Поэтому хотелось бы подробнее остановится на модульности и абстракции—понятиях, рассматриваемых в отличной книге «Structure and Interpretation of Computer Programs» («Структура и интерпретация компьютерных программ», SICP; первое издание в свободном доступе, второе—нет)—и процитировать введение к этой книге, которое, на мой взгляд, содержит в себе самые важные слова для инженеров.
Самые важные слова для инженеров
«We control complexity by building abstractions that hide details when appropriate. We control complexity by establishing conventional interfaces that enable us to construct systems by combining standard, well-understood pieces in a “mix and match way”. We control complexity by establishing new languages for describing a design, each of which emphasizes particular aspects of the design and deemphasizes others».
Еще раз: модульность и абстракция—основные способы управления сложностью; и это, на мой взгляд, самые важные идеи о разработке ПО и инженерной деятельности вообще, что мне довелось встречать (если кто-то читал еще интереснее—добро пожаловать в комментарии). Что может сравниться с наслаждением от сознания того, что вам не нужно помнить, как работает внутри используемый класс (или даже библиотека), в каком порядке вызывать его методы, какие ограничения накладываются на параметры?—потому что это все не имеет значения, ведь класс формирует правильную абстракцию и избавляет пользователя от деталей: методы можно вызывать в любом порядке, их семантика и семантика параметров очевидна, конфликтов с одновременно используемыми библиотеками не может быть и т.п.
Если вы хотите глубже проникнутся этими принципами, горячо рекомендую вам SICP и, как водится, МакКоннела. [Ремарки: конечно, многим эти книги будут известны, а цитата из SICP покажется банальной, но среди, по крайней мере, моих знакомых, профессиональных и высококвалифицированных программистов, очень многие не слышали о SICP—кто-то прогулял лекции, а кто-то учился на физика. И если вы знаете аналогичную книжку, но посовременне—добро пожаловать в комментарии].
Test-driven development и domain-driven design
Конечно, test-driven development и domain-driven design сложно представить без использования ООП, и, следовательно, изучать их необходимо после ООП, поэтому их можно было бы расположить на одном уровне с шаблонами проектирования.
С другой стороны, test-driven development вполне можно применять для программ на С, в которых не используется ни полиморфизм, ни наследование, но при написании которых можно проектировать архитектуру c расчетом на тестирование отдельных процедур и писать такие тесты. То же относится и к domain-driven design: программа может быть написана на C, но совершенно в духе DDD. Именно поэтому они помещены на один уровень с ООП.
Следствия
Правильные приоритеты в разработке
Если архитектура программы изобилует шаблонами проектирования и модными штуками типа Dependency Injection/Inversion of Control, это еще не значит, что программу будет легко понимать и сопровождать. Причина кроется в том, что есть более базовые принципы проектирования—модульность и абстракция, и архитектор может легко упустить их из виду в погоне за шаблонами. Помня об этой иерархии вы как архитектор больше не допустите подобную ошибку, а как разработчик всегда сможете легко вербализовать для архитектора, почему именно он не прав, совершая такую ошибку.
Правильные приоритеты в профессиональном росте и обучении (младших сотрудников или студентов)
Иерархия принципов проектирования, я надеюсь, сделает очевидным несколько фактов:
- прежде чем рекомендовать младшему инженеру книжку про ООП, лучше дать книжку про модульность и абстракцию (например, SICP)
- прежде чем рекомендовать книжку про шаблоны проектирования, лучше дать книжку про ООП
- и т.п.
Лучшее понимание существующих технологий
Например, что ООП—это не единственное средство создания уровней абстракций, и что процедурное программирование предназначено для тех же целей.
Всем спасибо за внимание!
P.S.
Вообще, раз уж я рекламировал SICP, называемую также Книгой Мага, в этой заметке, то надо для полноты картины порекомедовать Книгу Золушки и Книгу Дракона, являющиеся не менее фундаментальными. Итак, список сказочных книжек:
Опять же, многим эти книги покажутся банальными (особенно Книга Дракона), но, я полагаю, найдется и немало людей, кто впервые о них прочитает в этой статье.
ссылка на оригинал статьи http://habrahabr.ru/post/169487/
Добавить комментарий