how to organise large code?

Go To Last Post
24 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi

I am new to C and have been teaching myself for a few months, recently I found out that if my codes are getting larger and larger, it's harder and harder to organize.

Can someone share some tips on how to organize large code?

That my definition of large:
Say for I am dealing with a few(like 4-5) different sensors, LCD, some logic controls etc, battery monitor etc.

thanks

Zhuhua Wu - Electronic Engineering Student

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is a handy tutorial. Guess where it is? Its in the Tutorials section. It is even called something like "Organizing Large Projects".

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

C++ comes to mind.

Sid

Life... is a state of mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Jim

ka7ehk wrote:
There is a handy tutorial. Guess where it is? Its in the Tutorials section. It is even called something like "Organizing Large Projects".

Jim

Zhuhua Wu - Electronic Engineering Student

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ChaunceyGardiner wrote:
C++ comes to mind.

I don't see how C++ helps in big projects. It's even easier to make an unmaintainable mess in C++ with improper and/or abused OOP stuff.

Basically, it comes down to creating separate C/H file combo's that act as logical functional units instead of having mega sized monolithic C files. Splitting things up into directories.

And proper architectural things like decoupling, encapsulation, minimum number of global variables etc etc.

And proper, logical naming schemes.

But even with all this, if the project becomes big enough (I guess that's around 15-20KLOC) it becomes more and more difficult to maintain a good mental picture of everything.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I don't see how C++ helps in big projects. It's even easier to make an unmaintainable mess in C++ with improper and/or abused OOP stuff.

Largely, I agree. Still, C++ carries with it some constructs that help in modularization. Classes, of-course. Namespaces. Applying these wisely (in concert with how you organize your source code text filewise) makes C++ stronger in this respect as compared to C.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Agreed, but I guess if/by the time you are able to organize things neatly in C++, you can also do it in C ;)

I don't think jumping right into C++ suddenly makes you proficient at organizing things the right way.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jayjay1974 wrote:
ChaunceyGardiner wrote:
C++ comes to mind.

I don't see how C++ helps in big projects. It's even easier to make an unmaintainable mess in C++ with improper and/or abused OOP stuff.


Improper and abused stuff leads to a mess no matter what the language is.

C++ allows you to group data and related code together, removes most of the need for global variables and lets you keep track of a lot more code before you'll need to split the code into several files.

Depending on the file system to make it "easier" to keep track indicates that you don't use modern tools or don't know how to use them. Modern IDEs have a class browser, in AS6 it's called "VA Outline" for some reason. This allows you to navigate your source code with ease, and you can collapse the branches for anything you're not currently interested in looking at.

If you for some reason prefer to work with lots of source files, it'll still work the same way.

Sid

Life... is a state of mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Agreed, but I guess if/by the time you are able to organize things neatly in C++, you can also do it in C

And the other way around.

Quote:
I don't think jumping right into C++ suddenly makes you proficient at organizing things the right way

And the same holds for C.

Quote:
[...] in AS6 it's called "VA Outline" for some reason

Since it is one of the views that is supplied by the Visual Assist plugin/addon that Atmel has bought the rights to use in Atmel Studio.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Quote:
[...] in AS6 it's called "VA Outline" for some reason

Since it is one of the views that is supplied by the Visual Assist plugin/addon that Atmel has bought the rights to use in Atmel Studio.

That explains how they were thinking, but it's still a stupid name. Who gives a hoot who bought what ? Tell me what it does...

Sid

Life... is a state of mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know modern tools. One of the reasons I prefer to use Eclipse rather than the simplistic IDE of ICCAVR7. With V8 they improved it though with CodeBlocks.

Be able to see macro expansions in a tooltip, being able to F3 to a declaration, or Alt-Shift-G to find references, code folding and constant syntax checking, automatic code formatting are all handy features I use a lot.

Until you more or less defeat F3 and find references by connecting stuff via function pointers :)

Who actually use C++ on an AVR?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jayjay1974 wrote:
Who actually use C++ on an AVR?

Arduinians of course. :) Well, sort of C++.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, of course,how could I forget :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jay wrote:
Who actually use C++ on an AVR?

Me, sort-of. (I'm just a very engaged hobbyist playing around when it comes to AVRs.) Things might change in several ways, though.

And I am certainly no hobbyist when it comes to C++ in general.

Larry wrote:
Arduinians of course. Smile Well, sort of C++.

Please elaborate on the "sort of".

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sort of in the sense that the average Arduino user won't create his own classes, and probably isn't even aware that 'serial.write()' is an OOP construct.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK. I'll buy that, Jay. Reluctantly.. :wink:

(I read it as "it isn't really C++". That would be a false statement.)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jayjay1974 wrote:
Who actually use C++ on an AVR?

I do, all the time.

The question should really be "who actually uses C on AVR ?", but sadly there are plenty of people that think they actually gain something by using C instead of C++.

Sid

Life... is a state of mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bug13avr wrote:
Hi

I am new to C and have been teaching myself for a few months, recently I found out that if my codes are getting larger and larger, it's harder and harder to organize.

Can someone share some tips on how to organize large code?

The most effective way to organize code is to build abstractions around each part of the code. There are many levels of abstractions you can add, depending on your needs, and the project, and the ability to absorb overhead created by those abstractions.

Right away, you're using an abstraction from the raw Machine Code, so you've got a slight advantage in organization. As a matter of fact, you've been abstracted even further by using C, which is a higher level abstraction than Assembly.

Next, you can create functions which perform specific tasks. That is one level of reusable abstraction than improves organization.

Next, you can create groups of functions and datastructures (often called OO programming). In C++, namespaces help keep related functions and variables separated from others, while not being quite as heavyweight as classes/structs.

You can also move those abstractions into their own files (.h/.c/.cpp), so as to keep distinct concerns separate.

classes/structs help abstract even more away, allowing you to keep the concepts very general, and implementations specific to your needs.

The layer after that, you start getting into meta-programming. This can be a very powerful technique. This includes things such as Inversion of Control, Aspect Oriented Programming, and Code Generation. Though this requires a deep understanding of programming to get right.

Note, these "layers of abstraction" are not specific to C or C++, but can be useful in C/C++.

I know this was a general post, but I hope that it helps spark some thoughts/interest for you. This is not a complete list either, just off the top of my head.

Hopefully this helps,
Daniel.

P.S. I code in C++ for the AVR, though strictly my programs are small enough I could do the same thing in C with relatively the same level of organization and abstraction. It's just a matter of convenience with syntax in C++ for what I need to do. Although, some TMP in C++ has helped me create cleaner abstractions in a few instances.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Daniel

Thanks for taking the time to write such a useful information, I am at no way near that at this stage, but I know what I will be aiming for.

Thanks a lot.

random_hacker wrote:

The most effective way to organize code is to build abstractions around each part of the code. There are many levels of abstractions you can add, depending on your needs, and the project, and the ability to absorb overhead created by those abstractions.
......

Zhuhua Wu - Electronic Engineering Student

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My post was perhaps a bit vague, but some examples might help:

lets assume you have something along these lines:

#include 
int main(void) 
{
   PORTB = 3; // Enable my frobitz. 

   // Intertwine the Flange.
   for (int i = 0; i < 5; ++i) 
   {
      PORTB = PORTB & ~3 | (4<<i);
   }
}

Now, this makes some amount of sense (and the comments explain everything). However, if you keep adding to your main method, this is going to become a bunch of gobbledegook. Not to mention if you change your pins around or switch MCUs, you're going to have a hard time making sure you update all the appropriate PORTB accesses throughout your main.

So, the abstraction you can create is to introduce additional functions:

#include 

void enableFrobitz() 
{
   PORTB = 3;
}

void intertwineFlange() 
{
   for (int i = 0; i < 5; ++i) 
   {
      PORTB = PORTB & ~3 | (4<<i);
   }
} 
int main(void) 
{
   enableFrobitz();
   intertwineFlange();
}

Notice how your main function becomes more readable?

That is just the first step. Next, you could create a frobitz.h and frobitz.c keep the enableFrobitz function (and any related frobitz functions) in, and a flange.h/flange.c for the flange related functions.

Beyond that, you could even create a "config.h" file, which defines things like "FROBITZ_PORT", "FLANGE_PORT", "FROBITZ_BIT_MASK", "FLANGE_BIT_MASK", "FLANGE_BIT_SHIFT", etc... that would be used in the various .c files. This would allow you to rewire your entire project simply by modifying only the config.h.

Hopefully this gives you something more solid to sink your teeth into.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Notice how your main function becomes more readable?

I'd suggest at least a "static inline" on those functions or possibly even an __attribute__((always_inline)).

For embedded speed and size are generally your goal. You don't want an unnecessary CALL/RET and you don't want an externally callable copy of the code generated. Inlining may, however, mean a size increase if the code is called multiple times.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I'd suggest at least a "static inline" on those functions or possibly even an __attribute__((always_inline)).

For embedded speed and size are generally your goal. You don't want an unnecessary CALL/RET and you don't want an externally callable copy of the code generated. Inlining may, however, mean a size increase if the code is called multiple times.

I think as you put it in another thread, if you have to worry about that, then the compiler writers haven't done their job.

Anyway, my philosophy has always been:
Clarity first. Without clarity, you can't really work on the code.
Correctness second. Without correctness, why bother.
Optimized third. Only once you have a working program should you consider sacrificing clarity for anything at all. Speed or size.

Granted, choosing inline isn't necessarily premature optimization, but other techniques that make ugly code often aren't useful or necessary and just make it harder to debug.

Just my humble opinion.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think the difference between embedded programmers and application programmers is that the former are thinking about resource usage for everything they write.

A 2048 byte lookup table may be the "clean" solution to a problem but it's not going to hack it in a micro with 2K flash and 128 bytes of SRAM.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually, a look up table is rarely clean. Usually you just do the calculation. Only if you have a need to avoid that calculation do you add the coding overhead of a look-up table.

Point taken though, different concerns. I think both camps could learn from each other. Be aware of resource usage, but also be aware of maintainablity.