I’ve just opened a new question on StackOverflow.com: What RAD Tools Are Out There?
If you know a great RAD (Rapit Application Development) tool or platform, leave a comment and earn reputation!
I’ve just opened a new question on StackOverflow.com: What RAD Tools Are Out There?
If you know a great RAD (Rapit Application Development) tool or platform, leave a comment and earn reputation!
The basic idea behind pair programming is that you have one computer, one keyboard, two heads (one being mostly occupied with typing). There is just one problem, though: If you’re a developer like me, you’re using keyboard shortcuts. Lots of shortcuts. And you will have your own ways to achieve things. Those ways will be different from everyone else in the team. You’re not a clone, are you? Which leads to special shortcuts.
IDEA allows to switch prefs quickly with Ctrl-BackQuote (try that on a German keyboard …) Eclipse has no way to quickly switch the UI prefs (shortcuts, active toolbars/menus).
I’ve filed a new bug to track this.
If you’ve been using Java for a while, you will have encountered the need to start an external process. So you use Runtime.getRuntime().exec(...) … and you’re stuck. You can’t set the current directory for the new process, change the environment, etc. And you’ll also have to handle deadlocks.
Bad Java. Down. So Martin Buchholz came up with ProcessBuilder. I’ll use this API to explain my concept of “Angst API”. An Angst API is an API which keeps you afraid. You use it and there is the constant feeling that something might break. The default case (which should work out of the box) is in fact the most hard to make work right.
If you know a bit about processes, you know how easy it is to get a deadlock when one is reading from the other: Process 1 is trying to write some more data to process 2 which is waiting for process 1 to read the data is has sent back a few moments ago. Deadlock.
To avoid this, you need to wrap the output streams (from which your process is reading) in a thread. This is the default case. In the special case, when you know that the processes won’t exchange any data, you don’t need this but in the common case, you do. This is what is broken with the ProcessBuilder API: It makes the special case (no data exchange) simple and the common case hard. It even tries its best to make a fix hard: All classes involved are final, private, the “no trespassing” style.
Which is the other side of the Angst API: We don’t want to bloat the Java runtime, we are afraid that some user might reuse our code, we are afraid that the performance could suffer, we are afraid that error handling is more complex if we start a background thread (one thread would be enough to process the outputs of all external processes).
When you design an API, don’t be afraid. Make it a nice API, one which you love to write, which users love to use and which welcomes them with open arms. No one likes the scary neighbor who waits for trespassers with a gun in his arms.
Imagine you have a console widget in an SWT app. The app is doing some background work and dumps lots of text in the console. Something catches the eye of the user and she desperately tries to keep it in view while the console jumps to the bottom all of the time. Here is a simple solution how to notice that the user has grabbed the scrollbar.
private AtomicBoolean userHoldsScrollbar
= new AtomicBoolean ();
control.getVerticalBar ().addSelectionListener (new SelectionListener () {
public void widgetDefaultSelected (SelectionEvent e)
{
// NOP
}
public void widgetSelected (SelectionEvent e)
{
if (e.detail == SWT.DRAG)
userHoldsScrollbar.set (true);
else if (e.detail == SWT.NONE)
userHoldsScrollbar.set (false);
}
});
In your auto-scroll code, check whether userHoldsScrollbar.get() is true.
Anyone here who is working on an application which doesn’t need to persist its model in a database? You can tune out here.
The rest of you knows the problem: You have a change in your model, you need to persist it. The problem: The persistence layer is synchronous. Your application “hangs” until the change is written to the database and the database has confirmed the commit. The reason for this design is error handling: We are afraid of what might happen if there is an error in a commit for a transaction which we sent to the persistence layer five minutes ago. What’s the user supposed to do? How can the storage thread decide what to do with the following commits? Throw them away? Suppress them until the problem has been fixed five days later? Write them to a file? To name but a few.
If there is no error, this is not an issue and this works astonishingly good. I implemented such a scheme with roughly 50 lines in my program upcscan. For Java with it’s unhealthy type system, that would be a bit more code, a whole lot harder to get right. Fortunately, the guys at Terracotta offer a support module for that.
Read more in this article: Asynchronous Write Behinds and the Repository Pattern
Do you remember vex (visual editor for XML)? I mentioned the project in my very first blog post two years ago. Development has started again as an Eclipse project. More at VisualEditorForXML.
I just found this article: Background Unit Testing: New Evolutions in Unit Testing and IDE Integration
The idea is that your IDE should run the unit tests in the background just as it runs the compiler in the background. Compelling. There are already two implementations for Eclipse: JUnitMax from Kent Beck and Infinitest.
In a recent post, I talked about people ignoring the cost of some decision. In his blog “Joel on Software”, they talk about the same thing: How easy it is to fall into the “we must have strict rules” trap to protect ourselves against some vague fear of failure. Only, humans are really bad at sticking to rules. Or are they? Maybe it’s just that reality doesn’t care so much about rules because things change. If you built your castle on the belief how well strong walls will protect you, the swamp around the basement is not going to care. You’re going down, chummer.
So we end up with a lot of rules which make exactly one thing simple: To assign blame. I’ve been working for a big company where we have a strict process how projects were to be set up. There were lots of documents and forms and comittees how to start a project and a lot of documents describing how to end it (put it into production, what documents to file, who to inform, you name it). It was a great process (in the sense of “big”, mind). The actual writing of the code was explained in a document which contained a single page. On that single page, they talked on how they would strive to write excellent, error free code and that they would use a proven strategy, the waterfall model.
They built a huge, shiny castle on nothing.
If you go to a bank and tell them you have lots of $$$ and you need to pay some big bill somewhere in the future, their first question will be: How you want to make that money work for you in the meantime? Just letting it rot under your desk is not very smart, right? You should invest it somewhere, so you will have $$$$$ or even $$$$$$$ when it comes to pay the bill. Which makes sense. Contrary to that, when we write software, we tend to spend our money first instead of parking it in a safe place where it can return some revenue, being ever vigilant to be able to pay as the bills show up. Which is harder than just sitting back and relying on some mythical process someone else has written on a piece of paper a long time ago.
So when you ask: “Should I write tests for all my classes? For every line of code? How should I spend my money?” Then my answer will be: I don’t know. How can I? I know nothing about your project. But I can give you some ideas how to figure it out yourself.
“Should I write tests for all my classes?” That depends on what these classes are meant for. The more low-level the code, the more tests you should have. Rule of thumb: Tests yield more result in the basement. Make sure the ground you’re building on is sound. And behaves as you expect. The upper levels are mostly built from lego bricks. They are easy to take apart and reshape. They are exchangable, so you can get away with fewer tests. But every bug in the foundation will cripple anything above it.
“For every line of code?” No. Never. 1. It’s not possible. 2. Maintaining the tests will cost more than the real code. 3. Tests are more simple than the real code but you still make a constant amount of mistakes per lines of code. So this will only drive the number of bugs through the roof. 4. Strict, fixed rules never work (note the paradox).
“How should I spend my money?” One word: Wisely. Wisely means to think about your specific problem and find the unique solution. Do you know in advance how much each piece will cost? No. So the best you can do is a staggered approach: Invest a bit of money, check how it plays out. If it works well, spend more. If it doesn’t, scratch it, learn, try something else. Which you will be able to do since you didn’t put all your money on a single horse.
So what if your three month venture into agile development didn’t really work out? All you lost is three months. Other projects are deemed a “success” after going over budget by 100%, using twice the time that was estimated (and none of them were shorter than a year). But you will still have learned something. You paid for it, that wisdom is yours.
Use it wisely.
The discussion about checked/unchecked exceptions is almost as old as Java. While we all have a point in your stance towards this, maybe we are looking at the problem from the wrong angle. Manuel Woelker wrote an article which concentrates on the receiver of the exception, the user, and how exceptions should behave to help the user: Exceptions From a User’s Perspective.
In a nutshell:
[…]the error message displayed to the user should also explain what can be done to correct the situation
Take this code:
Foo foo = cache.get( key ); Preconditions.checkNotNull( foo, "foo is null" );
This error message is wasting someone’s time. Use this instead:
Foo foo = cache.get( key ); Preconditions.checkNotNull( foo, "No Foo for %s", key );
See? That actually tells you why foo is null.
Can we do better than that? Yes, we can:
Foo foo = cache.get( key );
Preconditions.checkNotNull( foo,
"No Foo for %s. Valid keys: %s",
key, cache.keySet() );
As you can see, by adding just a little bit of extra information, you can prevent someone (maybe even yourself) from starting the debugger, trying to reproduce the bug and then trying to pry some useful hints of the cause from the runtime.
I’ve been looking for quite some time for this article: How can you hide a virus in the source code? Basically, you create a binary of a compiler which contains the virus and which is patched to infect other programs as it compiles them. This is a feature of bootstrapping a compiler.
Reflections on Trusting Trust by Ken Thompson.