Бывает так что проект заходит в тупик, и дальнейшее его развитие становится невозможным. Не редко причиной такого провала становится неудачная архитектура, заложенная в начале разработки. Или приходится наблюдать споры о том какой из "двух стульев" лучше, а может даже участвовать и искренне не понимать, как оппонент может так думать!?
Тогда попробуем не много разобраться в абстракциях, откуда они берутся и что с ними делать.
Согласно Википедии Абстракция – это теоретическое обобщение как результат абстрагирования. В свою очередь абстрагирование – это отвлечение в процессе познания от несущественных сторон, свойств, связей объекта (предмета или явления) с целью выделения их существенных, закономерных признаков.
Из определения можно сделать вывод, что абстракцией может быть только осмысленное. При этом восприятие является лишь проекцией реального мира. Получается, что все размышления о реальном, являются размышлениями о наших моделях реального.
Абстракции формируют иерархии, и могут отождествляться как с частными сущностями, так и объединять схожие сущности в более высокоуровневые абстракции.
Абстракции в сознании
Кроме призмы восприятия, наши модели подвергаются ещё одному искажению: реальные сущности чрезвычайно сложны и имеют разные аспекты и параметры. При размышлении или разговоре о чём-то, всегда существует контекст, в котором существует модель. Причём иногда бывает так, что у собеседников этот контекст разный. И в довершение, наличие или отсутствие опыта (глобального) приводит к ещё большему изменению наших моделей в соответствие с этим опытом. В итоге у двух разных людей может быть очень разное восприятие одних и тех же сущностей реального мира.
Выходит, что каждый человек постоянно имеет дело с абстракциями, осталось научиться их явно видеть и управлять. Можно выдвинуть тезис, что программный код — это симуляция
Абстракции в разработке
Программные интерфейсы — это, пожалуй, самая явная формализованная абстракция. Отсекается все лишнее и остаётся только «что оно делает» без «как оно делает».
Реализуя интерфейс, мы создаём более реальную модель поведения или взаимодействия, которая уже может ответить на вопрос «как». Комбинируя интерфейсы между собой, мы можем создать общую архитектуру кода. При должном умении и сноровке архитектура, созданная таким образом, в будущем будет сохранять свою структуру. В то время как реализации составных интерфейсов могут изменяться до неузнаваемости.
Такая архитектура упрощает некоторые моменты в работе. Модульное тестирование сводится к написанию тестовых реализаций «соседних» абстракций и тестовых методов, сравнивающих вход и выход. Изоляция модулей позволяет безопасно проводить рефакторинг. Более того, если рефакторинг прошёл неудачно и всё сломалось, то откатывать придётся всего один модуль. Достаточно абстрагированный модуль может использоваться для схожих, но разных задач. При этом одна плохая реализация не будет влиять на работу других – изоляция говнокода.
Есть модуль для обработки входных данных, есть несколько вариантов их получения: из базы данных; из файла; по http. Решить эту задачу можно, выделив общий интерфейс для получения данных и сделав по реализации для каждого канала и канал данных для тестирования. Теперь один обработчик с помощью параметра «канал данных» может решать несколько схожих задач. А если выяснится, что одна из реализаций кривая, то её можно будет переделать на затрагивая другие модули.
Абстракций больше не надо
Не бывает идеальных решений, так же и с абстракциями не всё так гладко. Во-первых, абстракции субъективны, они могут вызывать споры о том, где начинается одна и начинается другая. Также существует проблема чрезмерного абстрагирования, когда под каждый вид и тональность чиха создаётся своя абстракция. Во-вторых, это подход повышает сложность кода, добавляя новые сущности, и новые уровни иерархии. Я уверен, что найдутся ещё недостатки этого подхода, часть из них будет субъективными, часть ситуационной, но будут и
Во всём должен быть баланс. Для себя я вывел следующую памятку.
- Если пишется большой и важный модуль – лучше расцеплять его.
- Если модуль используется много и/или в разных местах – лучше скрыть его за абстракцией.
- Если модуль должен распространяться как отдельная библиотека – лучше использовать абстракции.
- Если возможно изменение алгоритмов или путей взаимодействия – лучше реализовывать взаимодействие абстракций.
- Если класс используется в другом классе и нигде больше – можно подумать об их объединении или оставить как есть.
- Если это маленькая «одноразовая» задача – лучше не заморачиваться с её усложнением.
- Если это модуль, который скорее всего никогда не будет меняться – можно вывести его интерфейс и лучше оставить внутри всё как есть.
Итого
Абстракции — это инструмент, встроенный в наше сознание, как и любой другой они имеют свои плюсы и минусы, но знание альтернатив только помогает находить лучший путь.
Автор: ConstKosyanov