Каждый объект должен иметь одну обязанность и эта обязанность должна быть полностью инкапсулирована в класс, а все его сервисы должны быть направлены исключительно на обеспечение этой обязанности.
Программные сущности (классы, модули, функции и т. п.) должны быть открыты для расширения, но закрыты для изменения. Это означает, что эти сущности могут менять свое поведение без изменения их исходного кода.
Функционал, который наследуется от базового типа должен иметь возможность использовать функционал базового типа. Выносим только общий функционал из классов в базовый класс.
Клиенты не должны зависеть от методов, которые они не используют. То есть если какой‑то метод интерфейса не используется клиентом, то изменения этого метода не должны приводить к необходимости внесения изменений в клиентский код.
Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Пример с магазином и системами оплаты в нем. Если прописать жесткую связь с типом оплаты, то при добавлении нового типа оплаты нужно будет много рефакторить