When writing a small utility app, that does just one thing, should that one thing be encapsulated in a seperate class, or just let it be part of whatever class/module is used to start the application? I.e. Main would consist of 2 or three lines calling the constructor and then the DoIt methods, nothing else. Or should Main be the DoIt method, with whatever functions it needs added to the main class?

Asking because I want to get some alternative perspective, but couldn't find a similar question. If my google-fu is bad and there's a dup, please close.


You need to do more accurate calculation for an amount of the purposes. For end users, your utility has single purpose, right, but for it's code this isn't so.

Let's see, there's the part you denoted DoIt - it has that single purpose of doing utility function, fine, but besides it there's a part you called Main and it has own, separate purpose - it serves as program entry point.

You see, code serves at least two purposes, not one (second one isn't visible to end users but maintainers of your code will see it very well). And, if you happen to also have command line arguments passed to utility, there will also be a code with third purpose of parsing these, go figure.

All right, there is more than one purpose, and serving them in one class deviates from a single responsibility principle (SRP) - from this perspective you have full right to split it, you only need to decide whether deviation is justified or not.

Say, if your code to handle command line arguments is only 5-10 lines, benefits of keeping it nearby most likely outweight blind adherence to theoretical principles. Or maybe your DoIt code is so clean, elegant and compact that having even a small amount of unrelated parsing code there makes you feel "dirty"? if so, don't hold your pain, split it out and feel better - the very purpose of SRP is to justify moves like that.

Similar reasoning applies when you decide whether to keep the entry point in or split it out. If all your code is in single file, it's only reasonable to assume that anyone reading it will figure that entry point is also there. If you have more than that, well, it makes sense to give it a little more thought.

I for one feel quite frustrated when entering an unfamiliar codebase I have to waste time trying to figure whether to start reading code from MyVeryImportantClass or from MyAbsolutelyNecessaryClass. In cases like that, I would much appreciate if there was a simple, separate (however small) MainClass file I could start with without thinking.

  • 1
    Thanks. The classes that got me thinking about this are currently in seperate files, but they are easily small enough to be combined. I think in this case that provides the best solution. While the class is probably never going to be used for anything else, you're right about the responsibility of Main. – jmoreno Nov 2 '13 at 3:13

Your end goal is to produce, clean, reliable code that is easy to read. That means managing complexity. Classes help you do that by creating abstraction layers so that you can look at a simple public interface and not be concerned by all the nuts and bolts that make the class do it's thing.

However you also need to remember that "abstraction layers can solve just about any problem except for having too many abstraction layers" (not my quote but don't remember where I saw it).

So my advice would be to start small and follow some other good advice which is also not mine:

  1. Make it work
  2. Make it work right
  3. Make it work fast (this one probably doesn't apply here)

If a main function is simple enough, stick with it. If you notice it is starting to grow and morph, then take a chunk of functionality and make it a class (or 2, or 20)

  • 1
    Re: your quote – It's a modified version of a quote by David Wheeler, and is shortly discussed in the Wikipedia article on Indirection. – amon Nov 1 '13 at 9:06
  • @amon: ah! Thank you. Well they weren't talking strictly about abstraction but I say their quote, although it'll have to stay modified, still applies. – DXM Nov 1 '13 at 15:17
  • If it doesn't work right, it doesn't work. (Meaning having both 1 and 2 is redundant.) – Thomas Eding Nov 1 '13 at 16:01
  • @ThomasEding: without doing too much searching, this is the very first google hit: c2.com/cgi/wiki?MakeItWorkMakeItRightMakeItFast "To make it run, one is allowed to violate principles of good design. Making it right means to refactor it. -- DaveHoover" – DXM Nov 1 '13 at 18:04

Here's a rule of thumb when it comes to deciding between object-oriented and procedural programming:

Use object-oriented programming (OOP) when the overall complexity of a system exceeds the complexity of its individual algorithm.

If the control flow of your application is highly complex, switch to OOP. Else, stay with procedural programming.

  • 1
    I basically agree, but the key thing is how you measure complexity of algorithms (there is far more than one way) and how you define "highly complex" in that context. – JensG Nov 1 '13 at 15:50
  • 1
    There is, of coarse, no general answer for measuring complexity. Sure, there are software metrics like McCabe's cyclomatic complexity, but more important for the decision of switching to OOP is subjective estimation. However, this requires a lot of experience. – sfat Nov 1 '13 at 16:08

Both. I found myself repeatedly starting with a simple, procedural thing which ended up as a fully-fledged OOP solution consisting of several classes and interfaces. In my opinion, this is just how things are evolving in the real world and there's nothing bad about it. It happens due to enhanced requirements, due to better insight in the problem domain, or other reasons.

The most crucial point during this process is to develop an inner sense, some kind of mental detector, or maybe a certain rule (like "if it goes beyond 2000 lines, refactor it into classes") which rings the alarm bells right at the point, where the code starts becoming too complex for procedural but still is easy enough to refactor into classes.

Once you got to that point, the rest is easy.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.