tags:

views:

115

answers:

8

I've been repeatedly told not repeat myself when programming. I've come across a scenario where I'm wondering whether to write two functions, each for a particular purpose, or a single function that handles both purposes. I'm not sure what is the "best practices" approach:

All functions in question deal with allowing a person to change the rank of a list item by one position, plus or minus one. All items and their ranks are saved in a MySQL database table.)

Two functions One function to move an item's rank up by one, and another to move the rank down by one.

One function I can write the same functions into one by adding an additional argument of "direction" and using an if statement to decide whether to move an item up, or down.

In terms of performance, is it better to write two functions and let them share the load? Is there such a thing as "function overload" if the same function is receiving a ton of requests?

I don't think it is relevant, but I'm using ColdFusion, and my additional "direction" argument would be a string wrapped in a statement that checks it's value to determine which action to take.

+2  A: 

No, not necessarily.

The advantage comes in the maintenance part where you need to change old code. If the same code is repeated in several places, the risk is high that you do not fix all these places.

DRY avoids this, by avoiding multiple copies. Note, however that needing to add conditionals does NOT mean you obey DRY, because then you are merging two different functions.

Regarding your concern about "overloading" functions by calling them too many times. It doesn't work that way. The CPU doesn't care if the code is in one or two functions, as long as the design is pure and your code respects the semantics of parallel programs (which can be challenging in itself).

Thorbjørn Ravn Andersen
Couldn't have said it better myself :)
KevinDTimm
+2  A: 

DRY is for creating code that is smaller and more maintainable.

From a performance perspective, the difference will be practically non-existent in most scenarios. In a compiled language, the compiler will optimize out any performance difference there may be.

Pekka
+2  A: 

It's usually exactly the opposite; more re-use, more layers of abstraction means that at a micro level your program is doing more work (unless you have a very smart compiler or optimizer in between.) Trivial examples of eliminating DRY which are usually made pointless by modern compilers and runtimes are loop unrolling and function inlining.

However, any tiny gains made by limiting abstraction are usually dominated by the huge gains in readability and flexibility obtained by writing a nicely-organized program made out of reusable pieces.

mquander
+2  A: 

The DRY (Don't Repeat Yourself) principle isn't really aimed at maximizing performance though adhering to it can make it easier to optimize for better performance. DRY is aimed more at simplifying your code and making it slimmer and easier to maintain.

In practice, this can mean performance gains because once you find an optimal way to do something you implement it in the one place that you wrote it and everywhere it is in use will reap the benefit.

Daniel DiPaolo
+1  A: 

Like many other programmatic methodologies (or acronyms, or patterns, or whatever), your approach should be a pragmatic one, as no one approach will always equal a "better performing" app. Off the top of my head, I'd say you'd probably achieve nominal savings in the form of space, but probably not to the point where you'd notice it or make a difference.

Ultimately, however, the main point of DRY is for better performing DEVELOPERS moreso than better performing apps. If an optimization needs to be made, then there is only one place to make it, as opposed to having to remember all the various places you've "repeated yourself" :)

Montagist
+1  A: 

There would actually (in most cases, depends on the compiler) be a performance overhead in having more than one function, as the function call itself costs. The main reason for using the DRY approach is to make it easier to maintain and understand your application.

UPDATE: Update to answer a comment to this answer. This was meant as an answer to the general question as it's very far from it that DRY leads automatically to a better performing application, although the cost mentioned here is very little indeed.

If you run the following with the Debug/Window/Disassembly window open:

class Program
{
    static void Main(string[] args)
    {
        Do();
        Do2();
        Console.ReadKey();
    }        

    private static void Do()
    {
        int a = 10;
        a = a + 10;
        a = a * 10;
        Console.WriteLine(a);
    }

    private static void Do2()
    {
        int a = 10;
        Add(ref a);
        Mult(ref a);
        Console.WriteLine(a);
    }

    private static void Add(ref int a)
    {
        a = a + 10;
    }

    private static void Mult(ref int a)
    {
        a = a * 10;
    }
}

In the disassembly window you'll see the actual statements the application has to go through to call Do and Do2. Do2 simulates a DRY program. If you step through the assembly code, you'll notice a section similar to the following at the top of each function:

00000000  push        ebp 
00000001  mov         ebp,esp 
00000003  push        eax 
00000004  mov         dword ptr [ebp-4],ecx 
00000007  mov         eax,dword ptr ds:[71D81468h] 
0000000d  cmp         dword ptr [eax],0 
00000010  je          00000017 
00000012  call        FFFFDD68 
00000017  nop 

This is part of the overhead and just happens once in Do(). In addition to this, there will always be an operation that directs the control flow to a different place in memory.

This being said, I definitely would recommend using DRY in just about all circumstances.

steinar
Where is the penalty? It's one call per operation whether you're calling the general or specific function. The only difference I see is the effort involved in putting the flag value on the stack.
Larry Lustig
Edited to answer this comment.
steinar
+3  A: 

No, DRY does not necessarily mean that your application will perform better. It makes it easier to write a well-performing application (since optimizations only have to be done in one place) and it will almost certainly make your application easier to maintain. But a non-DRY application can, in theory, perform as well as a DRY one.

Choosing to write one more general function or two more specific ones is not necessarily the same thing as DRY. You have to balance how much of the code is the same in the two functions and how much is different versus the additional complexity of general purpose function. In my opinion, this is a borderline case but when I've done it I've done it in one general purpose function.

There is a term "function overloading" in programming, but it means something very different from what you suggest. There is no risk of "stressing" a function too much by calling it too often.

Larry Lustig
+1  A: 

DRY is about writing code that is correct, both now and in the future.

If your code is broken, it doesn't matter how fast it is.

Andy Lester