Go Down

Topic: How to avoid code duplication in a function? (Read 1 time) previous topic - next topic

pYro_65

Quote
When I wanted to know how to set up my leds I'd asked about using classes and I got yelled at because the leds are not objects, just elements in an array.   And since all this code is not an object which I would ever have more than one of, it doesn't seem to make sense to use a class for it either.


It makes enough sense to be useful.
A class can be an object or an interface, if you only have static members you can treat it like a namespace. The advantage being the protected and private areas.

johncc



This is the block of code I want to duplicate.  If I were to just copy this into a function and pass the 'mode' variable, the constants PORT_TOGGLE_MODE, MODE_SLOBLO, and MODE_FULLSTREAM would no longer be accessible.  So I would have to duplicate those in my function, or make them global.  Neither being a very pretty solution.

Static class members (of the appropriate class).  Or globals passed as references to the objects upon construction.
Quote

Of course what some of the others have suggested, using a namespace, as I have done with led and port there, is probably the right answer.  I'm not sure why some have suggested using a class though.  When I wanted to know how to set up my leds I'd asked about using classes and I got yelled at because the leds are not objects, just elements in an array. :)

Not by me :)
Quote

And since all this code is not an object which I would ever have more than one of, it doesn't seem to make sense to use a class for it either.

Singleton.

The only difference (from a logical design standpoint) between (1) namespace (2) Class with all static members and (3) Class with static and non-static members, is that with 1 and 2 if you change your mind later and want "more than one of them", you have to edit a bunch of code, both "client" ( the code that is calling it) and "server" (the code that is being called).

IMO :) 

I come from mostly a large-scale-project environement, and such approaches are often not "worth it" in the uC-- especially hobbiest or prototype -- environment.  But the concerns you raise about your project make these approaches more relevant.

Cheers,
John

ref
"GOF Design Patterns"
"Lakos Large-Scale C++ Software Design"

Nick Gammon


This is the block of code I want to duplicate.  If I were to just copy this into a function and pass the 'mode' variable, the constants PORT_TOGGLE_MODE, MODE_SLOBLO, and MODE_FULLSTREAM would no longer be accessible.


You've already got a class, have you? Or a namespace? Can't this extra "code I want to duplicate" be another function inside the class and have access to those constants?

Can you post enough code to demonstrate the whole problem? Like, the class/namespace, and two blocks of code that you want to duplicate (are duplicates of each other).

From what you've posted I don't see the problem.

scswift



This is the block of code I want to duplicate.  If I were to just copy this into a function and pass the 'mode' variable, the constants PORT_TOGGLE_MODE, MODE_SLOBLO, and MODE_FULLSTREAM would no longer be accessible.


You've already got a class, have you? Or a namespace? Can't this extra "code I want to duplicate" be another function inside the class and have access to those constants?


No, the functon that code is inside of is neither in a class or namespace.


Quote

Can you post enough code to demonstrate the whole problem? Like, the class/namespace, and two blocks of code that you want to duplicate (are duplicates of each other).

From what you've posted I don't see the problem.


I'll try to explain it a little better.

I have my main program.  I have my main loop in my main program.  My main loop handles timing and input and puts that data in globals so functions can access it.  And it calls a function, protonpack():

Code: [Select]

/* ---
Main loop - Executes continuously while the system is powered.
--- */

  void loop() {

    // Constants:
    // Statics: (These are initialized once and their value is maintained on each subsequent loop.)
    // Temporary variables:
       
    // Timing:
   
      lastTime = time;                           // Store start time of last update.
      time = millis();                           // Get current system time.
      timeDelta = time - lastTime;               // Calculate how long last update took, in milliseconds.
      timeDeltaSec = float(timeDelta) / 1000.0;  // Convert last update period into seconds.
      //Serial1.println(timeDelta);

  // Read all switch states:
    readIOPorts();
     
  // This is where all the magic happens:
    protonpack();
     
  // Update LEDs:
    updateLEDs();

  // Play any queued sound effects once the current sound effect ends:
    updateSound();

  // Calculate time left in this frame and delay if needed.
  //  timeDelta = millis()-time;
  //  if (timeDelta < 16) { delay(16-timeDelta); }

}



That function contains all the code that makes the board do all this:
http://www.youtube.com/watch?v=mLGnVd03MxM

And the contents of that function are basically a large switch statement that performs whatever actions are needed based on the current state.

But let's say I want to reconfigure the board to do this:
http://www.youtube.com/watch?v=NRt0SG-hepU

In that case, I would like to replace the call to protonpack() with a call to ghosttrap() and not have to mess with any of the code in my main program.  And sticking a bunch of globals in my main program which are specific to protonpack() is a big no-no, because then I'm altering my main program and I, or whomever else is modifying the code, might accidentally delete something they shouldn't, or do something else to break everything.

I'm basically trying to keep the code that drives everything behind the scenes, and everything protonpack() does, completely separate from eachother.

And it seems like sticking it in a namespace or class might be the best solution, although I am not sure if the IDE will allow me to put that code in a tab by itself rather than sticking it in my main program where I don't want it.

dc42


I'm basically trying to keep the code that drives everything behind the scenes, and everything protonpack() does, completely separate from eachother.

And it seems like sticking it in a namespace or class might be the best solution, although I am not sure if the IDE will allow me to put that code in a tab by itself rather than sticking it in my main program where I don't want it.


When defining a new class, typically you split it into a declaration, which goes in a .h file in one tab, and its member definitions, which go in a .cpp file in another tab. Then you #include the .h file in your main sketch.
Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Go Up