8

When I start writing code from scratch, I have a bad habit of quickly writing everything in one function, the whole time thinking "I'll make it more modular later". Then when later comes along, I have a working product and any attempts to fix it would mean creating functions and having to figure out what I need to pass.

It gets worst because it becomes extremely difficult to redesign classes when your project is almost done. For example, I usually do some planning before I start writing code, then when my project is done, I realized I could have made the classes more modular and/or I could have used inheritance. Basically, I don't think I do enough planning and I don't get more than one-level of abstraction.

So in the end, I'm stuck with a program with a large main function, one class and a few helper functions. Needless to say, it is not very reusable.

Has anybody had the same problem and have any tips to overcome this? One thing I had in mind was to write the main function with pseduocode (without much detail but enough to see what objects and functions they need). Essentially a top-down approach.

Is this a good idea? Any other suggestions?

  • 1
    I asked a similar qustion recently concerning project planning, but our problems are slightly different. Maybe some answers there could be of use to you. http://stackoverflow.com/questions/1100819/how-do-you-design-object-oriented-projects – Victor Jul 20 '09 at 22:44
  • I reward myself with chocolate. – Maxpm Nov 30 '10 at 07:35

8 Answers8

5

"First we make our habits, then they make us."

This seems to apply for both good and bad habits. Sounds like a bad one has taken hold of you.

Practice being more modular up front until it's "just the way I do things."

duffymo
  • 305,152
  • 44
  • 369
  • 561
3

Yes, the solution is easy, although it takes time to get used to it. Never claim there will be a "later", where you sit down and just do refactoring. Instead, continue adding functionality to your code (or tests) and during this phase perform small, incremental refactorings. The "later" will basically be "always", but hidden in the phase where you are actually doing something new every time.

Stefano Borini
  • 138,652
  • 96
  • 297
  • 431
1

I find the TDD Red-Green-Refactor discipline works wonders.

Avdi
  • 18,340
  • 6
  • 53
  • 62
1

My rule of thumb is that anything longer than 20 LoC should be clean. IME every project stands on a few "just-a-proof-of-concept"s that were never intended to end up in production code. Since this seems inevitable though, even 20 lines of proof-of-concept code should be clear, because they might end up being one of the foundations of a big project.

My approach is top-down. I write

while( obj = get_next_obj(data) ) {
  wibble(obj);
  fumble(obj);
  process( filter(obj) );
}

and only start to write all these functions later. (Usually they are inline and go into the unnamed namespace. Sometimes they turn out to be one-liners and then I might eliminate them later.)

This way I also avoid to have to comment the algorithms: The function names are explanation enough.

sbi
  • 219,715
  • 46
  • 258
  • 445
0

You pretty much identified the issue. Not having enough planning. Spend some time analyzing the solution you're going to develop, break it down into pieces of functionality, identify how it would be best to implement them and try to separate the layers of the application (UI, business logic, data access layer, etc).

Think in terms of OOP and refactor as early as it makes sense. It's a lot cheaper than doing it after everything is built.

Mircea Grelus
  • 2,905
  • 1
  • 20
  • 14
0

Write the main function minimally, with almost nothing in it. In most gui programs, sdl games programs, open gl, or anything with any kind of user interface at all, the main function should be nothing more than an event eating loop. It has to be, or there will always be long stretches of time where the computer seems unresponsive, and the operating system thinks considers maybe shutting it down because it's not responding to messages.

Once you get your main loop, quickly lock that down, only to be modified for bug fixes, not new functionality. This may just end up displacing the problem to another function, but having a monilithic function is rather difficult to do in an event based application anyway. You'll always need a million little event handlers.

Maybe you have a monolithic class. I've done that. Mainly the way to deal with it is to try and keep a mental or physical map of dependencies, and note where there's ... let's say, perforations, fissures where a group of functions doesn't explicitly depend on any shared state or variables with other functions in the class. There you can spin that cluster of functions off into a new class. If it's really a huge class, and really tangled up, I'd call that a code smell. Think about redesigning such a thing to be less huge and interdependant.

Another thing you can do is as you're coding, note that when a function grows to a size where it no longer fits on a single screen, it's probably too big, and at that point start thinking about how to break it down into multiple smaller functions.

Breton
  • 15,401
  • 3
  • 59
  • 76
0

Refactoring is a lot less scary if you have good tools to do it. I see you tagged your question as "C++" but the same goes for any language. Get an IDE where extracting and renaming methods, extracting variables, etc. is easy to do, and then learn how to use that IDE effectively. Then the "small, incremental refactorings" that Stefano Borini mentions will be less daunting.

Tyler
  • 21,762
  • 11
  • 61
  • 90
0

Your approach isn't necessarily bad -- earlier more modular design might end up as over-engineering.

You do need to refactor -- this is a fact of life. The question is when? Too late, and the refactoring is too big a task and too risk-prone. Too early, and it might be over-engineering. And, as time goes on, you will need to refactor again .. and again. This is just part of the natural life-cycle of software.

The trick is to refactor soon, but not too soon. And frequently, but not too frequently. How soon and how frequently? That's why it's a art and not a science :)

Larry Watanabe
  • 10,126
  • 9
  • 43
  • 46