Archive for the ‘Programming’ Category

When to class / when to table

Sunday, January 3rd, 2016

So, there’s a related issue in database design and in object oriented programming, and it surrounds the question of when do I break this type of data off into a new table / new class?

Fully normalized data is a pain in the ass to work with. You have to join to find anything you care about, and there’s a performance cost to doing joins, especially outer joins. On the other paw, fully denormalized data is also a pain in the ass to work with. It can be very expensive to search that enormous haystack for that tiny needle, ALTER TABLEs take forever to run, etc.

In the programming world, if you create too many object classes, it’s a royal pain in the ass to find anything, your executable size is going to go up, and unless you do a very good job of inheretince you’re going to be doing cut & paste coding every time you add a good feature. On the other paw, if you create too few object classes, you’re going to find they get large and cumbersome as you have to add many methods to them for the varying sorts of data they’re carrying. Again, maintainability goes down, readability goes down.

So, how do you decide when it’s time to tack on a table or a class? I don’t really know how I make this decision – there’s some sort of intuitive leap that happens inside my mind that says ‘now would be a good time for another table / another object’. Sometimes there are clear data bounderies – a map coordinate probably doesn’t belong in the same table as a phone number, because it’s a very different type of data. Sometimes external APIs suggest a path, because of the way their interfaces are defined. And so forth.

I don’t have a good answer to write down here yet. I’m still thinking about this. But if anyone wants to comment, I’d be happy to hear your thoughts on the matter. (I think I have about 3 readers at this point, although my web traffic statistics would suggest that’s not correct)

How to write really good code

Friday, January 1st, 2016

1) Test *every single line*. I generally execute whatever I’m writing about once every 2-3 lines of code, once I’ve got the skeleton up. If you can’t do this quickly, change your workflow so you can.

2) Use human-language function names, variable names, method names, and class names. If a loop won’t fit on a standard IDE screen, use a human language iterator name instead of i.

3) If you find yourself cutting and pasting code more than once, use a method or a function.

4) If you’re not sure exactly how something is going to play out (like a regular expression, library system call, etc) create a very small program that only tests the way you are using it. This will encourage you to test out the possibilities involved more thoroughly, and once you get used to doing it it can be a very fast thing to do.

5) In #4, deliberately create bad data. Pass in empty strings, negative numbers, nulls, strings with SQL injection in them, strings that are too long, email addresses with no @ sign, and the like.

6) If you have a try {} catch {} – make sure you do something useful in the catch. If you need to break this rule (and occasionally you will) write a very descriptive comment as to why.

7) Know when you’re not in the headspace to code. Don’t try to program when you’re not capable of simultaneously seeing things as black and white and as shades of grey. Only you will know which emotions and thoughts make you write bad code – but in general, if you’re not in the place to program, don’t try. The rest of the team thanks you. Coding is the very essence of explaining rational thought about a subject in very very small steps, so if you’re not thinking rationally, you’re not going to write good code.

8) If you’re working on a very big project (20k+ lines), try to do all your developing in little testbed programs (as in #4) until you’ve got it working completely correctly. It is much faster to build and run small programs, and you also stand a much better chance of not stepping on someone else’s work

9) Use source code control. Check in early and often.

10) If you have a group of related data (for example, information about a customer), use a class. Even if it’s just carrying data – later you may find reasons to add methods to it. There’s a fine line to be walked here, however. You don’t want to use a class for the customer’s phone number’s format string. Usually.

11) Once you know and understand how to write code, you will see that a lot of the things your teachers tell you are basic rules are meant to be broken, occasionally. When you do break them, however, comment on which one you broke and why.

12) Build quality stuff. You never know when you will have to maintain it.

13) Refactor and rewrite. You will often get much better results the second and third time you write the same function. I actually prefer to write most things in a prototyping language (php, perl) before writing them in a compiled binary language, and I think switching languages also helps me write better code.

14) I generally write out psuedocode in human-readable language (english, in my case) before I start programming. This encourages me as a developer to think through what I’m trying to do before I start thinking about breaking it down into if/then/else

15) Every function should have a sane default path through it. switch() is a very powerful and useful tool because it encourages this. Sometimes the sane default thing to do is throw a exception.

16) For every variable that comes from ‘the outside world’ (a human out there on the net, a A/D converter, etc) make sure your code can cleanly handle completely unexpected values. What would happen if there were special characters? If it’s a signed type, did you handle negative? If it’s a nullable type, do you handle null?

17) While you’re doing #1, notice where the ‘pain points’ are. Use a profiler, or just capture high resolution timestamps. Figure out what ran slow and how you can make it run faster. This can be a fine art – for example, knowing which types of data sort will run better on the database engine and which will run better natively in your code takes quite some time to master.

18) When refactoring – if the source code is getting shorter, you’re doing it right.

19) Beware of excess convolution. Occasionally you will find you have done something silly like failed to initialize a useful variable set early in the process and instead calculated the value for that variable all over a set of nested function calls. If it feels confusing reading it, you probably need to rethink your approach.

20) Above all, have fun. Building really high quality things can be a great joy, if you let it. Remember to keep a positive attitude, and always work on having more patience. If you find yourself getting angry, you are probably not thinking rationally, see #7.

21) Remember, *nothing is set in stone*. One of the joys of programming in this era is you can go back and change your mistakes.

Perl arg parser

Monday, June 10th, 2013


I use this a lot when writing a simple perl script that I want to take args like –flag and –database=this and –comment=”This is a comment with spaces”

while($arg = shift) {

if(($s1,$s2) = $arg =~ /–(.*)=(.*)/) {
$l1 = lc $s1;
$s2 = $a if(($a) = $s2 =~ /^\”(.*)\”$/);
$arg{$l1} = $s2;
} elsif(($s1) = $arg =~ /–(.*)/) {
$l1 = lc $s1;
$arg{$l1} = 1;
}
}

Stick it in the top of the script, and you can then just use

if($arg{‘flag’}) {

}

$comment = $arg{‘comment’};

and so on and so forth.