On this wiki site I would like to discuss the following situation:
You develop an object-oriented application. For this purpose you use an object-oriented framework that makes in easier for you. The framework contains several parts. Some of them are mainly used via inheritance, others mainly via normal class usage.
Now you would like to refactor your application code because you discover some smells in it. You take the book by MartinFowler and other resources to find the right refactorings. But it is difficult for you to apply them because you are not allowed to change the framework. So a number of refactorings might be unusable or have to be changed to fit your needs.
See also:
My PhD thesis focuses on this situation. The goal is to analyse this situation to provide the application developer with special refactoring tools and descriptions that are optimized for the situation described above.
So the main point of interest is NOT to refactor the framework. The framework code is fixed and not changeable for the application developer in most cases. This is the reason why some refactorings for the application code are more complicated than without a framework.
My first impression is that I should focus on the interface between the framework and the application. Inheritance relationships might be a difficult part of it because the relation between the framework and the application classes are very close.
A simple idea for a tool support is: Enhance the refactoring features in IDEs so that they have knowledge about the difference between the application code and the framework code. Then the tool would be able to inform the user that the chosen refactoring is not possible because it would affect framework code.
A good example for that might be RenameMethod: The application developer has subclassed a framework class and implemented a template method from the framework. Then he decides to rename the method because of special reasons of the application project. Good refactoring tools will rename all other usages of this method. too. That will affect the framework code because the template method is defined inside the superclass of the framework and is used by the superclass (or other classes) inside the framework. Normally the tool would rename all affected points in the code that deal with the method to be renamed.
In our case the tool should warn the application developer that this refactoring could break the right relation between the framework and the application code. This happens because the framework is not changeable and the method is used by the framework via the template method pattern.
Perhaps, more generally, any refactoring tool should have knowledge of what code you're allowed to change and what code you're not allowed to change. Not everyone has XP-style joint code ownership. You may not be able to change code because someone else owns it, because it's on a different release schedule, or because someone else has it "checked out" at the current time. -- JeffGrigg
(Later comments on AbstractionFromInterface.)
maybe a little off-topic
To facilitate refactoring of an application built on top of a read-only framework it might pay to organize the application software into (at least) two sets, that which is truly application specific, and that which is essentially framework extension/customization (and may be useful in the development of similar applications). Then the activity of refactoring is one of surveying closely related application-specific fragments, distilling out the framework-like capability, and retrofitting the application-specific code to use the newly crystallized framework code.
This approach can be useful even when you have permission to change the original framework, as it preserves original uses of the framework, and separates your local concerns from the global concerns the original framework developer was addressing. --ScottJohnston
Yes, you are right from my point of view (even if the comment get round the problem instead of addressing it directly ;-). A good separation between framework-specific code and application-domain-specific code helps me to reduce the coupling between the framework and the application on the one hand. And on the other hand it reduces the possible effects of application-code-refactorings on the (maybe read-only) framework.
But that seems to me possible only for highly technical frameworks. Application frameworks and frameworks that provides an architecture for the domain-specific part of the application are hard to separate from the domain-specific part of the application code. But this idea is interesting. Do you think the described problem (refactoring framework-based applications) occurs less if the framework is small and mainly has a technical focus? --MartinLippert
I know there is a good deal of difference between frameworks for manipulating and visualizing spatial-temporal data, and frameworks for handling business processes. And you can't always assume conclusions from one domain apply to the other. But then again, as the applications increase in complexity and generality they start to show common traits driven by the fact they are tools for humans producing data and decisions. It would be interesting to compare architectures of a real-time stock-trading system to a full-blown non-linear editor for video production.
Do I think the described problem (refactoring framework-based applications) occurs less if the framework is small and mainly has a technical focus? By this, do you mean is there less problem with CodeSmells in technical applications built on concise technical frameworks (as opposed to business process frameworks)? I would guess that might be true in the academic world, where alternate architectures/perceptions can be quickly ruled out to simplify things. In the business world, academic or otherwise, you have to cope with sizeable complexity partially imposed by financial and government institutions, with no option of ignoring them for simplicity sake. But a real-world application of a technical framework would soon run into the same morass of incompatibilities and regulations, and lead to the same degree of CodeSmells. At least that is my conclusion when I compare my close-to-R&D use of a vector-graphic framework to my recent employment in a broadcast-video devices company.
All that said, I am quite curious as to your statement that it is hard to separate domain-specific framework code from domain-specific application code for non-technical applications. Can you give more detail of why you've found this to be the case? -- ScottJohnston
Another thought that's been bouncing around in my head is that what you (MartinLippert) seem to be talking about is frameworks that offer different implementations of similar concepts - such that you might substitute one for another. A really common example might be the collection classes of the C++ StandardTemplateLibrary (STL) or RogueWaveTools?. It should, in theory, be trivial to switch between different collection classes within a framework/library, as they were all designed to have compatible interfaces. But it might be nice to have a tool that, given your interest in a particular instance of a particular collection (IE: a variable), it could look around to see what methods are being used, and limit your selection of alternate collections to those that support the same interface. Maybe the tool could help you evaluate the tradeoffs: memory vs speed, and insert vs selection speed.
Maybe the ACE/TAO framework (http://www.cs.wustl.edu/~schmidt/ACE.html) would offer examples of this, as it has plenty of swappable components - both for cross-platform portability and also for differences in implementation strategies. -- JeffGrigg