Replies: 1 comment
-
Here's the summary of the news so far:
I think an important insight is that specific object instantiation (plugging everything together) is not possible with having just one package subtree - it has to be done outside of it (as discussed here). There's also an example how to implement an ArchUnit test that would enforce this packaging rule (see TNG/ArchUnit#921). |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Context
In "Happy Packaging!" blog post the following packaging rules are proposed:
Example code
See case-1 module.
The main abstraction there is
com.company.app.PvModuleLayouts
interface which provides access to a somewhat complicated algorithm.Currently, its implementation is nicely contained in
com.company.app.pvmodulelayouts
package. So far so good.Inside the
com.company.app.pvmodulelayouts
package we have:DefaultPvModuleLayouts
class - the implementation of the interface which holds the high-level logic of the layout algorithmLayoutSpecification
interface - an abstraction of algorithm's input parameterslayoutspecification
subpackage - providing two alternative implementations ofLayoutSpecification
interfaceThis structure feels right intuitively, and it seems to fulfill the 3 rules with only one exception - object construction.
The challenge
In
DefaultPvModuleLayouts
there is the following code which seems to break the 1st rule:I don't yet see an acceptable way to reorganize this code to not break the first two rules. The options I considered:
layoutspecification
subpackage by introducing e.g.SlopeDependentLayoutSpecification implements LayoutSpecification
(that would delegate to one or the other existing implementation) solves nothing, as thenDefaultPvModuleLayouts
would still require a dependency onSlopeDependentLayoutSpecification
from a subpackageRoofFace
implementation also does not work, as then the 1st rule is still broken (asRoofFace
is in the ancestor package)com.company.app.objectconstruction
com.company.app.objectconstruction.SlopeDependentLayoutSpecification
depends on the interface and both implementations, but it does not violate the 1st rule as it's in a sibling branch of the package treeDefaultPvModuleLayouts
depends onSlopeDependentLayoutSpecification
which also does not violate the 1st rule (once again - sibling branch of the package tree)com.company.app.pvmodulelayouts
package (and its subpackages), is now leaking into the new sibling package.com.company.app.objectconstruction
package introduces new concepts not defined in a higher-level package)There is also a way to solve this using Spring Framework and dependency injection:
com.company.app.pvmodulelayouts
create an interfaceLayoutSpecificationsIndexedBySlopeAngle
(for lack of better name) with one methodLayoutSpecification find(double slopeAngle)
. This has no dependency on the subpackage.com.company.app.pvmodulelayouts.layoutspecification
define a Spring component that implements theLayoutSpecificationsIndexedBySlopeAngle
interface and returns an instance of one or the other implementation depending on givenslopeAngle
.com.company.app.pvmodulelayouts.DefaultPvModuleLayouts
inject an instance ofLayoutSpecificationsIndexedBySlopeAngle
and then the code becomesLayoutSpecification layoutSpecification = layoutSpecificationsIndexedBySlopeAngle.find(roofFace.slopeAngleInDegrees());
and the 1st rule is no longer broken.However, relying on Spring Framework feels like a crutch.
Do you see any additional options?
If not, would it be reasonable to add an exception to the 1st rule?
Beta Was this translation helpful? Give feedback.
All reactions