Does anyone know the best way to refactor a God-object?
Its not as simple as breaking it into a number of smaller classes, because there is a high method coupling. If I pull out one method, i usually end up pulling every other method out.
It's like Jenga. You will need patience and a steady hand, otherwise you have to recreate everything from scratch. Which is not bad, per se - sometimes one needs to throw away code.
Other advice:
- Think before pulling out methods: on what data does this method operate? What responsibility does it have?
- Try to maintain the interface of the god class at first and delegate calls to the new extracted classes. In the end the god class should be a pure facade without own logic. Then you can keep it for convenience or throw it away and start to use the new classes only
- Unit Tests help: write tests for each method before extracting it to assure you don't break functionality
I assume "God Object" means a huge class (measured in lines of code).
The basic idea is to extract parts of its functions into other classes.
In order to find those you can look for
fields/parameters that often get used together. They might move together into a new class
methods (or parts of methods) that use only a small subset of the fields in the class, the might move into a class containing just those field.
primitive types (int, String, boolean). They often are really value objects before their coming out. Once they are value object, they often attract methods.
look at the usage of the god object. Are there different methods used by different clients? Those might go in separate interfaces. Those intefaces might in turn have separate implementations.
For actually doing these changes you should have some infrastructure and tools at your command:
Tests: Have a (possibly generated) exhaustive set of tests ready that you can run often. Be extremely careful with changes you do without tests. I do those, but limit them to things like extract method, which I can do completely with a single IDE action.
Version Control: You want to have a version control that allows you to commit every 2 minutes, without really slowing you down. SVN doesn't really work. Git does.
Mikado Method: The idea of the Mikado Method is to try a change. If it works great. If not take note what is breaking, add them as dependency to the change you started with. Rollback you changes. In the resulting graph, repeat the process with a node that has no dependencies yet. http://mikadomethod.wordpress.com/book/
There are really two topics here:
Given a God class, how its members be rationally partitioned into subsets? The fundamental idea is to group elements by conceptual coherency (often indicated by frequent co-usage in client modules) and by forced dependencies. Obviously the details of this are specific to the system being refactored. The outcome is a desired partition (set of groups) of God class elements.
Given a desired partition, actually making the change. This is difficult if the code base has any scale. Doing this manually, you are almost forced to retain the God class while you modify its accessors to instead call new classes formed from the partitions. And of course you need to test, test, test because it is easy to make a mistake when manually making these changes. When all accesses to the God class are gone, you can finally remove it. This sounds great in theory but it takes a long time practice if you are facing thousands of compilation units, and you have to get the team members to stop adding accesses to the God interface while you do this. One can, however, apply automated refactoring tools to implement this; with such a tool you specify the partition to the tool and it then modifies the code base in a reliable way. Our DMS can implement this Refactoring C++ God Classes and has been used to make such changes across systems with 3,000 compilation units.
来源:https://stackoverflow.com/questions/14870377/how-do-you-refactor-a-god-class