Can someone please explain the difference between REP and CRP to me? I understand that the CCP (Common-Closure-Principle) states that modules that need to be changed together frequently should belong to the same package.
But what is the difference between REP and CRP? Both principles seem to say that what is reused together belongs in the same package. How do these principles stand in discord (tension triangle)? I hope someone can explain this to me.
But what is the difference between REP and CRP? Both principles seem to say that what is reused together belongs in the same package.
The REP states that components that are reused together should be released together.
E.g. this means that if you provide a framework for your clients and the framework is made up of various components, then that components must be compatible with each other. It would be hard for clients if they need to figure out which version of framework component A is compatible with component B and C. So Uncle Bob says:
The granule of reuse is the granule of release
Popular Java frameworks which apply that rule are the Spring Framework, Hibernate, JUnit, and a lot more. Take a look at the Maven BOM of Spring and you will see that each module is managed with the same version.
The CRP says that:
Don't force users of a component to depend on things they don't need.
So while the REP is about compatibility between components, the CRP focus on a component itself.
As an application developer it might often seem to be a good idea to use a library or framework for a specific problem. So you add that dependency to your project and you just use the features it provides.
As a framework or library developer you must resist the reflex to just add another dependency just for some features. Because if you do that, your clients will quickly transitively depend on a dozens of other dependencies. And since different libraries or frameworks need different dependencies in other versions your clients will quickly end up in version conflicts. This makes your clients life harder and therefore makes it more unlikely that they use your library or framework. So as a framework or library developer you should often just write the code you need instead of adding a dependency only to use a small string abbreviation method. Take a look at the dependencies of popular frameworks like spring-core, you will never see a lot of dependencies.
So whenever you plan to write a component that is made for reuse you should honor the CRP or it will not be reused.
Java library developers who want to use other libraries and prevent clients from horrific dependency versions often use a technique that is called repackage. Repackaging is a mechanism that rewrites byte code to place the dependent classes in another Java package so that they can not collide with the normal classes of that dependency that a library client puts on the classpath.
But repackaging comes at a cost. Imaging multiple libraries that use the same dependency, but they repackage it. This whould require the JVM to load the same class multiple times. Usually memory is not an issue nowadays, but you should be aware of this.
How do these principles stand in discord (tension triangle)? I hope someone can explain this to me.
When you apply the CRP you will write small components with maybe zero dependencies that can be independently released. Since these components have less, maybe zero, dependencies there is no need to group them for release like the REP proposes. On the other hand if you group them for release, you do that because there are dependencies between them and you don't want your clients to solve a version puzzle. I guess this is why the two principles stand in discord.