Как я могу сказать, что в моем программном обеспечении слишком много абстракций и слишком много шаблонов проектирования, или наоборот, как мне узнать, должно ли их быть больше?
Разработчики, с которыми я работаю, программируют по-другому относительно этих моментов.
Некоторые действительно абстрагируют каждую небольшую функцию, по возможности используют шаблоны проектирования и избегают избыточности любой ценой.
Другие, в том числе и я, стараются быть более прагматичными и пишут код, который не совсем подходит для каждого шаблона проектирования, но гораздо быстрее для понимания, потому что применяется меньше абстракций.
Я знаю, что это компромисс. Как я могу узнать, когда в проект вложено достаточно абстракции и как узнать, что ему нужно больше?
Пример, когда общий слой кэширования написан с использованием Memcache. Действительно ли нам нужно Memcache
, MemcacheAdapter
, MemcacheInterface
, AbstractCache
, CacheFactory
, CacheConnector
, ... или это легче поддерживать и по- прежнему хороший код при использовании только половина из этих классов?
Нашел это в твиттере:
Ответы:
Сколько ингредиентов необходимо для еды? Сколько деталей вам нужно, чтобы собрать автомобиль?
Вы знаете, что у вас слишком мало абстракции, когда небольшое изменение реализации приводит к каскаду изменений во всем вашем коде. Правильные абстракции помогут выделить ту часть кода, которую необходимо изменить.
Вы знаете, что у вас слишком много абстракций, когда небольшое изменение интерфейса приводит к каскаду изменений во всем вашем коде на разных уровнях. Вместо того, чтобы менять интерфейс между двумя классами, вы модифицируете десятки классов и интерфейсов, просто чтобы добавить свойство или изменить тип аргумента метода.
Кроме того, на самом деле нет никакого способа ответить на вопрос, указав число. Количество абстракций не будет одинаковым для разных проектов, от языка к другому и даже от одного разработчика к другому.
источник
interface Doer {void prepare(); void doIt();}
), и это становится болезненным для рефакторинга, когда эта абстракция больше не подходит. Ключевой частью ответа является тест, применяемый, когда абстракция должна измениться - если она никогда не меняется, она никогда не причиняет боль.Проблема с шаблонами дизайна может быть подытожена пословицей «когда вы держите молоток, все выглядит как гвоздь». Акт применения шаблона проектирования не улучшается вашей программы вообще. На самом деле, я бы сказал, что вы делаете более сложную программу, если добавляете шаблон проектирования. Остается вопрос, хорошо ли вы используете шаблон проектирования или нет, и в этом суть вопроса: «Когда у нас слишком много абстракций?»
Если вы создаете интерфейс и абстрактный суперкласс для одной реализации, вы добавили в свой проект два дополнительных компонента, которые излишни и излишни. Смысл предоставления интерфейса в том, чтобы иметь возможность обрабатывать его одинаково во всей программе, не зная, как он работает. Задача абстрактного суперкласса - обеспечить базовое поведение для реализаций. Если у вас есть только одна реализация, вы получаете все интерфейсы усложнения и абстрактные классы, и ни одно из преимуществ.
Точно так же, если вы используете шаблон «Фабрика» и обнаруживаете, что создаете класс для использования функциональности, доступной только в суперклассе, шаблон «Фабрика» не добавляет никаких преимуществ вашему коду. Вы только добавили в свой проект дополнительный класс, которого можно было бы избежать.
TL; DR Я хочу сказать, что цель абстракции не является абстрактной сама по себе. Это служит очень практической цели в вашей программе, и прежде чем вы решите использовать шаблон проектирования или создать интерфейс, вам следует спросить себя, легче ли понять программу, несмотря на дополнительную сложность или более надежную программу несмотря на дополнительную сложность (желательно оба). Если ответ «нет» или «возможно», потратьте пару минут, чтобы подумать, почему вы хотели это сделать, и, возможно, это можно сделать лучше, а не обязательно добавлять абстракцию в ваш код.
источник
TL: DR;
Я не думаю, что есть «необходимое» количество уровней абстракций, ниже которых слишком мало или выше которых слишком много. Как и в графическом дизайне, хороший ООП дизайн должен быть невидимым и должен восприниматься как должное. Плохой дизайн всегда торчит как больной палец.
Длинный ответ
Скорее всего, вы никогда не узнаете, на каком уровне абстракций вы строите.
Большинство уровней абстракции невидимы для нас, и мы принимаем их как должное.
Это рассуждение приводит меня к такому выводу:
Одна из основных целей абстракции - избавление программиста от необходимости постоянно помнить о работе всей системы. Если дизайн заставляет вас слишком много знать о системе, чтобы что-то добавить, то, вероятно, абстракции слишком мало. Я думаю, что плохая абстракция (плохой дизайн, анемичный дизайн или чрезмерная инженерия) также может заставить вас слишком много знать, чтобы что-то добавить. В одной из крайностей у нас есть дизайн, основанный на бог-классе или группе DTO, а в другой - у нас есть несколько каркасов OR / persistance, которые заставляют вас прыгать через бесчисленные обручи для достижения мира приветствия. В обоих случаях вы слишком много знаете.
Плохая абстракция придерживается колокола Гаусса в том факте, что, как только вы минуете сладкое пятно, начинает мешать. Хорошая абстракция, с другой стороны, невидима, и ее не может быть слишком много, потому что вы ее не замечаете. Подумайте о том, сколько уровней на уровнях API, сетевых протоколов, библиотек, библиотек ОС, файловых систем, уровней аппаратного обеспечения и т. Д., На которых построено ваше приложение и которое воспринимается как должное.
Другая главная цель абстракции - разделение, поэтому ошибки не проникают за пределы определенной области, в отличие от двойного корпуса, а отдельные танки предотвращают полное затопление корабля, когда в части корпуса есть отверстие. Если модификации кода в конечном итоге приводят к ошибкам в, казалось бы, не связанных областях, то есть вероятность, что абстракции слишком мало.
источник
Шаблоны проектирования - это просто общие решения проблем. Важно знать шаблоны проектирования, но они являются лишь признаками хорошо разработанного кода (хороший код все еще может быть лишен банды набора шаблонов проектирования четырех ), а не причиной.
Абстракции как заборы. Они помогают разделить области вашей программы на тестируемые и взаимозаменяемые блоки (требования для создания нехрупкого нежесткого кода). И так же, как заборы:
Вы хотите абстракции в естественных точках интерфейса, чтобы минимизировать их размер.
Вы не хотите их менять.
Вы хотите, чтобы они разделяли вещи, которые могут быть независимыми.
Наличие одного в неправильном месте хуже, чем отсутствие его.
У них не должно быть больших утечек .
источник
Рефакторинг
Я не видел слово «рефакторинг», упомянутое ни разу до сих пор. Итак, поехали:
Не стесняйтесь внедрять новую функцию как можно более прямо. Если у вас есть только один простой класс, вам, скорее всего, не нужен интерфейс, суперкласс, фабрика и т. Д.
Если и когда вы заметите, что вы расширяете класс таким образом, что он становится слишком толстым, тогда самое время разорвать его на части. В то время имеет смысл подумать о том, как вы на самом деле должны это делать.
Шаблоны - инструмент разума
Шаблоны, или, точнее, книга «Шаблоны проектирования», созданная бандой из четырех человек, хороши, среди прочего, потому что они создают язык, на котором разработчики могут думать и говорить. Легко сказать «наблюдатель», «фабрика» или «фасад», и все знают , что это значит, прямо сейчас.
Таким образом, я считаю, что каждый разработчик должен иметь мимолетные знания по крайней мере о шаблонах в оригинальной книге, просто чтобы иметь возможность говорить о концепции ОО, не всегда объясняя основы. Следует ли вам использовать шаблоны каждый раз, когда появляется возможность сделать это? Скорее всего нет.
Библиотеки
Библиотеки, вероятно, являются единственной областью, где это может быть для того, чтобы ошибиться в сторону слишком большого количества вариантов на основе шаблонов, а не слишком малого. Изменение чего-либо с «толстого» класса на что-то с более производным от шаблона (обычно это означает, что больше и меньше классов) радикально изменит интерфейс; и это единственное, что вы обычно не хотите менять в библиотеке, потому что это единственное, что представляет реальный интерес для пользователя вашей библиотеки. Им было бы наплевать на то, как вы справляетесь с вашей функциональностью внутри, но они очень заботятся, если им постоянно приходится менять свою программу, когда вы делаете новую версию с новым API.
источник
Суть абстракции должна быть в первую очередь той ценностью, которую приносят потребителю абстракции, то есть клиенту абстракции, другим программистам и часто вам самим.
Если в качестве клиента, потребляющего абстракции, вы обнаружите, что вам нужно смешивать и сопоставлять множество различных абстракций, чтобы выполнить свою работу по программированию, то потенциально существует слишком много абстракций.
В идеале, многоуровневая структура должна объединять ряд нижних абстракций и заменять их простой и высокоуровневой абстракцией, которую ее потребители могут использовать без необходимости иметь дело с какой-либо из этих базовых абстракций. Если им приходится иметь дело с нижележащими абстракциями, слой просачивается (из-за того, что является неполным). Если потребителю приходится иметь дело со слишком многими различными абстракциями, то, возможно, не хватает слоев.
После рассмотрения значения абстракций для программистов-потребителей мы можем обратиться к оценке и рассмотрению реализации, такой как реализация DRY-ness.
Да, все дело в упрощении обслуживания, но мы должны сначала рассмотреть сложность обслуживания наших потребителей, предоставляя качественные абстракции и уровни, а затем рассмотреть возможность упрощения нашего собственного обслуживания с точки зрения аспектов реализации, таких как избежание избыточности.
Мы должны смотреть на точку зрения клиента, и если его жизнь становится проще, это хорошо. Если их жизнь сложнее, то это плохо. Тем не менее, может быть, что отсутствует слой, который объединяет эти вещи во что-то простое в использовании. Внутренне это может очень улучшить обслуживание реализации. Однако, как вы подозреваете, также возможно, что это просто чрезмерно спроектировано.
источник
Абстракция предназначена для облегчения понимания кода. Если слой абстракции сделает вещи более запутанными - не делайте этого.
Цель состоит в том, чтобы использовать правильное количество абстракций и интерфейсов для:
Аннотация только при необходимости
Не абстрагируйся когда
Некоторые примеры
источник
Я думаю, что это может быть спорный мета-ответ, и я немного опоздал на вечеринку, но я думаю, что очень важно упомянуть об этом здесь, потому что я думаю, что знаю, откуда вы.
Проблема с тем, как используются шаблоны проектирования, состоит в том, что, когда их обучают, они представляют такой случай:
Проблема в том, что когда вы начинаете заниматься реальной инженерией, все не так уж и скучно. Шаблон дизайна, о котором вы читаете, не совсем подходит к проблеме, которую вы пытаетесь решить. Не говоря уже о том, что используемые вами библиотеки полностью нарушают все, что указано в тексте, объясняющем эти шаблоны, каждая по-своему. В результате код, который вы пишете, «чувствует себя неправильно», и вы задаете такие вопросы, как этот.
В дополнение к этому, я хотел бы процитировать Андрея Александреску, говоря о разработке программного обеспечения, который заявляет:
Возможно, это немного преувеличение, но я думаю, что это прекрасно объясняет дополнительную причину, по которой вы можете чувствовать себя менее уверенно в своем коде.
В такие времена в моей голове кричит пророческий голос Майка Актона, ведущего игрового движка в Insomniac:
Он говорит о входах в вашу программу и желаемых результатах. И еще есть этот драгоценный камень Фреда Брукса из Мистического Месяца Человека:
Поэтому на вашем месте я бы рассуждал о своей проблеме, основываясь на моем типичном случае ввода и на том, достигает ли он желаемого правильного результата. И задавайте такие вопросы:
Когда вы это сделаете, вопрос о том, «сколько слоев абстракции или шаблонов проектирования необходимо» становится намного проще. Сколько слоев абстракции вам нужно? Столько, сколько необходимо для достижения этих целей, и не более. «А как насчет шаблонов дизайна? Я не использовал ни одного!» Что ж, если вышеуказанные цели были достигнуты без непосредственного применения шаблона, то это нормально. Заставьте это работать, и переходите к следующей проблеме. Начните с ваших данных, а не с кода.
источник
Архитектура программного обеспечения изобретает языки
На каждом программном уровне вы создаете язык, на котором вы (или ваши коллеги) хотите выразить свое решение следующего уровня выше (поэтому я добавлю некоторые аналоги на естественном языке в своем посте). Ваши пользователи не хотят тратить годы на изучение того, как читать или писать на этом языке.
Этот взгляд помогает мне при решении архитектурных вопросов.
читабельность
Этот язык должен быть легко понят (делая код следующего уровня читабельным). Код читается гораздо чаще, чем написан.
Одна концепция должна быть выражена одним словом - один класс или интерфейс должен раскрывать концепцию. (Славянские языки обычно имеют два разных слова для одного глагола английского языка, поэтому вам нужно выучить дважды словарный запас. Все естественные языки используют отдельные слова для нескольких понятий).
Представленные вами концепции не должны содержать неожиданностей. Это в основном соглашения об именах, такие как методы get, set и т. Д. И шаблоны проектирования могут помочь, поскольку они предоставляют стандартный шаблон решения, а читатель видит «ОК, я получаю объекты с фабрики» и знает, что это значит. Но если простая инстанцияция конкретного класса делает свою работу, я бы предпочел это.
Удобство использования
Язык должен быть простым в использовании (что позволяет легко формулировать «правильные предложения»).
Если все эти классы / интерфейсы MemCache становятся видимыми для следующего уровня, это создает крутую кривую обучения для пользователя, пока он не поймет, когда и где использовать какое из этих слов для единой концепции кэша.
Предоставление только необходимых классов / методов облегчает пользователю поиск того, что ему нужно (см. Цитату Антуана де Сент-Экзюпери DocBrowns). Предоставление интерфейса вместо реализующего класса может сделать это проще.
Если вы демонстрируете функциональность, в которой может применяться установленный шаблон проектирования, лучше следовать этому шаблону проектирования, чем изобретать что-то другое. Ваш пользователь поймет, что API следует шаблону проектирования легче, чем какое-то совершенно другое понятие (если вы знаете итальянский, испанский будет для вас легче, чем китайский).
Резюме
Ввести абстракции, если это облегчает использование (и стоит затрат на поддержание как абстракции, так и реализации).
Если в вашем коде есть (нетривиальная) подзадача, решите ее «ожидаемым образом», т.е. следуйте подходящей схеме проектирования, а не изобретайте колесо другого типа.
источник
Важно учитывать, что нужно знать об этих классах, связанных с кэшированием, потребляющему коду, который фактически обрабатывает вашу бизнес-логику. В идеале ваш код должен заботиться только об объекте кэша, который он хочет создать, и, возможно, о фабрике, которая создаст этот объект, если метод конструктора не достаточен.
Количество используемых шаблонов или уровень наследования не слишком важны, поскольку каждый уровень может быть оправдан для других разработчиков. Это создает неформальный лимит, так как каждый дополнительный уровень труднее обосновать. Более важной частью является то, как много уровней абстракции затрагиваются изменениями функциональных или бизнес-требований. Если вы можете внести изменения только в один уровень для одного требования, то, скорее всего, вы не слишком абстрагированы или плохо абстрагированы, если вы измените тот же уровень для нескольких несвязанных изменений, вы, вероятно, недостаточно абстрагированы и нуждаетесь в дальнейшем разделении проблем.
источник
Во-первых, цитата из Твиттера фальшивая. Новым разработчикам нужно разобрать модель, абстракции, как правило, помогают им «получить картину». При условии, что абстракции имеют смысл, конечно.
Во-вторых, ваша проблема не слишком много или слишком мало абстракций, это то, что, очевидно, никто не может решить эти вещи. Никто не владеет кодом, никакой единый план / дизайн / философия не реализован, любой следующий парень может делать то, что ему кажется подходящим для этого момента. Какой бы стиль вы ни выбрали, он должен быть один.
источник