June 22, 2008
Setter methods make kittens cry
Do use setters if being edited is the central purpose of that class. Do not use setter methods to create an object. Setter methods intended for creation will still be accessible during the whole lifetime of the object. Someone might use them and break all your stuff. Basically everything involving caches or hashCode() will die in your arms. Like when changing an attribute will cause some remote piece of code have maps with broken mappings and suddenly sport sets with duplicate elements. Being paranoid makes for good code karma.
Furthermore, do not use setters to wire up required attributes. I often see code like this:
Foo foo = new Foo();
foo.setAttribute1(a1);
foo.setAttribute2(a2);
foo.setAttribute3(a3);
This is bad because until the last line has executed, foo lives in some sort of twilight zone, where it exists but may not be used yet. Your class should not allow to create an object with invalid state. Better use the constructor to wire up attributes:
Foo foo = new Foo(a1, a2, a3);
Some people will argue that this will become hard to read if you have a lot of attributes. In such cases you should use a Builder separate factory class that collects all attributes with setters and can create the object once all required attributes are present (otherwise throw an exception). This shifts the enforcement of valid object creation from compile time to runtime, but still fails fast if necessary.
A related point I would like to make is that immutable objects (objects that cannot change their state after instantiation) also make for good code karma. Mutable objects can be a pain to work with and force their clients to make defensive copies. Immutable objects are also thread-safe by default (you might still screw it up though).
May 11, 2008
Hahahahahaha
Some consultant guy writes about PHP 6:
The language and syntax differences in PHP V6 may or may not affect you as much as the next features, which are those that directly allow you to introduce Web 2.0 features into your PHP application.
Apparently Web 2.0 means libraries for SOAP and XML. I love it when I hear someone say the words "Web 2.0" with a straight face, because then I know I'm in for comedy gold.
But wait, there's more! Here are some features being removed from PHP:
magic_quotes
register_globals
safe_mode
Awesome. I couldn't name a favorite. The $SECURITY = true superglobal will still be in PHP6 though.
PHP is like a crippled old man beating himself up.
April 12, 2008
You don't know Java: Method type parameters
When someone tells you they know Java, smile and say "no, you don't". Proceed to soften them up with questions about covariance and contravariance and how they relate to parametrized types. When they start crying, go in for the kill.
But let's talk about something nice today: Method type parameters. Few people know that type parameters in Java are not limited to types, but that every method and constructor can declare their own type parameters. And if this alone wasn't cool enough, it can actually be useful!
To illustrate, I need a couple of interfaces from Java kindergarden:
interface CanWalk {
void walk(int steps);
}
interface CanSwim {
void swim(int strokes);
}
interface CanSleep {
void sleep(int minutes);
boolean isSleeping();
}
interface Animal implements CanSleep { }
interface Cat implements Animal, CanWalk { }
interface Dog implements Animal, CanWalk, CanSwim { }
Say we want to write a method that simply takes an Animal and returns it. This is the way we used to roll:
Animal returnMe(Animal animal) {
return animal;
}
What's bad about this method is, that it returns its value as Animal, even if we gave it a Cat. So if we wanted our cat back, we need to cast it manually:
Cat cat = (Cat)returnMe(new Cat());
We can improve on this by binding a type variable to the returnMe method like this:
<A extends Animal> A returnMe(A a) {
return a;
}
This way we don't need the cast:
Cat cat = returnMe(new Cat());
To give an actually useful example, let's write a method getAwake that is given a list of objects implementing CanSleep, and returns those objects that return false from isSleeping():
<A extends CanSleep> List<A> getAwake(List<A> potentialSleepers) {
return Lists.select(potentialSleepers, new Filter<A>() {
public boolean passes(A element) {
return !element.isSleeping();
}
});
}
... with Lists.select working like select in Ruby lists, but you cool kids already figured that out by yourself. Again we can give getAwake a list of cats, and get a list of cats back, rather than a list of animals. You can see how method type parameters allow us to be more expressive about our method signatures.
This might be stretching the attention span of the YouTube generation, but here's one more cool thing: Method type parameters with composite upper bounds:
<Duckish extends CanWalk & CanSwim & CanSleep> void rockTheBeach(Duckish duckish) {
duckish.walk(100); // check out the chicks
duckish.swim(20); // cool down in the water
duckish.sleep(60); // take a nap
}
This is about as much fun as you'll ever be able to have writing Java. Enjoy!
March 21, 2007
Names are important
For a profession that is all about naming things, most programmers are being terribly careless with names. Although you get away with it most of the time, you look so immensely stupid when two pieces of code disagree over the meaning of a name. Names are important.
One of the things I still love about Perl is that, by convention, it is considered rude to invade other people's namespace. So we put all our public methods and constants into the @EXPORT_OK array and let the client decide which part of that he wants to use in their code. I should be able to do the same with code extending existing classes: Let me decide which extensions I want patched in on a per-class basis. I believe extension methods in C# 3.0 work this way. Do copy this.
Another name issue few languages get right are namespaces. Namespaces are important, because sooner or later you will have two different Node classes in your project and you need to tell your code which one to use. Let's look how some popular languages are dealing with this:
- PHP
-
Bashing PHP is a bit like beating up an old man, but here we go anyway: PHP has no notion of namespaces at all. To work around this, people are using
Really_Long_Classnames_With_Packagish_Names_Prefixedto lessen the chance of namespace clashes. LOL. - Java
-
Has a wonderful culture of putting classes in packages named after some domain you own. So my
Nodeclass would be packaged asorg.netalive.swsu.Nodeand people couldimportthis name and just writeNode. Bad: When you need to use two differentNodeclasses in the same piece of code. As you can only import oneNodewithout name clashes your code will look likeMap<Node, incredibly.long.package.name.of.other.Node>. Horrible when it happens, and it happens frequently. For instance, both the most basic GUI widget in Swing and the most basic data structure in Java are calledList. - Perl and Ruby
-
Uses
Package::Subpackage::Classnamesyntax for improved looks, but since you cannot import or alias these long names, this is more about organizing files and not really better than PHP'sPackage_Subpackage_Classnameworkaround. At least you can switch into a namespace and add and replace methods without using fully qualified names. It's kind of OK for untyped languages because you only need to reference types when calling a constructor or another static method. Still the possibility of anotherTree::Nodeclass in a second library is always there and sometimes urges you to use more unique package names than you would like. - Python
-
I don't speak Python, but from what I've seen this is a language that got namespaces right. You can import a namespace as in Java, you can selectively import symbols as in Perl, and here's the goodness: You can
import reallylongmodulename as shortcutto aliasreallylongmodulenameintoshortcut. Nice.
I think what Python does (importing and importing into aliases) should be the minimum requirement for any language that wants to take names seriously. The package naming convention from Java is cool, because the DNS is the only naming scheme humanity ever reached something like an agreement over, and unique names are good. Imagine blowing up the planet because some piece of code felt ambivalent about the semantics of System.Nuke. We would look all kinds of stupid if this sort of thing ever happened.
March 20, 2007
Whoops! Open classes not cool after all!
Ruby, Perl and many other languages let you reopen an existing class or namespace and add additional methods to it, or replace existing methods with new code. Everyone thinks that is "like super-cool" and "really feels the spirit of getting things done", probably accompanied by some generic "LOL Java, agile languages FTW!" rant.
Surprisingly, open classes have one serious problem: People are using them!
Right now the two most popular uses for reopening classes are (1) adding methods to core classes like objects or lists and (2) patching totally not public code with your own funky version. Both are terrifyingly bad ideas which will probably break with the next update of the code you're patching, or as soon as another clever library attempts to do the same. But let's enjoy some examples together:
It is impossible to use prototype.js and json.js at the same time because prototype.js does something nasty to Object.prototype. But never mind since these are only the two most commonly Javascript libraries on the planet.
What Rails is doing to the Ruby core, and what some plugins are doing to Rails, is downright scary in some places. Thankfully Rails is heavily maintained and bugs are patched quickly.
While developing a World of Warcraft addon in Lua, we discovered that the preferred way to intercept chat messages was to replace the existing message handler, intercept the messages you need and hand over the rest to a copy of the old handler. Unfortunately, since our addon name was lexically smaller than the name of another addon that used the same trick, and World of Warcraft loads addons in alphabetical order, our new message handler was replaced by a third addon handler by that other, lesser addon and everything went to hell.
I'm not even sure if the last example is valid in this context, but it's also about bad scope and globals, and I really needed to stress the fact that I'm writing kick-ass World of Warcraft addons this very minute.
Anyway, don't you think it's funny how twenty years after people realized that "globals are teh suck" we're falling into the same bad habits all over again? Yes, open classes are fun toys to play with, but you can also fuck up royally if you don't pay attention. So, please, do think about what happens when other libraries attempt to pull the same hackery as you. Do consider the chance that a second library also wants to decorate the draw method, and do assume it will also save the existing method using alias :original_draw :draw. And OH MY GOD do not patch up private methods that have clearly not been cleared for public consumption by the original author!
Patching private methods. I mean, what the hell. Think of the children!
January 16, 2007
Gapless MP3 loops in Flash
When encoding a sound loop as MP3, the encoder will add ugly gaps of silence at the beginning and end of your track, making the resulting file not very loopable at all. This is due to the way MP3 encoding works.
Although there are some instructions (scroll down to "Part 2") how to remove those gaps from your sound file, the amount of hackery involved is not for the faint of heart. The same guy also wrote a tool to automate the process but it's restricted to a maximum of 8 seconds of sound, and you can totally not buy a full version.
You're lucky if you're working in Flash however. The MP3 encoder inside the Flash IDE knows about the problem and will make sure any MP3 it compresses will loop without gaps. So:
- Have an uncompressed sound loop as WAV oder AIFF. If your loop is already an MP3, remove the silent padding at the beginning and end of the track and save it as WAV.
- Import the uncompressed sound into the library of your clip.
- In the sound properties, set the desired MP3 compression.
- Loop away.
December 24, 2006
You don't know jack about thread-safety
All you hotshot programmers need to drop what you're doing and secure a copy of Java Concurrency in Practice. 50 pages into the book my face was frozen in pure horror, as Brian Goetz and his friends happily ran over everything I ever thought I knew about thread-safe programming.
What do you think the following code will print to the console?
public class NoVisibility {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread {
public void run() {
while (!ready) Thread.yield();
System.out.println(number);
}
}
public static void main(String[] args) {
new ReaderThread().start();
number = 42;
ready = true;
}
}
Unless your answer is "either zero, 42 or nothing at all" you really need to read the book before someone notices.
December 08, 2006
There's nothing wrong with bloggers
<tom> there's nothing wrong with bloggers <tom> it's just that like <tom> when they're ALL in ONE ROOM, all SWEATING, all POSTING, <tom> all EDITING ONE DOCUMENT COLLABORATIVELY WITH SUBETHAEDIT, <tom> it gets a bit much <liz> do non-bloggers not sweat then? <tom> they do, but their sweat doesn't have an rss feed
July 30, 2006
Why you should stop blogging
Look kids, I really believe this blogging thing has gone out of hand, so here are some things I need to get off my chest before anyone gets hurt.
First off, you really don't have to apologize for not having updated your weblog in a while. I'll just assume you had something better to do. Also your guides on overcoming writer's block and getting your daily blogging rythm going make me cry. It's not a freaking competition, mmkay? The whole beauty of this syndication thing is that I will still hear you after three years of blogging absence. I actually prefer reading occasional burts of goodness over the stream of consciousness shit that is clogging up the internet.
Second, if you ever forego a night with your friends in order to be able to update your weblog and I catch you, it's not going to be a pretty sight. Understand that our time on this planet is very limited and there are only so many bars you can hit before nature collects its toll. You must choose how to spend the time that is given you, and if the majority of it is spent blogging, you really need to reconsider that choice.
Also your weblog is probably not going to get you laid, ever. That implies that you should not see blogging as a popularity contest. You probably don't want to be among the "A-List" bloggers and if you ever find yourself aspiring that goal, please see the previous paragraph about bars and friends. Enjoy what weblogs have to offer, but don't use weblogs as your sole source of knowledge and self-affirmation. Always remember that the "blogosphere" is an echo chamber that can give you a very distorted image of reality if consumed without enough perspective. The vast majority of the online world does not read or write weblogs, and in no way are we smarter or hipper or more interesting or better informed than they are.
The most important people in your life will probably not have a weblog. They also won't turn up on a Google search.
Finally, stay away from World of Warcraft. That is all.
June 29, 2006
My homework could totally beat up your homework
How's that for a university project: We're currently writing the AI code for a heavily pimped Lego Mindstorms robot, which has to collect "flags" in a labyrinth and shoot down the Lego bots of the other, lesser teams.
Best project ever.
Elsewhere
-
Invasion Of The Dynamic Language Weenies
""What we need is to kick the idiots out, and educate those with less understanding."" -
Stop Thinking of Flex As a Browser Technology. Seriously. Stop It.
"In this rush to throw all of our applications into a web browser, it seems like we haven’t stopped to ask ourselves why these old rules should apply to this new software medium." -
Mr. Gosling - why did you make URL equals suck?!?
"java.net.URL class officially sucks!" -
How to hire Guillaume Portes
"This is a running criticism I have of Microsoft's Office Open XML (OOXML). Its extreme length (over 6,000 pages) stems from it having detailed every wart of MS Office in an inextensible, inflexible manner. This is not a specification; this is a DNA sequen" -
GPL Java: who cares?
"Yet every little fuck and his penis are waggling furiously about how this is a new era of something or the other. Even that perennial turdburglaring hippie Stallman is on board. How low do you have to sink to need an endorsement from him?" -
How Two Hours Can Waste Two Weeks
"We know how programmers think. We know how expensive switching their context is. If Sarah spends just two hours thinking of her old project, she loses a day of productive work on the new one." -
Fucks per programing language and license.
"What language is the most sweared one?" -
Dynamic language, refactoring IDE. Pick one.
"amen" -
Good Agile, Bad Agile
"It turns out there's a good kind of Agile, although it's taken me a long time to be able to see it clearly amidst all the hype and kowtowing and moaning feverishly about scrums and whatnot." -
Purr Programming
"With suitable training, the cat's natural pattern recognition abilities can be directed to the task of code style and format checking. The feline preference for playing with balls of yarn manifests in a programming context as a facility with multi-threadi" -
Is Weak Typing Strong Enough?
"I was personally able to witness a more or less apples-to-apples, multi-year comparison of the strong-typing and weak-typing camps at work in the same production environment." -
Language Wars
"People all over the world are constantly building web applications using .NET, using Java, and using PHP all the time. None of them are failing because of the choice of technology." -
Software Development: The Abstraction Dilemma
"Being able to use the String class from your language to achieve your string manipulation goals is essential. Making your application dependent on Apache Strings package just to use a couple of their convenience methods is not essential." -
Offensive Coding
"Tempted to code defensively? Maybe it's because you're dealing with offensive code." -
The Vietnam of Computer Science
"Object/Relational Mapping is the Vietnam of Computer Science. It represents a quagmire which starts well, gets more complicated as time passes, and before long entraps its users in a commitment that has no clear demarcation point, no clear win conditions," -
Why code reviews are good for you
"Over the years, I have had the opportunity to work with various code review systems, and I have come to believe that one particular approach works better than the other. Here is what I've learned." -
My First BillG Review
"THERE WERE NOTES IN ALL THE MARGINS. ON EVERY PAGE OF THE SPEC. HE HAD READ THE WHOLE GODDAMNED THING AND WRITTEN NOTES IN THE MARGINS." -
Checked exception still considered pointless
"Checked exceptions don't help much and are best minimized or avoided. But I don't expect to get much traction on that idea." -
Discontinuous Web
"Continuation-based web frameworks are the correct answer to the wrong question." -
The Programming Language of the Future is in /dev/null
"When someone from the future hands me a programming language from the future, I already know it's a kid's project on extinct software design practices." -
Josh Bloch on Design
"In this interview, Josh discusses API design, extreme programming, code quality and reuse, refactoring, defensive copies trust, forgiveness, immutables, documenting for inheritance or disallowing it, copy constructors, factory methods, the equals method," -
Making Popular Layout Decisions
"You’re a Web designer, right? You fascist oppressor." -
MVC: No Silver Bullet
"A clear separation of concerns is what is really important, and while MVC is one way of achieving it, it is not the only way. By concentrating too closely on an MVC architecture, it is possible to overlook other important aspects of the system that warran" -
What the space shuttle taught us about reuse
"The space shuttle is a great lesson for people about what NOT to do in engineering. Aside from violating every principle of KISS it basically asked all the wrong questions and as a result came to all the wrong conclusions." -
When Design is a Matter of Life or Death
"You've taken on a design challenge and come up with a solution that's been widely admired and won you accolades. But a year or so later, you realize you made a mistake. There's something horribly wrong with your design." -
When friends and contacts are neither
"I realized mapping my personal relationships of "contact" (acquaintances) and "friend" clashed with the actual utility of Flickr." -
SQL on Rails
"Rails is a short-stack framework for developing database-contained web applications according to the Model-Model-Model pattern." -
Best Practices for Object/Relational Mapping and Persistence APIs
"I will begin with a discussion of home-grown vs. off-the-shelf persistence solutions, including areas to consider when deciding between the two, and advice for choosing the best off-the-shelf solution to meet your needs. I will also share suggestions and" -
Fluent Interface
"The API is primarily designed to be readable and to flow. The price of this fluency is more effort, both in thinking and in the API construction itself. The simple API of constructor, setter, and addition methods is much easier to writ" -
A little anti-anti-hype
"Ruby's dad could totally beat up Python's dad." -
Standards, APIs, and the eye of the reader
"It's time to stop talking about how we'd build stuff, and go on and actually do it. Validation porn has had its day."