In an OOP world, what's the best way to handle a lot of sequential code?
April 16, 2008 10:19 AM   Subscribe

Design-pattern (programming) question.

I'm working on a huge app (many thousand lines of code), and one of the most complex parts of it is the initialization logic. There's a ton of code that needs to run sequentially and only once.

Currently, I'm handling all of this with singletons, but I wonder if there's a better way.

Here's the basic framework now (in pseudocode).

MainInit.getInstance().init();

/* inside MainInit's init() method... */

DataManager.getInstance().init();
CommandManager.getInstance().init();
GraphicsManager.getInstance().init();
... etc ... //maybe 40 more calls like this

This seems pretty straightforward and easy to maintain. I don't have any real problems with it. But it's sort of off-the-top-of-my-head. I've never worked on an app that needs so much initializing before.

Since it's not really about objects -- it's just about tons of code running in sequential order -- I'm not sure of the best, tried and true method of breaking it up into manageable chunks. And I can't find much about it in my Design Pattern books.

I'm cool with non design-pattern solutions, too. I know patterns aren't for everything. I just need a really good way of organizing this sort of code.
posted by grumblebee to Computers & Internet (41 answers total) 2 users marked this as a favorite
 
Typically if you want to break down a lot of code to run in sequential order you use functions, not objects. Do these managers actually serve any purpose other than their init methods?
posted by grouse at 10:28 AM on April 16, 2008


Does the order of the inits matter, like does it matter if DataManager::init runs after CommandManager::init? If it doesn't matter *when* it gets run (only that it does gets run), just have the init() call for each singleton inside each singleton's creation block.

Also, what grouse said. Hopefully these objects need to be singletons and serve some other purpose than just holding init code.
posted by PantsOfSCIENCE at 10:29 AM on April 16, 2008


Assuming these singletons all have methods other than init() and will be used later, I wouldn't have a problem with this. If not, I'd pull the code out of the inits and break them up into local MainInit functions.
posted by ignignokt at 10:32 AM on April 16, 2008


Response by poster: grouse, I know that functions are supposed to be better for sequential order. But if I put all these functions in my main class, that class would be thousands of lines long. So I'm basically (stupidly?) using classes as namespaces.

Yes, PantsOfSCIENCE , the order of the inits does matter.

Here's a better way of stating my problem: imagine you have a thousand initialization steps, and each step takes two-to-fifty statements. How would you organize those steps?

One way would be:

function step1() { /* etc. */ }
function step2() { /* etc. */ }
function step3() { /* etc. */ }
function step4() { /* etc. */ }
...
function step1000() { /* etc. */ }

But it seems to be like there should be at least one higher level of organization, especially since steps 1 though 10 could be logically grouped together (e.g. data parsing), as could steps 11 through 25 and so on.

It's not imperative, but I also though my code should somehow reflect the fact that these steps should only run one. In other words, after step5() gets called, it should never get called again. It's just part of a long init sequence.
posted by grumblebee at 10:38 AM on April 16, 2008


Response by poster: ignignokt, you've hit the nail on the head. The code will only run once, so singletons seem a bit wrong. I will never access, say, GraphicManager after that one call to its init function.

What I really want is a way to organize this code so it's not in one huge file.
posted by grumblebee at 10:40 AM on April 16, 2008


I have no specific answers, but some thoughts that might help.

Singletons are generally frowned upon for this sort of task - primarily because they make testing harder. If you want to test the app with a dummied up database layer, for example, then you don't have a good way of doing it. Dependency injection is an approach that avoids this problem by passing in objects defined in an external config file to MainInit - so you'd be calling dataManager.init() rather than DataManager.getInstance().getInit(), and dataManager would be passed in from outside. If you're using Java or .NET, look at Spring or Spring.NET. Using Spring has the added advantage that it sorts out the initialization for you automatically based on the dependencies that you specify for your components.

Do you need to run shutdown code as well as initialization code? If so, then a list of lifecycle objects would be useful (where Lifecycle would be an interface that defined init and shutdown methods, and each of your Manager objects would implement it). Then, going through the list and calling init on each, and subsequently going through the list in reverse and calling shutdown on each, would mean you didn't need to duplicate the list of items.

Are there dependencies between the various Managers? i.e. GraphicsManager can't be initialized until CommandManager has run? In which case, you might think about use of the Composite design pattern, so each Manager is a Composite which has a list of its dependencies, and goes through to initialise each of them when it initialises. It looks like you're thinking along these lines already based on the MainInit you have above.

My experience with systems like this is that they can be very painful to write unit tests for - you find you need to spend five minutes running setup code at the beginning of every test, and testing anything in isolation is difficult. Bear this in mind, whatever solution you go for.

Good luck!
posted by siskin at 10:47 AM on April 16, 2008


Response by poster: siskin, there's no shutdown code. This is a web app, written in Actionscript. "Shutdown" happens when the user navigates away from the page.

The history is that, originally, there was a simple init() method in my main class. But bit-by-bit, my employer started demanding more and more stuff happen on startup.

So I started having init() call other methods, also in the main class.

But then the init requirements kept growing. So my main class grew, too. Eventually it was unwieldy. I knew I needed to break up the methods into logical groups (and separate files), so (with a sense that I wasn't doing it in the best way but without any other ideas), I broke them up into singletons.

The nice thing is that if I need to work on just the data-retrieval init code, it's in a single file (class) without any other distracting stuff. So if not singletons, I need SOME method of dealing with this huge number of methods.

Yes, later methods are often dependent on results of earlier methods.
posted by grumblebee at 10:58 AM on April 16, 2008


In the java space there are solutions that manage (initialise) objects and their dependencies. Examples are OSGI implementations like Apache Felix and dependency injection frameworks like Spring and Seam.
Basically these are implementations of DSLs that allow you to describe initialisation and 'building' of an object tree. Individual objects only know by interface what other objects they need to accomplish their tasks. The actual implementing objects are determined by the DSL implementation.
posted by jouke at 11:00 AM on April 16, 2008


Response by poster: I'm thinking there's a way to abstract my question into a broader one. There must be SOME accepted way of dealing with a huge run of sequential code in an otherwise OOP/Pattern system. Let's say you're programming a robot.

You have classes for various robot behaviors: Walk, Sit, Grab, etc. But let's say it just so happen that grabbing is really complicated. It takes 3000 lines of code to grab, but those lines are always run in the same order.

You don't want as 3000 line-long class!

There MUST be some well-thought-out way of dealing with this.
posted by grumblebee at 11:05 AM on April 16, 2008


Best answer: I know that functions are supposed to be better for sequential order. But if I put all these functions in my main class, that class would be thousands of lines long. So I'm basically (stupidly?) using classes as namespaces.

Yes, but the way you've implemented this, your classes are basically just global functions. I would say you should try to strike a balance between having a lot of functions in one class, and having a lot of classes that only have one function.

Here's how I would suggest you do it:

- Create an abstract base class called "Initializer", give it a required function called "Initialize".

- Create several high-level classes that inherit from Initializer, such as "ParserInitializer" and "UserInterfaceInitializer".

- In each high-level class, write 5-20 lower level initialize functions, such as "InitializeScreen" or "InitializeFileSystem", where each function has a few lines of code to do the initialization.

- If you want to get fancy and your language supports it, you can use build a function into the Initializer base class to find all of the Initialize functions in the class and execute them in the order that they appear in the file. This is what a lot of unit testing frameworks do, so that you don't have to hard-code a list of functions to call when you basically want to just call all of the functions in the class in a certain order.

Once you have that written, you can change your main startup code to create new instances of all of the high-level Initializer classes and execute them in the correct order. I would probably do this by adding all of the instances to an ordered list and iterating through it in a loop to call Initialize on each one.
posted by burnmp3s at 11:10 AM on April 16, 2008 [1 favorite]


I actually had a similar thought to burnmp3s (a centralized "Init" object). In .NET, you can use System.Reflection to easily iterate through a bunch of functions. Or, if you wanted to get extra fancy and wanted to deploy across different instances that have different initializations, you could externalize the contents and order of calling those functions into your config file. Since you're only doing it once, the minimal extra overhead involved in that is pretty minimal.
posted by mkultra at 11:21 AM on April 16, 2008


Response by poster: bumnmp3s, I like your structure. My one question is about those classes based on Initializers: shouldn't they be singletons. You would never (at least in my system) want two instances of InitializeFileSystem.

And you could even implement a boolean, in each singleton, that got set to true once that initializer had finished it work. And you could make initialize() check that boolean before allowing any of the sub-functions to run.

if (booFinished == false) { /* run all sub functions */ }

lastSubFunction()
{
//main code
booFinished = true;
}

That way, an initialize class can only run once.
posted by grumblebee at 11:28 AM on April 16, 2008


Non-object oriented programming is sometimes referred to as sequential programming. Maybe there is a reason for this? OOP helps break free of the step-by-step nature of non-OOP. In the end, however, a sequence does occur, but your OO code creates simplicity for the sequential side of your code because their is a simpler interface that you have provided for yourself (or others).

So ask yourself, how is it that my OO code is simplifying the necessariy sequential parts of my code? It could be that all you have is purely sequential code and there are no need for objects.

Just looking at what you have, I might break the actions that need to take place out of the code and into some sort of a list. The list could be a text file, or a binary file, that has a step by step itemization of what things need to be initialize. Then in your code, you just run a program loop through that list initializing each item.
posted by nickerbocker at 11:29 AM on April 16, 2008


Response by poster: nicerbocker, I sort of get what you're saying, but many initialization steps take multiple lines of code to achieve. For instance, if there's a textfield, initing it might mean setting the font, color, size, etc. Each of these might take a statement. So it seems logical to put the whole thing in a function:

initTextField()
{
setFont()
setColor()
setSize()
etc.
}

If I understand what you're saying, I'd then create a text file that would say things like:

initTextField | initVideoPlayer | initMP3player....

Or it might get even more spacific

initTextField..font:Times,color:green,size:3...

Fine, but where do I put the initTextField() function and the dozens of other functions like it?
posted by grumblebee at 11:36 AM on April 16, 2008


Response by poster: I really like this idea (from burnmp3s):

-- INTERFACE Initializer
public method: initialize()

-- Class GraphicsInitializer implements Initializer
public method initialize()
{
a()
b()
}

private method a() { ... }
private method b() { ... }

-- Class DataInitializer implements Initializer
public method initialize()
{
a()
b()
c()
}

private method a() { ... }
private method b() { ... }
private method c() { ... }

-- StartUp Class
array aInitializers = [new GraphicsInitializer(), new DataInitializer(), ... ]

loop through aInitializers and call initialize() on each item.




My only issue is that I'd like to stop accidental later calls to (say) GraphicsInitializer.initialize().
posted by grumblebee at 11:43 AM on April 16, 2008


I like your structure. My one question is about those classes based on Initializers: shouldn't they be singletons. You would never (at least in my system) want two instances of InitializeFileSystem.

Yes, you can definitely make each Initializer a Singleton and build in logic to make sure each one only runs once. That's one of the nice things about having a common base class, you can have the base class's Initialize function check a required "HasFinished" boolean and return immediately if it's True, and then in the child classes all you have to do is make sure that HasFinished gets set to true after the last initialize function runs. That way you don't have to implement the condition checking and whatnot in multiple places.

In this case I don't think I'd go through the effort of making each one a Singleton though. I usually only use the Singleton pattern if there is something that is used throughout the code that I only want one instance of. For example, if there's an application-wide Log class that can be called from anywhere, I'd make that a Singleton so that only one log is written. Having a Singleton works great in those situations, because there are of places where the object could be used and you want to use the same instance everywhere without worrying about how it gets created. For cases like this where only one part of the code is going to be creating and using these classes, I don't worry about making Singletons. That's just my personal style though, I know a lot of people have a rule that they make everything that is only instantiated once into a Singleton.
posted by burnmp3s at 11:53 AM on April 16, 2008


My only issue is that I'd like to stop accidental later calls to (say) GraphicsInitializer.initialize().

in Initializer:

private boolean Initialized = false;

In beginning of initialize():

if ( Initialized ) {
return;
}

(... initialize code ... )

Initialized = true;
}
posted by StarForce5 at 12:01 PM on April 16, 2008


Best answer: Based on what I've read on the subject, a singleton should only really be considered when you must have only one object and it must be globally accessed.

As initialization only occurs once I don't see how it needs to be globally accessible. Even the fact that you will only ever want to initialize a particular system one time (you mention a file system... what if you want to have two file systems eventually? one in FAT and one in NTFS? or you're making a game and of course it'll only run on one screen... or will it?) is debatable. Additionally, it may be possible for you to write your initlization code with parallell computing in mind and making a singleton multithreaded is a bit of a chore.

A fairly good criticism of singletons is found here.
posted by Green With You at 12:16 PM on April 16, 2008


Response by poster: That's a good article, Green With You, but this paragraph is EVIL:

Of course I loved all of Design Patterns, except for pages 243 to 256, which had the magic property of inducing a coma-like trance whenever I tried to skim through them. I could put on a black ninja suit and sneak through the building, and presuming I didn't get arrested, I could tear those pages out of every single copy of Design Patterns at Amazon, and almost nobody would notice. That's because it's the most important one, so of course nobody gets it. I sure didn't!

Okay, I can't find my copy of GOF. Can someone please tell me which pattern he's talking about?
posted by grumblebee at 12:55 PM on April 16, 2008


Why not have a static boolean _initialized in the Initializer classes and enforce the only initialize once rule at the superclass level?
posted by atomly at 12:55 PM on April 16, 2008


nicerbocker, I sort of get what you're saying, but many initialization steps take multiple lines of code to achieve. For instance, if there's a textfield, initing it might mean setting the font, color, size, etc. Each of these might take a statement. So it seems logical to put the whole thing in a function:

I'm not sure what programming language you are using. Some programing languages allow you to call functions dynamically. Like PHP for instance, you can call eval() on a string that contains a function and the passing variables. I dunno if this will simplify anything for ya though. Good luck! What is fun about programming is how much you learn and fine tune your skills after every project. I currently program in LabVIEW and my boss is always asking me if I can manipulate an old program to meet the needs of a new program... I always reply something like "well..yeah, I could. But I could probably write a much better program from the ground up and quicker knowing what I know now." Knowing the syntax of a programming language doesn't make you a good programmer. It takes practice and experience.
posted by nickerbocker at 1:02 PM on April 16, 2008


Response by poster: atomly, in Actionscript, subclasses don't inherit static members. So you'd have to re-create that boolean on each initializer-based class.
posted by grumblebee at 1:03 PM on April 16, 2008


Response by poster: Green With You, in that article, the writer suggests using Factory when you think you need Singleton. I know (and often use) Factory, but I'm not sure I get that.

I always feel a bit yucky when I use Singletons. I came to some of the same conclusions as in that article some time ago. But I'm not sure how to replace Singleton in many cases.

Let's say you need a log. You need only one log. And multiple classes need to write to it. How do you cleanly do that without a singleton? You don't want to risk classes using unique instances of Log.
posted by grumblebee at 1:08 PM on April 16, 2008


Let's say you need a log. You need only one log. And multiple classes need to write to it. How do you cleanly do that without a singleton? You don't want to risk classes using unique instances of Log.

I agree, Singletons are a necessary evil for things like logging. Global state is a pain to keep track of in general though, and having a global accessible class that is used everywhere can be a nightmare to maintain, especially if its interface needs to change often.

Although I personally don't have much experience with it, these kinds of problems are what Aspect Oriented Programming was designed to solve. For example, see this intro to AOP that describes how it can be used to implement logging.

I'm not entirely sold on AOP, because it breaks a lot of the nice assumptions that you can usually make about the order that code executes in and makes the flow of the program more complicated in the same way that GOTO does. I think it comes closer to solving the logging problem than any other method does at this point though.
posted by burnmp3s at 1:31 PM on April 16, 2008


Response by poster: burnmp3s, I've been look at some blogs and message boards, and I found this strong comment:

Singletons are unequivocally a bad choice for the reasons mentioned above (although a singleton registry can have its uses). You won’t ever see them in a good OOP design.

The problem with encapsulating code in classes is that everything is locked up in separate components: how to get all the bits talking to each other? Who gets a reference to what is the basic problem of OOP design. Simply making things global to get around that is a bit of a cop out. Instead you should figure out how to pass objects around where they are needed.


This is basically my feeling. This is why I feel yucky when I use singletons. If classes A, B and C need access to a log, it SHOULD be possible to make an instance of the log and pass it to A, B and C. But that means some other process needs to do the passing and make sure that no class gets a second instance of the log by mistake.

At the very least, it seems like that process would need to be a Singleton.

But I always have the nagging feeling that if I really knew what I was doing, I'd find a way to make non-singletons and yet ensure that all players got the correct instance.
posted by grumblebee at 1:48 PM on April 16, 2008


Okay, I can't find my copy of GOF. Can someone please tell me which pattern he's talking about?

The Interpreter pattern, at least in my hardcover copy.
posted by DarkForest at 3:19 PM on April 16, 2008


Objects are not a panacea. Procedural programming is not evil. The task you are hoping to accomplish is naturally a procedural one. Shoehorning it into some object design pattern will result in you trading away your time and energy in return for extra-complicated code.

public class MainClass {
  public static void main(String args[]) {
    MainInitializer::Initialize();
    DoTheMainJob();
  }
}

class MainInitializer {
  static void Initialize() {
    static bool isInitialized = false;
    if (isInitialized) {
      throw("WTF?");
    }

  InitializeSomeCrap();
  InitializeSomeOtherCrap();
  InitializeMoreCrap();
  }

  private static void InitializeSomeCrap() {
    InitializeSomeCrapStep1();
    InitializeSomeCrapStep2();
  }

  // et cetera
}

posted by Flunkie at 4:42 PM on April 16, 2008


Uh, and remember to set isInitialized to true when appropriate.
posted by Flunkie at 4:43 PM on April 16, 2008


You have classes for various robot behaviors: Walk, Sit, Grab, etc. But let's say it just so happen that grabbing is really complicated. It takes 3000 lines of code to grab, but those lines are always run in the same order.

You don't want as 3000 line-long class!
Why not?

You're proposing taking something that is naturally a unit, and breaking it up for no real reason. The result will be more lines of code than that 3000, and will be unnaturally spread apart where its nature is to be together.

If you have some actual reason for breaking part of it off, by all means do so. But "it's big" is not such a reason.

One option, if you are intent on breaking it up, is to give it its own namespace, inside of your main namespace. So you have a main "MyRobot" namespace, and a "MyRobot::Grabbing" namespace.

Inside of that "MyRobot::Grabbing" namespace are all the supercomplicated, incredibly numerous, and incredibly tiny classes that your heart could ever desire. But there is one, and only one, function that is accessible from outside MyRobot::Grabbing. Namely, grab().
posted by Flunkie at 4:56 PM on April 16, 2008


Trying to shoehorn this procedural task into some sort of faux object hierarchy is an anti-pattern. It will only obfuscate your code. Listen to Flunkie.
posted by grouse at 5:15 PM on April 16, 2008


Response by poster: I totally agree that OOP code isn't a magic bullet.

But...

You don't want as 3000 line-long class!

Why not?


Because it's hard to debug.

This is the part of the app that I have to update the most. Scrolling up and down in a huge file would be a nightmare, given the amount of times I'd have to do it.

And there ARE logical ways to group the init methods. There are batches of them that init the same thing and other batches that group other things.
posted by grumblebee at 6:39 PM on April 16, 2008


Response by poster: AS 2.0 (I'm forced to write this code in 2.0, not 3.0) doesn't have namespaces, other than classes.
posted by grumblebee at 6:42 PM on April 16, 2008


Scrolling up and down in a huge file would be a nightmare
You need a better IDE, not a design pattern.
And there ARE logical ways to group the init methods. There are batches of them that init the same thing and other batches that group other things.
Which is why I made my example group things. Initialize() called three different functions: InitializeSomeCrap(), InitializeSomeOtherCrap(), InitializeMoreCrap().

InitializeSomeCrap(), in turn, called more specific initialization functions.

And there's no reason why those couldn't do so as well.

Earlier you said this:
Here's a better way of stating my problem: imagine you have a thousand initialization steps, and each step takes two-to-fifty statements. How would you organize those steps?

One way would be:

function step1() { /* etc. */ }
function step2() { /* etc. */ }
function step3() { /* etc. */ }
function step4() { /* etc. */ }
...
function step1000() { /* etc. */ }

But it seems to be like there should be at least one higher level of organization, especially since steps 1 though 10 could be logically grouped together (e.g. data parsing), as could steps 11 through 25 and so on.
If they can be logically grouped together, then do so. That's what I was attempting to show you in that portion of my example.

As to namespaces and such, I'm not at all familiar with your programming language, and I'm not intending to give you recommendations specific to it. But it certainly must allow some way to accomplish what I am suggesting, which, at a high level, is this:

The task you are attempting to accomplish is procedural in nature. Accomplish it procedurally.

I stand by that.
posted by Flunkie at 6:54 PM on April 16, 2008


Response by poster: I agree with you, Flunkie, but I don't think putting logical groups into separate files is non-procedural. Most books are procedural, and yet they're divided up into chapters.

I'm prepared to be wrong about this.

Now, in a language where different files are classes, is it horrible to use a class as a namespace? I know that's now what classes were intended for. But so what?

The main criticism of singletons is that they're a trick to sneak procedural programmimg into an OOP world.
posted by grumblebee at 4:57 AM on April 17, 2008


Response by poster: By the way, my IDE is Eclipse. It has tons of search and navigation tools. Maybe I'm nuts and just need to get over my issues, but I still find the idea of a 5000-line file depressing -- especially if I have to make changes to it every day.
posted by grumblebee at 4:58 AM on April 17, 2008


I still find the idea of a 5000-line file depressing

I see what you are saying. But, in the end, the number of lines in a file doesn't matter. If you make your code more complicated solely to reduce the number of lines in a file, you're doing it wrong.

I try to keep the number of lines of code in a function or a class or a file relatively small. Same goes for number of characters in a line. These are good rules of thumb that can lead to better code. But when they lead to worse code via gymnastics performed solely to keep to the rules of thumb, you should ignore them.

If you want to do some serious refactoring, you should address why you need so much "initialization" rather than the number of lines in the file. I don't understand your application, but something still doesn't sit right with me in all of this.

And now skimming through an ActionScript tutorial, I see that it appears to have first-class functions. I had assumed that it was brain-damaged in the same way Java was to insist that all code must be part of a class.

Why then, are you using classes? Again, just use functions. I assume you can put them in separate files as well, unless I am missing something.
posted by grouse at 7:01 AM on April 17, 2008


Response by poster: Yeah, it doesn't sit right with me either to do all that initializing, but it's necessary. Here's why. I was hired to write one of those anything-to-anybody applications. In other words, "Make something that displays media and allows one media element to talk to another one. No assumptions. But, for instance, via directions in a data feed, the app should be able to import a jpeg and a video, place them next to each other, and connect them so that when you click the jpeg, the video pauses. In another instance, the app might need to place two videos side-by-side..."

So before anything can happen, the data feed needs to be loaded in, parsed, etc. The external media assets need to be cached, etc. Also, there's all kids of reporting that needs to happen, prior to any display. I could go on and on.

About 50% of the app makes sense (to me) to write as an OOP project. It's pretty hard to get away from OOP in Flash, even if you want to, because much of its basic, internal structure is based around objects and instances. But, as you said, it does have first-class function, etc. In any case, I do think it makes sense for me to use OOP once the initializing is done.

What's a bit confusing to me is how to start with a procedural process and then switch to an OOP framework. I mean, I know WAYS to do it. But I don't know the best way to do it -- or if there is a best way.

There's tons of material about procedural programming out there; there's tons of material about OOP out there. There's little about switching back and forth between the two paradigms. I think that's why so many programmers tend to find one system and stick to it, whether the shoe fits or not.

Flash does have an #include compiler directive. So maybe I'll use that. I'll create an init() method that calls initData(), initGraphics(), etc. Each of these functions will call other functions that are in separate files. And I'll link to those files with includes. But take a look at this...

#include ../lib/initGraphics.as
#include ../lib/initData.as

function init()
{
initGraphics();
initData();
}

... and compare it to this:

import com.grumblebee.GraphicsInitializer; //a singleton
import com.grumblebee.DataInitializer; //a singleton

function.init()
{
GraphicsInitializer.getInstance().init();
DataInitializer.getInstance().init();
}

At the end of the day, aren't both examples doing the same thing? You're telling me I should use procedural-programming to do this. And I agree. The OOP/Design-pattern people are maligning singletons because they sneak procedural programming into an OOP system.

If you remove the pejorative word "sneak" and the stupid view that all apps should be OOP, could you just say that "if you need procedural code in an otherwise OOP system," use a singleton?

With this approach, I could also set up Singleton init classes with a common interface. I could store all initializers in an array, loop through the array, and call init() on each instance.
posted by grumblebee at 8:37 AM on April 17, 2008


aren't both examples doing the same thing?

Yeah, but one has a lot of extra cruft you don't need. You'll have to declare all those extra classes, and make them all singletons before you can start writing code. It makes it harder to write or refactor your code

could you just say that "if you need procedural code in an otherwise OOP system," use a singleton?

No, that's not really what the singleton is for. You should really only use it when you need to ensure that only one copy of an object exists. That's really irrelevant to your needs here, which is to run a set of procedures in order.

You're lucky enough to be using a programming language that allows direct procedural programming, and doesn't share Java's brain-death in that regard. Just use it.
posted by grouse at 8:54 AM on April 17, 2008


Response by poster: grouse, I'm not trying to pick nits. I'm really trying to understand. So I hope you take my response in that spirit. I'm playing devil's advocate to try to get at the truth.

What do you mean by "that's not really what the singleton is for." I'm assuming you don't mean, "That's not what the Gang of Four intended it for." Because I don't care -- and I don't see why one should care -- what the creators intended.

I assume you mean, "Singletons don't do what you're trying to do with them very well." If so, can you delve a little deeper into the negative side-effects.

I hear you on the extra cruft thing. But it really only takes a few lines to make a class a singleton. So it's not really a big deal. It's not hard to maintain, because all the singletons have those exact same few lines.

I do see one problem. Assuming I'm part of a team, a programming choice isn't just a way of solving a problem. It's also a form of communication. If I use singletons in a non-traditional way (even if there's a logic to it), I may confuse other team members.

On the other hand, one thing I like about classes and packages -- aside from all the OOP stuff (inheritance, etc.), is that if you name them and organize them well, you can navigate through your code in a logical way. It's great to see all your packages in the IDE, open one, and get right to the (aptly named) class you want.

If I break out of that pattern, it's kind of ugly. It's like having a book with neat chapters. But then at the end of chapter 5, it says, "before you go on to chapter 6, please go to youtube and watch the video..."
posted by grumblebee at 9:06 AM on April 17, 2008


I assume you mean, "Singletons don't do what you're trying to do with them very well."

Yeah, you've got it. Also, you are right when you point out that
programming is not only a form of human–computer communication, but also of human–human communication. The thing to remember is that your code is going to be read many more times than it is written. Even if the other communication is only with yourself, when you read the code again a few days later, I still think it is important to be as expressive as possible and eliminate any cruft you don't need. It takes up space on your screen and in your mind that keeps you from figuring out what the code does.

So if I were to write a singleton, when I came back and read the code again I would immediately know that "this is an object that MUST be instantiated only once for some important reason." If you use them willy-nilly, you lose this message.

Also, if you have extra cruft around, it becomes annoying to refactor it, and might discourage you from doing so due to the extra hassle.

one thing I like about classes and packages -- aside from all the OOP stuff (inheritance, etc.)...

See, I think that the OOP stuff (inheritance, encapsulation, polymorphism) is the only reason to use classes. When you need it, great, but when you don't, it just gets in the way of doing programming.

As far as organization, I usually organize my projects at the filesystem level. So things will be organized by directory (optionally) and file, and only then in classes or first-class functions. If your directory structure is orthogonal to your package structure, this shouldn't be too hard.
posted by grouse at 9:20 AM on April 17, 2008


but I still find the idea of a 5000-line file depressing

I would too. Any time I ran across a procedure/method as big as that I'd suspect that there were some abstractions that could be pulled out of it that would make if easier both to conceptualize and to edit/debug/navigate. Your initial design with DataManager.getInstance().init(), etc., is far preferable, imho, to a flattened 5000 line procedure.
posted by DarkForest at 9:21 AM on April 17, 2008


« Older Buscar con Google!   |   Where should we go? Newer »
This thread is closed to new comments.