Fast lines in DirectDraw
Filed Under Software development
When building applications that include a direct-manipulation user interface, I tend to go with DirectDraw, as this API provides a seemingly simple and efficient way of implementing interactive graphical surfaces. However, as this article demonstrates, simplicity isn’t always necessarily a good thing.
Post Linx
Permalink | Trackback |
|
Print This Page | Leave a Comment
Avoid duplicate code with delegates
Filed Under Software development
This post looks at a common system architecture (using business objects, proxy objects and command objects) and describes how code duplication can be avoided in certain situations. While all example code is in C#, this approach can be applied to most other languages with just minor tweaks.
Post Linx
Permalink | Trackback |
|
Print This Page | Leave a Comment
The Daily WTF
Filed Under Amusing, Software development
Sweet Frith on the hills, how did I manage to overlook The Daily WTF for so long? This website is a gold mine chock full of hysterically funny, spine-chilling software development occurrences from real-life projects, all nicely wrapped in deeply sarcastic commentary.
For example, consider the following method:
public bool getIsNull (object obj) {
return (obj==null);
}
Short. Simple. Tells the story.
However, while preparing the release of their product, management brought in a highly-paid consultant to refactor a load of code; during his efforts, he chanced upon the above method (and many like it), and decided to dump the old-fashioned == operator in favour of the much more enterprise-y .Equals method:
public bool getIsNull (object obj) {
return obj.Equals(null);
}
I realise this is deeply, almost ludicrously nerdy, but that change had me weeping with laughter for a good ten minutes. Fellow coders will understand why.
Post Linx
Permalink | Trackback |
|
Print This Page | Leave a Comment
Switchers revisited in C#
Filed Under Software development
For reasons that I will never understand, Microsoft’s C# does not support anonymous classes. So when applying the Switcher pattern in C#, we need to take a different approach to implementation.
A word of warning: this posting discusses the Switcher pattern that I introduced in an earlier posting. If you have not read this earlier posting, I would suggest doing so before proceeding, as it provides some fairly fundamental exposition.
Again, let’s start with some simple classes that require class-dependent processing. We’ll use fruit instead of animals this time, so nobody accidentally tries to mix Java code from previous posting with C# code from this one.
public abstract class Fruit { }
public class Banana : Fruit { }
public class Plum : Fruit { }
Here is the version of the client code that’s practically begging to malfunction once a new subclass of Fruit is introduced:
Fruit F = getRandomFruit();
if (F is Banana) {
Banana B = (Banana)F;
B.peel();
B.eat();
} else if (F is Plum) {
Plum P = (Plum)F;
P.eat();
spitOut(P.stone);
}
In C#, I implement the Switcher pattern using delegate methods (which are basically type-safe function pointers) that are passed as arguments to a Switcher method in an abstract Switcher class:
public abstract class FruitSwitcher {
public delegate void BananaMethod (Banana B);
public delegate void PlumMethod (Plum P);
public static void switchAll(
BananaMethod onBanana,
PlumMethod onPlum,
Fruit F)
{
if (F is Banana) {
onBanana((Banana)F);
} else if (F is Plum) {
onPlum((Plum)F);
}
}
}
Client code can then use the Switcher class thusly:
Fruit F = getRandomFruit();
FruitSwitcher.switchAll(
delegate(Banana B) {
B.peel();
B.eat();
},
delegate(Plum P) {
P.eat();
spitOut(P.stone);
},
F
);
This approach offers a number of features not included in the previous, Java-based Switcher class.
Firstly, the Switcher class offers class-switching logic as static methods rather than as constructors. This has the advantage that a single Switcher class can implement various collections:
public abstract class FruitSwitcher {
/* Delegate method definitions omitted */
public static void switchAll(
BananaMethod onBanana,
PlumMethod onPlum,
LemonMethod onLemon,
OrangeMethod onOrange,
Fruit F)
{ /* Implementation details omitted */ }
public static void switchCitrus(
LemonMethod onLemon,
OrangeMethod onOrange,
Fruit F)
{ /* Implementation details omitted */ }
}
Secondly, the delegate methods each include a parameter containing the original object, just re-cast to the respective class. This is for two reasons:
- It is highly likely that the class-specific client code will want to access the class-specific object members, so this would also be a good feature to add to any Java implementations.
- More importantly, this ensures that the delegate methods are specified in the correct order in the client code; if all delegate methods used a common
FruitMethoddelegate, it would only be a matter of time until someone put the arguments in the wrong order and thereby ended up trying to spit out a banana’s stone.
Other features are of course also possible, including code for dealing with null values (which could either throw an exception, or call a delegate onNull method). There is also no rule that states the Switcher method has to have the void return type; for example, we could implement FruitSwitcher.switchAll(...) so that the client code’s delegate method returns the color of the fruit.
Post Linx
Permalink | Trackback |
|
Print This Page | Leave a Comment
The old switcheroo
Filed Under Software development
One problem that has caused more bugs in previous software projects than I’d like to admit was the problem of incomplete if/then and switch blocks.
To illustrate this problem, let’s consider the following minimalistic Java classes:
public abstract class Animal {
public abstract void callTo(String message);
}
public class Cat extends Animal {
public void callTo(String message) {
...
}
}
public class Dog extends Animal {
public void callTo(String message) {
...
}
}
Now let’s assume that somewhere else in the application, we want to do something based on the class of an object. It’s a one-off action, so it cannot be implemented as a member function. Let’s say we want to attract the animal’s attention.
Animal a = getRandomAnimal();
if (a instanceof Dog) {
a.callTo("Here, boy!");
} else if (a instanceof Cat) {
a.callTo("I have food!");
}
The problem that arises is of course inevitable: what happens when we introduce a new subclass of Animal, such as Hamster? In the above code snippet, the new class would simply be ignored, which is clearly not acceptable. But how can we ensure that all possible subclasses of Animal are covered, no matter how many we decide to add later?
Superficially, the following code might look like it provides a solution:
Animal a = getRandomAnimal();
if (a instanceof Dog) {
a.callTo("Here, boy!");
} else if (a instanceof Cat) {
a.callTo("I have food!");
} else {
throw new Exception("Unknown animal type");
}
This is certainly a step forward in that the code recognises an unknown class and refuses to proceed. However, any code blocks that are not updated to include new subclasses will throw an exception during runtime, i.e. while the client is using the software. In any non-trivial code base, it is practically guaranteed that at least one such code block will be overlooked during testing, which means that the software has a hard-coded bug just waiting to happen.
What we need is a way to make sure that the code cannot be compiled until all code has been updated to include the new subclass. I call my solution the Switcher Pattern. The implementation of this pattern depends heavily on the language that the code is written in. In Java, I use anonymous classes.
public abstract class AnimalSwitcher {
protected Animal _animal;
public AnimalSwitcher (Animal A) {
_animal = A;
if (A instanceof Cat) {
this.onCat();
} else if (A instanceof Dog) {
this.onDog();
}
}
public abstract void onCat();
public abstract void onDog();
}
Client code then uses the following syntax:
Animal A = getRandomAnimal();
AnimalSwitcher sw = new AnimalSwitcher(A) {
public void onDog() {
_animal.callTo("Here, boy!");
}
public void onCat() {
_animal.callTo("I have food!");
}
};
Let us now assume we want to introduce the new subclass Hamster. Once the new class has been added to AnimalSwitcher (including the abstract method onHamster), all anonymous implementations will refuse to compile until the newly created abstract method has been implemented.
Animal A = getRandomAnimal();
AnimalSwitcher sw = new AnimalSwitcher(A) {
public void onDog() {
_animal.callTo("Here, boy!");
}
public void onCat() {
_animal.callTo("I have food!");
}
public void onHamster() {
_animal.callTo("I have a nice running wheel!");
}
};
Using this pattern, we only have to add the new subclass-based behaviour a single time, namely in the Switcher class. After that, we just have to diligently work our way through the error list generated by the compiler.
This pattern does not just apply when handling a complete set of sibling classes. It can also be used for subsets of sibling classes or even for entirely unrelated classes.
public abstract class Animal {}
public class Cat extends Animal {}
public class Dog extends Animal {}
public class Horse extends Animal {}
public class Cow extends Animal {}
public abstract class Furniture {}
public class Sofa extends Furniture {}
public abstract class PetSwitcher {
public PetSwitcher (Animal A) {
/* Implementation details omitted */
}
public abstract void onCat();
public abstract void onDog();
}
public abstract class BarnyardAnimalSwitcher {
public BarnyardAnimalSwitcher (Animal A) {
/* Implementation details omitted */
}
public abstract void onHorse();
public abstract void onCow();
}
public abstract class StuffInLivingRoomSwitcher {
public StuffInLivingRoomSwitcher (Object A) {
/* Implementation details omitted */
}
public abstract void onCat();
public abstract void onSofa();
}
Naturally, the benefits of Switcher classes depend on well-written code, as even the best design can be destroyed by poor implementation.
Post Linx
Permalink | Trackback |
|
Print This Page | Leave a Comment