Со временем я смог понять две части SOLID - «S» и «O».
«O» - я выучил принцип Open Closed с помощью модели наследования и стратегии.
«S» - я изучил принцип единой ответственности при изучении ORM (логика персистентности отбирается у объектов домена).
Аналогичным образом, какие области / задачи лучше всего изучать для других частей SOLID («L», «I» и «D»)?
Ссылки
Ответы:
Я был на твоем месте пару месяцев назад, пока не нашел очень полезную статью.
Каждый принцип хорошо объясняется в реальных ситуациях, с которыми каждый разработчик программного обеспечения может столкнуться в своих проектах. Я сокращаюсь здесь и указываю на ссылку - Разработка твердого программного обеспечения, один шаг за раз .
Как отмечается в комментариях, есть еще одно очень хорошее чтение PDF - SOLID Software Development от Pablo .
Кроме того, есть несколько хороших книг, которые более подробно описывают принципы SOLID - Good Book по разработке программного обеспечения SOLID .
Редактируйте и комментируйте краткое резюме по каждому принципу:
«S» - принцип единой ответственности обусловлен потребностями бизнеса в разрешении изменений. «Одна причина для изменения» помогает вам понять, какие логически отдельные концепции следует объединять, рассматривая бизнес-концепцию и контекст, а не только техническую концепцию.
In another words
Я узнал, что каждый класс должен нести одну ответственность. Ответственность заключается в том, чтобы просто выполнить поставленную задачу«О» - я выучил принцип Open Closed и начал «предпочитать композицию, а не наследование» и, как таковой, предпочитая классы, которые не имеют виртуальных методов и, возможно, запечатаны, но зависят от абстракций для их расширения.
«L» - я изучил принцип подстановки Лискова с помощью шаблона репозитория для управления доступом к данным.
Поскольку полезный ресурс из CodePlex упоминался в комментариях, ссылка на SOLID включена в качестве примера.
источник
(I) Сегрегация интерфейса и (D) инверсия зависимостей могут быть изучены с помощью модульного тестирования и насмешек. Если классы создают свои собственные зависимости, вы не можете создавать хорошие модульные тесты. Если они зависят от слишком широкого интерфейса (или вообще без интерфейса), не очень очевидно, что нужно смоделировать для проведения модульных тестов.
источник
Принцип подстановки Лискова в принципе не позволяет вам чрезмерно использовать наследование реализации: вы никогда не должны использовать наследование только для повторного использования кода (для этого есть состав)! Придерживаясь LSP, вы можете быть уверены, что между вашим суперклассом и вашим подклассом действительно существуют отношения «есть отношения».
Это говорит о том, что ваши подклассы должны реализовывать все методы подкласса аналогично реализации методов в подклассе. Вы никогда не должны переопределять метод с реализацией NOP или возвращать нуль, когда супертип генерирует исключение; указанные в Условиях проектирования по контракту, вы должны соблюдать контракт метода из суперкласса при переопределении метода. Способ защиты от нарушения этого принципа состоит в том, чтобы никогда не отменять реализованный метод; вместо этого извлеките интерфейс и реализуйте этот интерфейс в обоих классах.
Принцип разделения интерфейсов, принцип единой ответственности и принцип высокого сцепления от GRASP так или иначе связаны между собой; они ссылаются на тот факт, что организация должна нести ответственность только за одну вещь, так что есть только одна причина для изменения, чтобы изменение было сделано очень легко.
Это фактически говорит о том, что если класс реализует интерфейс, то он должен реализовать и использовать все методы этого интерфейса. Если есть методы, которые не нужны в этом конкретном классе, то интерфейс не годится и должен быть разбит на два интерфейса, в котором есть только методы, необходимые исходному классу. Это может быть рассмотрено из POV, который относится к предыдущему принципу тем, что он не позволяет создавать большие интерфейсы, чтобы их реализация могла нарушить LSP.
Вы можете видеть Инверсию Зависимости в Заводском Образце; здесь и компонент высокого уровня (клиент), и компонент низкого уровня (отдельный экземпляр, который будет создан) зависят от абстракции(интерфейс). Способ применить его в многоуровневой архитектуре: вы не должны определять интерфейс для слоя в слое, который реализован, а в вызываемом модуле. Например, API для уровня источника данных должен быть записан не на уровне источника данных, а на уровне логики бизнеса, где он должен быть вызван. Таким образом, уровень источника данных наследует / зависит от поведения, определенного в бизнес-логике (таким образом, инверсия), а не наоборот (как было бы в обычном порядке). Это обеспечивает гибкость проектирования, позволяя бизнес-логике работать без каких-либо изменений кода с другим совершенно другим источником данных.
источник