This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
It's a legacy system. It doesn't obey the OO design principles properly. The biggest problem is it programs to the implementation, not to the interface. The code snippet below spreads anywhere in the system.
The problems raise when I add a new type, for example, a Bird. So I need to find where need to be changed in thousands of files. I take a lot of time to do this, but it's hard for me to list all the files need to be changed. I'm afraid adding a Bird will take new bugs to the system. My questions are:
1 Adding a new type is an urgent requirement, should I add it to the system now(but new bugs may be taken in) or refactoring the system now(but it seems a huge work to do, and the refactor process may take in new bugs too)?
2 Do you have some ideas to do the refactoring? I know an interface Animal may be good. But that's just a basic idea. Would you suggest me some step by step way to do the refactoring job? Also I'm really afraid huge changes will be made to the system.
You have good instincts. This "instanceof" checking points up behavior that probably should have been in the animals to start with. You can make the new Animal interface and implement it with the next new type:
I worked with a system that took Data Transfer Objects as parameters. They were generated from models and had no behavior or business code in them. So we did something more like:
Do either of those look like they'd work for you?
A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Originally posted by Louis Wang: should I add it to the system now(but new bugs may be taken in) or refactoring the system now(but it seems a huge work to do, and the refactor process may take in new bugs too)?
It's tough to get buy-in to do the refactor when something urgent is on the horizon. I think they key is to not leave the system worse off than you found it. In other words, one step closer to how you would want it in an ideal world. Part of the reason the system currently looks like this is likely that it was written only for Dog and then someone "urgently" needed Cat.
I like Stan's approach because it lets you refactor slowly over time. It's hard to get someone to agree to let you spend 2 weeks refactor. It's much easier to get someone to agree to let you spend 2 hours a week. So you could have Dog implement Animal and then replace all references one at a time.
.... Part of the reason the system currently looks like this is likely that it was written only for Dog and then someone "urgently" needed Cat. ...
You are absolutely right.
When I think of refactoring, abstract, program to the interface and design patterns all come into my mind. But I find it's hard for me to apply these principles and patterns into the real system. When I just learned 2 or 3 patterns, I can easily apply them into an Animal-Dog-Cat expample. But When I learn more, and the system change to the real word, I can't find a steps for me to follow. This situation confuses me a lot. I have worked for less than 3 years. I learned the OO principles and design patterns from books or articles on the internet. So I'm not very confident to do the refactoring right now without a mentor. I know exactly what the problem is in the legacy system. But I don't know if the refacoring(if failed) will take troubles to others.
I find another problem in the legacy system. It uses collections a lot. For example a HashMap, it uses the type name as the key:
And these code spreads over the packages, when I try to add a new type, I need to find out these files to change. Now what I do is just search "cat" in the files. I can't find some design patterns to do this job. Do you have some suggestions on this problem?
Joined: Jan 29, 2003
And these code spreads over the packages ...
Another hint that back in the day when this all started somebody put the responsibility in the wrong place. Why should many clients know about the structure of the map, or even know there's a map involved? It will be tough to retrofit, but see if you can get the code that has to know about the map in one new class or method and have all clients use it.
The warning signal somebody missed was duplicating code. If you find yourself copying even a couple lines every time you use some API, maybe that tiny bit of logic belongs inside the API. For example, here are a few lines I see all over the system I'm on now:
The first time somebody copied that block they should have stopped and moved that logic to a new API so clients write:
That won't help you refactor a ton of code right now, but thinking that way might help you avoid it again in the future.
Joined: Aug 19, 2005
Originally posted by Louis Wang: I learned the OO principles and design patterns from books or articles on the internet. So I'm not very confident to do the refactoring right now without a mentor.
In the absence of a mentor you may want to consult the following sources:
Your lack of confidence is partially due to the fact that the current system is not "under test" - therefore you really have not idea what is going to break when you make a change in the code. Working Effectively with Legacy Code deals with the problems that are encountered when you need to bring a system "under test" so that you can proceed effectively with the necessary refactorings.