Thursday, August 23, 2007

Do you want to get annoyed?

I hate when software asks things like
"Do you want to reboot now?" or
"Do you want to stop debugging?"

I almost always see this when I've done something that means I have to stop debugging or I have to reboot, even though I don't want to. While other software forces me to start what I am doing over again, I tolerated this knowing how much harder it would be to write software that let me continue working. Having the software ask me if I want to is painfully bad design - it feels like my computer is making fun of me. "Oh, did you want to keep working? Ha Ha - you want to keep working don't you. Well you aren't going to!"

Even worse, but rarely seen, is the dreaded countdown of reboot doom. This is where the software developer decided not only that a reboot was needed, but they should not give you the option to do it later. In a perverse attempt to be friendlier than instantly turning off your machine, you get a dialog box saying "your computer will reboot in 30 seconds" 29, 28, 27 ... 1, 0 Like a bomb in a B movie. If you were doing anything important, now you have to make a split second decision - should you spend your time trying to save your work and close anything running, or try various things to stop your computer from rebooting. Do I cut the red or green wire?

Even asking a question is unnecessary. I know how to reboot my machine, and I can decide when. How about simply "You will need to reboot your system before using this application".

Tuesday, August 21, 2007

Bad Chicken Code

Many people are teaching programmers object oriented programming by thinking about real world objects. A chicken and a sparrow are both birds, so think about creating a bird class, and deriving 2 subclasses. A sparrow definitely cannot cluck, so only the chicken gets a cluck method. At this point, the teacher, who likely has never seen a chicken without breading and cole slaw, tries to figure out if chickens can fly. Since I grew up with a friend who raised chickens, I will give both a fly method, but the chickens will print 'flutter'. This gives us:

abstract class Bird

{

abstract void Fly();

bool hasFeathers() { return true; }

}

public class Sparrow : Bird

{

override void Fly()

{

print('Fly');

}

}

public class Chicken : Bird

{

override void Fly()

{

print('Flutter');

}

void Cluck()

{

print (‘Cluck’);
}

}

void SomeMethod()

{

Chicken chicken = new Chicken();

Sparrow sparrow = new Sparrow();

print ('Do sparrows have feathers');

print sparrow.hasFeathers();

print ('Can sparrows fly?');

print ('Sparrows ');

print sparrows.Fly();

print ('Do chickens have feathers');

print chicken.hasFeathers();

print ('Can chickens fly?');

print ('Chickens ');

print chicken.Fly();

}

What could be easier? This teaches a student how to categorize based on logical real world concepts and how to implement inheritance in C++ style languages.

There is a huge problem with this though. We don't want new programmers to categorize based on logical real world concepts. Often times, logical real world concepts is a good place for production programmers to start dividing up large problems. But students at this level aren't ready to work on problems 1/10th that size.

Consider the code:

void SomeMethod2()

{

print ('Do sparrows have feathers? True');

print ('Can sparrows fly? Sparrows fly');

print ('Do chickens have feathers? True');

print ('Can chickens fly? Chickens flutter');

}

Aside from being too trivial to use to teach programmers, SomeMethod2() is better in all possible ways (extensible, readable, maintainable etc). If we wanted to write a non-trivial program to track various attributes about birds, we likely would create a relational database.

This is an extremely dangerous, wrong lesson that programmers will need to unlearn later. Some programmers simply don't unlearn this, just cannot stop classifying, and probably would have been happier as taxonomists in the biology department. Legal secretaries are users, so why not derive a class from them for users - heck why not even derive them from a secretary class? U.S. Dollars are money, Wednesday is a weekday. When the only tool you have is a hammer, every problem looks like a nail. There is no end to the number of real world relationships that the tool of object oriented programming seems to apply to. Maybe someone can teach them Prolog.

The reason we have object oriented programs is not to classify but to create good coupling and cohesion in ways easy for human beings to understand. Bad chicken code completely ignores coupling and cohesion, the above example (and most bad chicken code) only suffers from bad cohesion, but throw a bad chicken coder at a large enough problem, and you get coupling issues as well, since they are thinking in terms of classification, not relationships, abstraction or data flow.

Ian Griffiths (http://www.interact-sw.co.uk/iangblog/2005/09/26/extensionmethods) comments on inheritance and says “It conflates two very important but really rather different concepts: reuse and polymorphism”. Now we are teaching our students to use inheritance to define relationships and classifications rather than reuse or polymorphism.

I was writing programs complicated enough to justify object oriented code long before I learned object oriented programming, and I am not sure how I would go about teaching a new programmer now. You cannot completely ignore classes if you teach using Java or similar languages, and teaching Pascal (how I learned) is just too outdated. Maybe it would be best to gloss over the class keyword until programmers are writing 1,000 line programs (1 class, several methods), and then show them how much easier programming is if you break code up based on related functionality. That way they understand why and when to use different classes at the same time they learn how.

Its been a while since I last posted, and I am not going to clean up my last entry, I am being lazy.