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
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
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.PvModuleLayoutsinterface which provides access to a somewhat complicated algorithm.Currently, its implementation is nicely contained in
com.company.app.pvmodulelayoutspackage. So far so good.Inside the
com.company.app.pvmodulelayoutspackage we have:DefaultPvModuleLayoutsclass - the implementation of the interface which holds the high-level logic of the layout algorithmLayoutSpecificationinterface - an abstraction of algorithm's input parameterslayoutspecificationsubpackage - providing two alternative implementations ofLayoutSpecificationinterfaceThis structure feels right intuitively, and it seems to fulfill the 3 rules with only one exception - object construction.
The challenge
In
DefaultPvModuleLayoutsthere 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:
layoutspecificationsubpackage by introducing e.g.SlopeDependentLayoutSpecification implements LayoutSpecification(that would delegate to one or the other existing implementation) solves nothing, as thenDefaultPvModuleLayoutswould still require a dependency onSlopeDependentLayoutSpecificationfrom a subpackageRoofFaceimplementation also does not work, as then the 1st rule is still broken (asRoofFaceis in the ancestor package)com.company.app.objectconstructioncom.company.app.objectconstruction.SlopeDependentLayoutSpecificationdepends on the interface and both implementations, but it does not violate the 1st rule as it's in a sibling branch of the package treeDefaultPvModuleLayoutsdepends onSlopeDependentLayoutSpecificationwhich also does not violate the 1st rule (once again - sibling branch of the package tree)com.company.app.pvmodulelayoutspackage (and its subpackages), is now leaking into the new sibling package.com.company.app.objectconstructionpackage 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.pvmodulelayoutscreate an interfaceLayoutSpecificationsIndexedBySlopeAngle(for lack of better name) with one methodLayoutSpecification find(double slopeAngle). This has no dependency on the subpackage.com.company.app.pvmodulelayouts.layoutspecificationdefine a Spring component that implements theLayoutSpecificationsIndexedBySlopeAngleinterface and returns an instance of one or the other implementation depending on givenslopeAngle.com.company.app.pvmodulelayouts.DefaultPvModuleLayoutsinject an instance ofLayoutSpecificationsIndexedBySlopeAngleand 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