Wednesday, May 5, 2010

Good Programming Practice

Henceforth, I intend to post an entry every Wednesday and Saturday. I expect you folks to hold me to it, should I forget or ignore this self-imposed obligation.

Without further ado, here is this entry!

I am by no means a professional programmer. I recently finished Computer Science I at my university, and I struggled through it. In my struggles, though, I learned two major things that help with good program design, and I would like to pass them on to other student programmers. I'm all for learning things on your own, but sometimes it's better to learn from other people's mistakes.

Quick note: my CS1 class used C, but these thoughts should be useful for any programming language that uses functions (or methods), including some scripting languages.

Thing Number 1: Block Diagrams

Block diagrams: use them. Before you start coding your project, look at what you have to do, come up with a design, and draw boxes and diamonds and arrows, with simple words and conditionals, visually representing what it is you intend to do. Basically, imagine a flow chart that does what your program will do. You'll figure out very quickly if the vague idea you thought would work actually makes sense, and it'll help you figure out where you are being inefficient (i.e. did you draw the same box in two places, and can you make that not happen?). When it comes time to actually code, you can follow your block diagram for what to code next and what connects to where. It'll also make it easier for you to figure out some of the functions you will need, which brings me to...

Thing Number 2: Functions

Functions: Use them, liberally. I used to be in the habit of making my main() entirely too long, stuffing as much code as possible into it, and not understanding why functions were really useful except in certain special circumstances. The way I coded made my work more difficult, as I tried to read my code and keep track of what I had done, and it made debugging far more ridiculous than it should have been. Now, whenever I have a chunk of code that does one definable thing, I make it into a function. Determine input (if necessary), test the output (or what was printed/changed if it is void). It makes testing/debugging easier, because you can test each function essentially independently of the rest of the program. When everything is in main(), it tends to get so wrapped up in the rest of what you've written that testing a particular section of code involves a lot of commenting things out, and is a pain in the ASCII. Functions also just make things more organized. "Gee, where's the chunk of code that handles checking out a customer?" Why, it's the the checkout() function that I wrote. "I need to initialize a few structs." It's only a few lines of code, but it's much neater to keep it all in an init() function.

Give it a whirl, little programmy folks, and if you have anything to add, clarify, or argue against, please feel free to comment!

9 comments:

Kevin said...

My first read through this, I agreed with what you said, but really only for procedural languages like C. The planning approach and diagrams for OOP languages is a little different. You want to think your data structures through first, then figure out how they should look to other objects (as a sort of black box). Then make it all work as a whole.

But your second "thing" implies you're already thinking in terms of objects. Just change "structs" to "objects" and "functions" to "methods" and you're almost using OOP. And that independent testing of functions is known as "unit testing" (in case you didn't have a word for it) and is the most feared term in CS.

Rae Botsford said...

Intriguing...I was taking two other classes this semester that required coding, in JavaScript and Proce55ing (which is based on Java), both of which are object-oriented, and this approach worked really well. I did have to figure out my objects ahead of time, where I used them.

I hadn't heard of "unit testing" before. My trouble was mostly that I'd code something, the problem would get lost in the middle of everything, and I'd have an idea that it was related to one chunk of code but testing it would be a pain. Being able to test a function, trust that it works, and move on made everything take so much less time, so I have to assume that what I do is different from unit testing somehow?

Like I said, I am by no means a professional; this stuff just made things work better for me towards the middle/end of the semester.

Kevin said...

Unit testing involves testing a big set of inputs and outputs (usually automatically) so you know that function or "unit" works exactly as you expect it.

Rae Botsford said...

Gotcha. Why is that feared?

Kevin said...

It usually takes more code to test a function then exists in the function. You double your work. And do you really want to find bugs? You're expecpted to fix them...

Kevin said...

By the way, I really like processing. Mostly because it meshes really well with the Arduino (which uses a language based on processing). And if you ever find something you can't do, you pull in the java library that can do it. I'm writing a cool visual lyric analysis app for it.

Rae Botsford said...

Makes sense. In the case of a homework situation, I usually have some bugs, and I like them to be easy to find, so I can fix them fast and turn in my projects on time.

I've never heard of anyone using Processing before this class, but it seems like it has some cool capabilities. The generic name makes Googling irksome/impossible, but the Javadoc and the Processing doc are comprehensive enough that I got over the Google problem right quick.

Kevin said...

Search processing.org not processing

Rae Botsford said...

I ended up using processing.org's documentation the whole time.