You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
a module should be responsible to one, and only one, actor
a class should have only one reason to change
solves the problem of God objects, tight coupling and change chains (and more)
Solution: Don't rely on technology but rely on functionality (feature)!
E.g. don't depend on email technology but depend on messenging functionality.
Sending the message via email becomes a hidden and technical implementation detail.
Open closed principle
software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification
once a software module is completed, it should not be modified when adding new functionality
instead its behavior should be extended by adding new code, rather than changing existing code
Solution: Make a class final and use the decorator pattern!
Liskov substitution principle
we should be able to replace a class with a subclass without any unexpected behavior
solves:
subclasses can be used interchangably with their base classes without altering the functionality or correctness of the program
prevents the use of inheritance for quick'n'dirty hacks
Solution: "Replacing" and introducing unexpected behavior must be prevented!
This can be accomplished by relying on properly typed ValueObjects instead of badly applied inheritance principles.
Interface segregation principle
no client should be forced to depend on methods it does not use
split large interfaces into smaller more specific ones so that clients only need to know about the functionlity/features they are interested in
solves:
prevents a class carrying unwanted dependencies and methods which it does not use
keeps code robust and easy to maintain
reduces the risk of bugs due to changes in unrelated methods affecting classes that should not logically be affected
more likely to adhere to single responsibility principle
Solution: Refactor the large interface step by step by introducing more streamlined interfaces.
The result is in contrast to have a single large interface.
After that, let services implement only the interface which is required by the client.
Dependency inversion principle
high-level modules (business logic/what is done) should not depend on low-level modules (technical details/how it is done)
both should depend on abstractions (e.g. by using interfaces or implementing interfaces)
abstractions should depend upon details
details (concrete implementations) should depend upon abstractions
solves:
addresses the problem of tightly coupled code which often occurs when high-level modules directly depend on low-level modules
tight coupling leads to:
difficulty in modifying:
changing the low level module affects the high level module
challenging tests:
high-level modules are harder to test in isolation because they directly depend on the technical details (the low-level module)
Solution: Shift the concrete dependency to an abstraction and use dependency injection whenever applicable.