-
Notifications
You must be signed in to change notification settings - Fork 531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implemented: Introduced base/util module (OFBIZ-12308) #837
base: trunk
Are you sure you want to change the base?
Conversation
* Movend lang package to util gradle project * Moved some classes * First road block: Debug + UtilValidation, UtilProperties
Quality Gate passedIssues Measures |
Hi Eugen, |
Hi @OmarAbdullwahhab , Thanks for taking an interest.
One of the blockers for moving things forward are the circular dependencies between classes. |
Thank you @ieugen |
Hi @OmarAbdullwahhab , Thanks for the suggestions. There is a pattern where some classes (UtilProperties + UtilCache is one example) initialize state as static fields.
These initialization bind the two classes in a circular dependency : UtilProperties depends on UtilCache that depends on Debug that depends on UtilProperties. In some cases we can solve this and avoid code duplication if we pull out the initialization and move it into Main class for example. This is a solution that should be less invasive. The pattern here is the one described by Dependency Injection / Inversion of Control. |
Yes I searched and found the following classes uses a ( Higher Level ) modules,
So my opinion is now lets do
These are my ideas |
One solution to break the dependency in static initializations like :
is to move initialization in the app entry point: https://github.com/apache/ofbiz-framework/blob/trunk/framework/start/src/main/java/org/apache/ofbiz/base/start/Start.java with code like this (provided we use an interface):
A similar initialization pattern can be used for Debug with UtilProperties. cc @mbrohl , @JacquesLeRoux : is the above solution ok for you? |
Hi @ieugen , I'm generally on-board with the IoC approach, but it is safer when dealing with instantiated objects rather than static fields in classes. If we had an IoC framework, such as Spring, I think this would be an easy pattern to implement. Alas, we are don't have such a framework, and we shouldn't let 'perfect be the enemy of good', so should carefully implement our own IoC patterns per your suggestion. Personally, I'm happy for classes at the same level or in the same module to reference each other, as long as those classes do not require any configuration. In the particular case of UtilCache/UtilProperties/Debug, it seems to me that the configuration is actually in the static initialiser of Debug where we find a reference to UtilProperties. My preference would be to break the link in Debug by removing reference to UtilProperties. Instead there should be a static method in Debug to apply the configuration that is currently being read from debug.properties. Some other class (such as Start) should be responsible for reading debug.properties and determining the debug configuration. Debug currently has two jobs: reading its configuration from a properties file; carry out logging. The above proposed changes would reduce Debug's responsibility and break the dependency cycle between UtilCache, UtilProperties and Debug. Summary: I'm broadly supportive of the pattern, but IoC with static initialisers and methods can be risky. Focussing on parts of the dependency cycle where we can reduce the responsibilities a class has might yield a similar result. If you decide to go with your original proposal of please consider adding a null check in the places where URL_CACHE is used and throw a suitable exception to explain the cause, rather than letting a NPE bubble up the stack. |
hi @danwatford , Thanks for taking the time.
I think this is the sensible way to move forward.
The issue is with circular dependencies. It often leads to situations where it is very hard to refactor - like our case now.
Yes, this one should be easy to fix via the IoC pattern.
Totally agree.
Agree. We are where we are and we can do what we can do.
Sounds reasonable. |
I have a quick note on the IoC container idea. I also used to believe we need one in Ofbiz(for example Spring) in order to help with testability, but recently I discovered an article from James Shore where he explains the testing approach he takes. So now I don't think we really need an IoC container, neither do we need to write one ourselves. We can just use constructor based injection. This would work for a normal non-static scenario, not sure about the static case you have here. Also, in order to not instantiate the whole dependency tree in unit tests, see the Parameterless Instantiation section in the article. Here is the article in question: https://www.jamesshore.com/v2/projects/nullables/testing-without-mocks |
Regarding the cyclic dependency . |
Explanation:
The goal is to have a set of common classes in a library (gradle project) that we can use in the other components.
To minimize friction, classes are moved as is.
First road block: org.apache.ofbiz.base.util.Debug depends on UtilValidation and UtilProperties that bring a LOT of stuff in and start the dependency cycle.
I fixed this in my previous PR by splitting some methods into a Util*Runtime class.