Code Design/Structure

With the best of intentions, when I lurk in posts or post myself, people sometimes come across with the attitude of 'why on earth are you doing this like that', or 'that's completely unnecessary you shouldn't do that'. Now a large portion is probably down to a simple disparity in experience (on my part also), but it does garner the question of... If I wanted to learn more about the best ways to structure or design a program / piece of code... Where would be the best places to go looking?

I've been reading about the SOLID design principles and common Design Patterns in programming but honestly, it seems that the second any arduino folk see a bunch of interface classes with multiple inheritance (which seems to align with SOLID and most design patterns) that they try to flame for over complicating the issue or saying 'this isn't Java, not everything has to be a class'.

All potentially great advice, but it leaves me and maybe others slightly torn in the quest for structuring our code in the best (right?) way.

Of course, if the code does its job its fine, but that doesn't help the quest for bettering yourself as a programmer.

Arduino programs, especially one we see here, tend to be small. Minuscule really, in terms of anything professional programmers are likely to be working on these days.

The good stuff in the software engineering toolbox really pays off when you're working on something big. Which is not to say that you shouldn't use it in smaller programs too, but if you do, it sometimes feels like you're "putting an elevator in an outhouse, it don't belong."

“Programming” covers quite a bit of territory.

One reason ppl get in a twist about some of the more advanced solutions advocated for here is that they are often not anything an OP is gonna make any sense of, sometimes obviously, sometimes only after a few posts in.

Another reason may just be habits developed over years of using tiny tiny processors with limited resources. Not all features of every language are appropriate for use in every system.

Or personal preference. I’d rather write my own code than figure out someone else’s idea. Or library, whatever. Of course no one is waiting for me to finish. Anything. Ever. It does change a person’s perspective.

There are good books for improving, but reading as much code as you can is going to be an equally if not better use of time. Pay attention to ppl who call the code good or bad, and why, and maybe some of that starts to lock in.

a7

It's fine hitherto. However, from what I've seen on this forum, many programs are exceedingly verbose and rife with magic numbers and with the same instruction hard-coded over and over, or no functions at all and everything going into the loop(), and so on. Sooner of later, code will need maintenance, and then, what could have been an easy 15-minute fix becomes a nightmare lasting for days or weeks.

OK, conclusions: For me, the only advice to improve already working code that should always be followed is that which makes maintenance and expansion easier and improves readability, not so much for others (if you work on your own), but for the programmer himself, especially if months go by before you touch up your project again.

On the other hand, insisting on OOP everywhere is just silly.

I think a lot of that is ultimately what I've been reading in the 'SOLID principles', such as code being open for extension but closed for modifications.

I guess that's most useful in very large projects with multiple people working on them. Because if Dave decides to overhaul or extend his code functionality, then Jack (who's code depends on Dave's) shouldn't then have to rewrite his (otherwise perfectly functional) code.

The elevator in an outhouse analogy did hit home a little. I guess in my own case I've been more interested in/focusing my learning on, c++ programming in general. Usually from people teaching in a Windows/Mac environment.

That said my entry into programming was through my (so far) sole and ongoing Arduino creation (a foot controller board for a guitar amp). So that's mostly where I put what I've been learning into practice and sandbox ideas.

Just don't use dynamic memory allocation. What's fine with tons of RAM is not with 64K or less, much less.

Don't use interrupts as a way to task unless the timing is real important.

1 Like

i had the Design Patterns book on my shelf for years. could never figure out why you would need any of those concepts. then an course instructor from Stanford happen to mention how he helped interface the F-15 guidance system into some newer jet using some of those Design patterns. that guidance system is probably huge and is being integrated with other huge systems requiring a layer of code between the systems

in a more recent interview, Brian Kernighan, co-author of the C Programming Language, suggested that C doesn't have the "guard rails" needed in much larger software systems that C++ provides

in comparison to such systems, Arduino is a flea and any application of some more sophisticated concepts is certainly overkill.

i read about multi-tasking OSs, inter-processor communication, ... for years without any opportunity to apply any of it. but when the need arose, i was able to, solving some problem. it was the right tool for the job, but only a small part of the job

but regardless of the size of the system, the one goal that always pays off is minimizing the code. And learning to keep things simple and maintainable with Arduino is something that can be applied later.

obviously, too simple makes things worse. learning just how complicated, how generic, to make things easily extensible and maintainable is the trick

That includes: Stay away form the String class. Unfortunately, many people are unaware of what the String class does under the hood and the official documentation is not clear at all on this point.

1 Like

That's how they do it on the F-15 is all the encouragement I need, now my arduino needs to have jet-level tech design! :joy:

Some great thoughts overall here, and I think it's starting to sink in that objection is possibly not the code design but just a case of the wrong tool for the job.

Like hiring a bloke capable of architectural marvels to erect your dolls house, or dropping a wrecking ball to knock in a few nails.

I definitely don't agree with that. Unless I don't understand what you mean by "minimising".

Again, I don't agree. (But that's OK - things would be boring if people always agreed.) I think "simple and maintainable" is one of the things to learn first and foremost. Meaningful variable names, extensive commenting, no magic numbers..... these are all things best learned right from the beginning, I think.

"Minimising" - do you mean optimisation for code space? Or RAM usage? I think there is no merit in either until code space or RAM becomes short, and then it might be better to migrate to a more powerful Arduino. Optimisation at the code level often makes it harder to understand and debug.

2 Likes

I think @st3v3n92 raises a valuable point. Although formal methodologies such as SOLID are probably inappropriate, there must be a set of basic principles we could come up with for raw beginners to help them make good, maintainable code. It could even include things like using millis() and state machines for multi-tasking code that must remain responsive, along with a wide range of other tips.

numerous times an OP posts code on a thread that is overly complicated and i've posted a version that is half the size that is more than readable.

professionally i've reviewed code where sub-functions are mostly duplicated with minor changes rather than add additional parameters, blocks of code just copy&pasted or that the code is convoluted and could have been designed better, smaller and more readable

you "don't agree" with "simple and maintainable" ??

of course they are, but these things don't describe the design which affects code size and maintainability.

architecture -- which can result in a 500 lines of maintainable code instead of 1500 lines.

very early on i was told "you don't know what you can do with 1k of RAM".

Don't be silly. I said "don't agree" with the "can be applied later" part of your comment. In the very next sentence I said "simple and maintainable" should be learned "first and foremost".

Read first, before reacting.

Ah, this is something we do agree on. Removing unnecessary duplications and convolutions makes perfect sense. "Optimising" for the smallest possible memory footprint is a quite different thing and not appropriate for a beginner.

i quoted what you wrote.
still unclear what you disagree with

by "can be applied later" i was trying to say learning to write simple and maintainable code on an Arduino is a skill that can be applied the rest of your career.

were you interpreting this to mean that after getting code to work you then make it simple and maintainable?

you seem to be equating minimizing the code with optimizing.

Ah yes, we are at cross-purposes. Sorted!

I'm not, but "minimising" wasn't entirely clear. It seems you mean making the code reasonably concise, without bloat, repetition, etc. Nobody could disagree with that. Going further than that is something I don't support - I've seen too many fancy tricks for making the source code as short as possible, but rendering it incredibly hard to read and understand.

I think there's a sweet spot when it comes to conciseness.

yes, but with more thoughtful design, not simply reducing redundancy. maybe i should have said minimize the design/architecture (which typically reduces lines of source)

i've heard very good developers complain that C++, at least for the not so small projects i've worked on, can be very difficult to follow (organized poorly).

Cargill discusses poorly written classes. Ken Thompson wasn't fond of C++. but even Stroustrup warned developers not to unnecessarily use C++ features in his 3rd ed.


i had never heard of SOLID. certainly such approaches make sense. i feel you've suggested better programing style. and i believe you've helped me clarify that once you know how to at least read code and can appreciate readbility, that understanding program design is an important step that minimize the size of the source, making it easier to read and maintain.

i think understanding design tradeoffs makes it easier to grasp highly level concepts, such as SOLID. early on i had read about maximizing "cohesion" and minimizing "coupling from Page-Jones, 1980. assume there are many others

1 Like

The Container Classes in general are bath tub on a bicycle when it comes to small RAM.

I learned C long before C++. IMO C++ String is for anal-retentives and plain dimwits.

I roll my own well-behaved classes, C++ has nice tools for that. I made one class that handles the cabinet file and mod files for EAW back in 99. On instantiation it opened the file(s) into browse mode.

C++ lets me organize code more easily and cleanly than with C.

If you use Serial, you use a class object, it has a place other than adding 3K to your hex.

More or less my thought from post #4. Compact and streamlined may compile to the exact same machine code as does copy&pasted and convoluted, but the difference still matters a lot. At the end of the day, it's still a man (OK, maybe a woman) who's looking at the code, maintaining it, chasing down bugs, scrolling lines on a monitor.

you can still have a well written and readable program that isn't easy to modify/expand if requirements change.