yep, anywhere away from the current code.
On Tue, Mar 27, 2012 at 10:44 AM, Jacques Le Roux <jacques.le.r...@les7arts.com> wrote: > From: "Mansour Al Akeel" <mansour.alak...@gmail.com> > >> Jacopo, >> >> I didn't know about the deprecated methods, and I didn't want to open >> the subject of changing methods, because I don't what methods are used >> a lot in the applications code, and don't want to introduce a lot of >> change. However, in my opinion, I don't see a need for something like: >> >> public void clearCacheLine(GenericPK primaryKey); > > > It's used in GenericDelegator.removeByPrimaryKey() and > GenericDelegator.removeAll() > This usage is inside the delegator itself so it can be wrapped, but from applications it is used only. ./product/src/org/ofbiz/product/product/ProductEvents.java Additional components under "framework" needs it. Will need to plan before we start and create a branch. > >> I am not sure if an application programmer will be interested in >> something like this. If I have to design Delegator class, I will >> restrict the methods only to those that offer some sort of >> functionality to the application programmer, and hide everything else. >> However, to avoid breaking any existing application code, I suggested >> only a refactor. However you suggestion is useful, and would make >> things easier, and give a ofbiz entity engine a cleaner code base. >> >> Definitely, I am supporting this idea. If we are going to do a >> refactor, we might as well, remove deprecated methods, and replace >> methods in the application code, that uses those deprecated calls. >> >> So the starting point to tackle this task with minimal risk would be, >> decide and remove deprecated methods from Delegator interface, then >> clean the applications code and replace those calls. >> >> Is that ok ? Do you see a need for a fork ? > > > A branch would be safer > > Jacques > > >> >> >> >> On Tue, Mar 27, 2012 at 6:12 AM, Adrian Crum >> <adrian.c...@sandglass-software.com> wrote: >>> >>> I agree that the decorator pattern could improve the Delegator >>> implementation. >>> >>> Some time ago I had suggested using the decorator pattern to support DB >>> localization - which would eliminate the need for the clunky LocalizedMap >>> interface/implementations - but there wasn't much interest in it. >>> >>> -Adrian >>> >>> >>> On 3/26/2012 10:25 PM, Mansour Al Akeel wrote: >>>> >>>> >>>> Hello all, >>>> I am looking at the code for the GenericDelegator. We have 2913 line >>>> of code in one class !!! >>>> This class handles a lot of functions and I think it's the most >>>> critical to the application. These functions can >>>> be distributed among more classes, providing better maintainability >>>> and extensibility. I can see the best pattern to >>>> be used here are chain of responsibilities and decorator, where each >>>> class provide a defined set of functionality and implement the >>>> Delegator interface. >>>> >>>> For example, currently this class handles caching, configurations, >>>> model Reading, encryption, logging, and the main function of accessing >>>> data. >>>> It's true that the interface it implements is huge (1217 line of code) >>>> but mostly comments and documentation. CoR design pattern will allow >>>> easier >>>> unit testing, and better maintainability and allow to extend. So let's >>>> say: >>>> >>>> GenericDelegator implements Delegator (Interfaces with the external >>>> world >>>> ) >>>> ===> passes calls to SQLQueriesDelegator (build the sql through >>>> implementing findXXX()) >>>> =====> passes calls to LoggingDelegator >>>> =====> passes calls to ModuleReaderDelegator >>>> ======> MultiTenantDelegator >>>> ========> CachingDelegator >>>> ==========> EncryptionDelegator >>>> ============> etc >>>> >>>> Each delegator does some work and calls the next one in chain until >>>> the final functionality is achieved. Of course customization will be >>>> easier. >>>> For example, if I want to swap the current caching implementation with >>>> something like memcahe or ecache, I have to change in many places in >>>> the single 2913 line-of-code class !! With CoR all I do is swap the >>>> current CachingDelegator class with my own. Let's say I want to access >>>> the file system >>>> or jcr nodes in the same unified way I access the db. In this case all >>>> I need to do is add some thing like "RequestRoutingDelegator", and >>>> JCRDelegator. >>>> The RequestRouting decides how to access the entity in hand and based >>>> on that uses either the SQLDelegator or JCRDelegator. >>>> Those who did xml processing with SAX2 filters (CoR) or worked with >>>> java IO streams (Decorator Pattern) will appreciate the concept of >>>> separating functionality. An example in JavaIO, if one needs to ecrypt >>>> a stream, unzip the input, or zip the output .... etc. All these is >>>> done though decorator pattern. >>>> >>>> The whole chain can be created and constructed in the factory method >>>> (or using a container config in the future), so existing applications >>>> should not see any changes, as all of these delegators will be hidden >>>> by package visibility (except for the first one in the chain). >>>> In the factory method (hopefully in the future called through a >>>> service locator), we can do something like: >>>> >>>> Delegator encryptionDelegator = new EncryptionDelegator(); >>>> Delegator cachingDel = new CachingDelegator( encryptiongDelegaort); >>>> ..... >>>> ..... // may be do some configuration as we dont want every delegator >>>> to configure itself by reading a file or looking up a >>>> // of a property, in case we used a container in the future. >>>> .... >>>> Delegator realOne = new GenericDelegator(); >>>> >>>> static methods can be moved where needed and ensure there's not >>>> duplication of functionality. At some point we may consider >>>> making them instance methods. >>>> >>>> To avoid DRY, we can create a class (implement Delegator) with default >>>> functionality of calling the child (next) delegator. >>>> Then just extend it and override whatever we need. This way we keep >>>> the code minimal, and clean. >>>> >>>> At the end, assuming no advantage gained, who wants to maintain 2913 >>>> line of code with some lines more than 100 character wide ??!! >>>> >>>> I am not sure about the amount of work it takes to finalize it, but I >>>> can see some difficulties. For example, assuming two different methods >>>> belongs to two different layers, need one of the static methods in the >>>> GenericDelegator. This will lead to duplicate code, we are going to >>>> call static methods in other classes, and creating a mess again. >>>> Another issue is when an object needs to be accessed in different >>>> layers. This means we need to keep a reference for that object in >>>> multiple places. What if it changed in one of the layers ? For >>>> example, ModelReader is accessed in cloneDelegator and in >>>> decryptField. Both of these methods belongs to different Delegators. >>>> cloneDelegator goes into GenericDelegator, and decryptField goes into >>>> EncryptionDelegator. What if the model reference changed in one of >>>> them ?? Caution needed ! >>>> >>>> Another problem is when the order of calls in GeneralDelegator is not >>>> consistent. For example, in one method we accessed the cache then we >>>> did the logging. In another method we did the opposite, we logged, >>>> then we accessed the cache. When done in layers, it will be harder to >>>> do this. >>>> >>>> Another alternative is something close to the composite pattern, where >>>> we have Helper classes with a subset of Delegator implementation. The >>>> GenericDelegator class, instantiates them and keeps a reference to >>>> each of them. Then calls the appropriate method. This really simple, >>>> but less >>>> sexy, as extending the functionality still requires looking between >>>> the lines. It's just breaking the HUGE class into smaller classes. >>>> >>>> Not sure if I missed something. Other patterns could fit better. If >>>> someone captured something, please let us know. Ofbiz team can decide >>>> what path to follow. >>>> >>>> Since this component is critical to the application, some may prefer a >>>> more senior resource on the team and more skilled >>>> with the internals of ofbiz, to handle this task. However, I don't >>>> have a problem giving it a try. This task may sound small, but I don't >>>> know what is a head of us. Someone with deeper knowledge about the >>>> entity engine can comment. >>>> Alternatively, one of the commiters, can adopt this task, and do the >>>> cleaning as needed. For example, every while and then revisit this >>>> huge class, and >>>> break separate the functionality into the corresponding classes. >>>> >>>> I didn't want to open this subject now, as I am aware of the cleaning >>>> being performed by the team. However, if we can not do it now, and we >>>> agreed about the path, it can be added to JIRA for future reference. >>>> >>>> Please discuss and share knowledge. >> >> >