Я читал эту вики о Принципе стабильных абстракций (SAP) .
SAP заявляет, что чем стабильнее пакет, тем более абстрактным он должен быть. Это подразумевает, что если пакет менее стабилен (более вероятно, изменится), то он должен быть более конкретным. Что я действительно не понимаю, так это то, почему так должно быть. Конечно, во всех случаях, независимо от стабильности, мы должны зависеть от абстракций и скрывать конкретную реализацию?
design
design-patterns
architecture
object-oriented-design
design-principles
SteveCallender
источник
источник
Ответы:
Думайте о ваших пакетах как об API, чтобы взять пример из бумаги, взять определения для
Reader
сstring Reader.Read()
иWriter
сvoid Writer.Write(string)
как ваш абстрактный API.Затем вы можете создать класс
Copy
с методомCopier.Copy(Reader, Writer)
и реализациейWriter.Write(Reader.Read())
и, возможно, с некоторыми проверками работоспособности.Теперь, вы делаете конкретные реализации, например
FileReader
,FileWriter
,KeyboardReader
иDownloadThingsFromTheInternetReader
.Что если вы хотите изменить свою реализацию
FileReader
? Нет проблем, просто измените класс и перекомпилируйте.Что если вы хотите изменить определение своей абстракции
Reader
? К сожалению, вы не можете просто изменить, но вы также должны изменитьCopier
,FileReader
,KeyboardReader
иDownloadThingsFromTheInternetReader
.Это обоснование принципа стабильной абстракции: сделайте ваши конкретизации менее стабильными, чем абстракции.
источник
Из-за ЯГНИ .
Если у вас есть только одна реализация одной вещи , зачем беспокоиться о лишнем и бесполезном слое? Это приведет только к ненужной сложности. Хуже того, иногда вы предоставляете абстрактное мышление в тот день, когда придет вторая реализация ... и этот день никогда не случится. Какая трата труда!
Я также думаю, что реальный вопрос, который нужно задать себе, это не «Нужно ли мне зависеть от абстракций?» а скорее «Нужна ли модульность?». И модульность не всегда нужна, см. Ниже.
В компании, в которой я работаю, некоторые программы, которые я разрабатываю, тесно связаны с каким-либо аппаратным устройством, с которым оно должно взаимодействовать. Эти устройства разрабатываются для достижения очень конкретных целей и являются не только модульными. :-) После того , как первый произведенный устройство выходит из завода и устанавливается где - то, как его встроенное программное обеспечение и аппаратные средства никогда не может изменить, когда - либо .
Так что я могу быть уверен, что некоторые части программного обеспечения никогда не будут развиваться. Эти части не должны зависеть от абстракций, поскольку существует только одна реализация, и эта никогда не изменится. Объявление абстракций в этих частях кода только запутает всех и займет больше времени (без какого-либо значения).
источник
Я думаю, что вы, возможно, смущены словом « стабильный», которое выбрал Роберт Мартин. Вот где я думаю, что путаница начинается:
Если вы прочитаете оригинальную статью , вы увидите (выделение мое):
Я всегда боролся с авторским выбором слова « стабильный» , поскольку я (как и вы) склонен думать о «вероятностном» аспекте стабильности, т. Е. Вряд ли изменится . Сложность подразумевает, что изменение этого модуля сломает множество других модулей, и для исправления кода потребуется много работы.
Мартин также использует слова « независимый и ответственный» , которые для меня гораздо более значимы. На своем обучающем семинаре он использовал метафору о родителях детей, которые растут, и о том, как они должны быть «ответственными», потому что их дети зависят от них. Развод, безработица, тюремное заключение и т. Д. Являются отличными примерами того, как изменения в родителях будут влиять на детей. Поэтому родители должны быть «стабильными» на благо своих детей. Кстати, эта метафора детей / родителей не обязательно связана с наследованием в ООП!
Итак, следуя духу «ответственности», я придумал альтернативные значения, которые трудно изменить (или не следует менять ):
Итак, вставив эти определения в утверждение
Давайте процитируем принцип стабильной абстракции (SAP), подчеркнув запутанные слова стабильный / нестабильный:
Разъяснение без этих смущающих слов:
TL; DR
Название вашего вопроса спрашивает:
Я думаю, что если вы правильно создаете абстракции (например, они существуют, потому что от них зависит большой объем кода), то никаких существенных недостатков нет.
источник
Абстракции - это вещи, которые трудно изменить в программном обеспечении, потому что все зависит от них. Если ваш пакет будет часто меняться и содержит абстракции, люди, которые зависят от него, будут вынуждены переписать большую часть своего кода, когда вы что-то измените. Но если ваш нестабильный пакет предоставляет некоторые конкретные реализации, гораздо меньший код придется переписывать после изменений.
Таким образом, если ваш пакет будет часто меняться, он должен лучше предоставлять конкретные, а не абстракции. Иначе ... кто, черт возьми, будет его использовать? ;)
источник
Имейте в виду показатель стабильности Мартина и то, что он подразумевает под «стабильностью»:
Или:
То есть пакет считается полностью нестабильным, если все его зависимости являются исходящими: он использует другие вещи, но ничто его не использует. В этом случае имеет смысл только, чтобы эта вещь была конкретной. Это также будет самый простой вид изменения кода, так как ничто другое не использует его, и поэтому ничто другое не может сломаться, если этот код изменен.
Между тем, когда у вас есть противоположный сценарий полной «стабильности» с пакетом, используемым одной или несколькими вещами, но он ничего не использует сам по себе, например, центральный пакет, используемый программным обеспечением, тогда Мартин говорит, что эта вещь должна быть Аннотация. Это также подкрепляется частью DIP SOLI (D), принципом инверсии зависимостей, который в основном утверждает, что зависимости должны равномерно перетекать в абстракции как для кода низкого, так и высокого уровня.
То есть зависимости должны равномерно перетекать в сторону «стабильности», а точнее, зависимости должны перетекать в пакеты с большим количеством входящих зависимостей, чем исходящих, и, кроме того, зависимости должны перетекать в абстракции. Суть обоснования этого заключается в том, что абстракции предоставляют передовую возможность для замены одного подтипа на другой, предлагая такую степень гибкости для конкретных частей, реализующих интерфейс, чтобы изменить его, не нарушая входящие зависимости для этого абстрактного интерфейса.
Ну, я на самом деле не согласен с Мартином здесь, по крайней мере, в отношении моего домена, и здесь мне нужно ввести новое определение «стабильности», как «отсутствие причин для изменений». В этом случае я бы сказал, что зависимости должны стремиться к стабильности, но абстрактные интерфейсы не помогают, если абстрактные интерфейсы нестабильны (по моему определению «неустойчивые», как в случае склонности к многократным изменениям, а не Мартина). Если разработчики не могут получить правильные абстракции и клиенты неоднократно меняют свое мнение таким образом, что абстрактные попытки моделировать программное обеспечение становятся неполными или неэффективными, мы больше не выигрываем от расширенной гибкости абстрактных интерфейсов для защиты системы от каскадных изменений, нарушающих зависимость , В моем личном случае я нашел двигатели ECS, такие как те, что найдены в играх ААА,наиболее конкретный : к необработанным данным, но такие данные очень стабильны (например, «вряд ли когда-либо нужно будет менять»). Я часто находил вероятность того, что что-то, требующее будущих изменений, было бы более полезным показателем, чем отношение эфферентных к общему количеству связей при принятии решений SE.
Поэтому я бы немного изменил DIP и просто сказал бы, что «зависимости должны течь к компонентам, которые с наименьшей вероятностью требуют дальнейших изменений», независимо от того, являются ли эти компоненты абстрактными интерфейсами или необработанными данными. Все, что для меня имеет значение, - это вероятность того, что они могут потребовать непосредственного изменения дизайна. Абстракции полезны только в этом контексте стабильности, если что-то, будучи абстрактным, уменьшает эту вероятность.
Во многих случаях это может иметь место с приличными инженерами и клиентами, которые предвосхищают потребности программного обеспечения в первоначальной разработке и проектируют стабильные (как в неизменяемых) абстракции, в то время как эти абстракции предоставляют им все возможности, необходимые для замены конкретных реализаций. Но в некоторых областях абстракции могут быть нестабильными и склонными к неадекватности, в то время как данные, необходимые для движка, могут быть намного проще предвидеть и заранее сделать стабильными. Таким образом, в этих случаях это может быть более выгодно с точки зрения удобства сопровождения (простота изменения и расширения системы), когда зависимости направляются к данным, а не к абстракциям. В ECS наиболее нестабильные части (как в наиболее часто изменяемых частях) обычно представляют собой функциональные возможности, находящиеся в системах (
PhysicsSystem
Например, в то время как наиболее стабильные части (как, по крайней мере, вероятно, будут изменены) являются компонентами, которые просто состоят из необработанных данных (MotionComponent
например,), которые используют все системы.источник