proceso o pasos para refactorizar la clase de dios en una aplicación heredada de c ++?

This application was written without any knowledge of design principles (SOLID) by the previous developer. The most critical issue of the app is that it has god class with lots and lots of switch statements. This ill-advised structure makes it hard to maintain the app. Of course, there is no unit testing at all.

First on switch statements, I found there are two main potential classes that varies over the application. So I will try to first construct those two classes and move the corresponding code to the classes from the god class. Is this a right way? What is a good process to attack this issue?

BYW, I have the book "Working Effectively with Legacy Code". So you can suggest which part of the book I have to read for this too :-)

preguntado el 10 de marzo de 12 a las 14:03

Simple, you move parts of God's code to Heaven and Earth, you derive a Jesus from it. -

@nightcracker Isn't that another god class that every class should depend on? -

Definition of god class? -

@Paul, no, the only dependence is that classes should support the private pray(const Jesus) método. -

2 Respuestas

What is a good process to attack this issue?

"don't fix it if it ain't broke".

The good process is to leave the issue alone until you HAVE to deal with it or unless you were ordered to refactor the code. It doesn't sound like this is the case in your scenario.

The rationale behind this kind of reasoning is quite simple: a sudden fit of perfectionism ("let's make it better, cleaner and shinier") might cost you next 6 months of your life with no reward of any kind (satisfaction doesn't count, because things like this quickly stop being satisfying enough). In the process you'll introduce multiple new bugs and probably break the whole system at least once, so there will be periods of time when you have large code base that doesn't work. The whole thing will increase the workload and might stress you badly which can result in bad health problems. Unless you were given the task of refactoring the code and a decent reward is guaranteed, supress the urge to improve the codebase "for the greater good" - thinking this way can badly backfire.

Put the whole thing under version control that allows quick branching/merging (git). Because you haven't mentioned version control, then by murphy's law I'll have to assume you aren't using it.

Concentrate on immediate bugs you have to fix. In areas you work with, improve code to make it fit your favorite style, but keep changes minimal, and do not touch anything that is not related to immediate problem. When you have bastante of free time if you feel like it, start implementing tests where it is necessary (contrary to popular belief, unit testing is not a silver bullet). Once you have some way to test that application still works, create separate development branch, and start modifying the code very slowly and only when you have time for that. Avoid merging changes back into master branch (that contains unmodified legacy code) as long as possible - until you're sure that everything works properly.

Keep in mind that your goal is not to make perfect code. Your goal is to provide fast and efficient solution for current problem using minimum amount of resources (time/effort), while getting maximum reward for your work. In my experience, deviating from this principle is extremely unhealthy.

Maintaining and improving existing los ancianos code base is roughly equivalent to rebuilding bottom floor of 3 foot tall card house. I.e. it is challenging, tedious, risky, but does not provide necessary level of emotional satisfaction. So unless there's a big reward of some sort, it makes sense to avoid doing this as long as possible. Code doesn't rot, so if existing works properly, there is no reason to modify it just because you don't like the look of current source code.

However, it would be a good idea to read the code and attempt to understand thinking of previous author and get better understanding of program structure. This might pay off in the long run.

respondido 10 mar '12, 16:03

Thanks for your answer. You sound like one of my previous boss, I mean in a good way. I totally agree with you on don't fix it if it aint't broke and I am no perfectionist at all. But issue here is that it's getting harder and harder to add/test new code in it. So potential an-hour coding work becomes a-couple-of-days work without talking about test. In this case, do you think no change's still good? - Tae Sung Shin

@Paul: In this case it would still be a better idea to keep changes minimal and limited to areas you directly work with. If you feel the need to give large scale refactoring, you might want to discuss it with your superior without sugar-coating the risks of the procedure. The problem with large scale modification is that there will be bugs that will slip through unit test suite to be discovered few months later. Also, if code base is big, trying to refactor it alone (you haven't mentioned coworkers or other developers) becomes even more risky, because you won't be able to remember all details. - SigTerm

I am with you. But in this case, code base is not big and maintaining/expanding the app is only under my control. So I don't have to worry about coworker or boss that much. As you said, I can revert my change anytime if it takes too long or break anything. So at this point, according to your suggestion, good idea would be to implement unit testing which will be hard in C++ environment especially with that god class, right? - Tae Sung Shin

@Paul: "code base is not big" is relative. The amount you can remember more or less reliably is around 200kbytes, I think - but only if you wrote it completely yourself. Anything else requires documentation. "according to your suggestion" My suggestion is to take things slow and avoid unnecessary changes. If you're modifying something, try to make sure it fixes existing problem. If you want to "play around" with code and look for ways to improve the code, then do it in separate git branch and only if you there are no other issues to deal with and you have completely free time. - SigTerm

@Paul: If I were you I'd attempt to document it first and maybe change indentation, without actually doing significant changes that can result in new bugs. - SigTerm

Switches are an obvious refactor target. But there could be others. You give uslittle to go on.

I often spend a great deal of time massaging the code, rewriting it such that I can change the type used by commenting/uncommenting a few lines.

For a swich on an enum, it can be useful to define a struct that contains one member: the enum value, and has an implicit conversion to the enum value. Using typedefs or macro, you can make sure that your new type is passed around in stead of the enum. If that has undesired side effecs, revert, fix the implementation, and try to use yournew type.

Next, move the switch code to a member function of the new type, one switch at a time.

If unit tests are required in the process is up to you.

respondido 10 mar '12, 15:03

I understand switch is necessary sometimes and can be dictionary. But I meant the case where I need class hierarchy instead of it so that I can have a switch statement in class initialization instead of everywhere. Yeah, I agree that my question is poorly written but I can't really describe all the structure of the code, especially when it's written in a disorganized way. - Tae Sung Shin

My suggestion will allow you to make a hierarchy. But I postpone this till last. I think that is safer. - user180326

Understand what you are saying. A list would've been clearer but no complaint. Thanks! - Tae Sung Shin

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.