Me and My Desktops
I currently have four main computers in my life:
- My Dell D610 laptop, is running Kubuntu Feisty, with a KDE (3.5.6) desktop
- My home server is running Xubuntu Dapper, with an XFCE (4.3.90.2) desktop
- My work desktop PC, running Ubuntu Dapper, with a Gnome (2.14.3) desktop
- My work laptop, an Apple MacBook Pro, with Mac OS X (10.4.10) desktop
For completeness, I also have a couple of (real and virtual) Windows machines kicking around, running XP. I've briefly touched Vista (mainly studying whatever has provoked the latest stream of invective from my wife). And, prior to the rise of Ubuntu, I spent seven years running Slackware, with WindowMaker as my main desktop environment.
So, I thought I'd write up some thoughts, particularly on the four main environments I work in. This is all just my opinion - a review of the four main environments I use. I don't say much about Windows - just don't.
Anyway, this all started in early 2006. I needed to get my laptop to hibernate. Many hours had been lost attempting this in Slackware to no avail. I needed to look elsewhere. Years of leading an always-on desktop lifestyle meant I struggled in a laptop world, where you switch your PC off and have to reload all your applications the next day.
Gnome / Ubuntu Dapper
I installed Ubuntu Dapper. Hibernation worked. I decided to stick with the default Gnome desktop (Metacity - although I will use the generic term Gnome throughout).
I lasted about two days. Gnome was pretty and clean, but functionally crippled. I have 10 desktops - some are general purpose and some are dedicated to certain tasks. For example, I always have Firefox running on Desktop 9 (or "Browser"). Gnome had no way of making my apps appear in the right place. I had to load Firefox, then move it to Desktop 9. And I couldn't drag it. I had to right-click and tell it to move. I also have lots of keyboard shortcuts. Gnome apparently provided no way to set these.I switched back to WindowMaker.
WindowMaker didn't integrate so nicely with Ubuntu though. After a few days I reluctantly returned to Gnome - assuming it was my lack of Gnome skills at fault rather than the software.
I discovered Devils Pie, an application that makes windows appear on the right desktop. It's not great, but Gnome is useless without it. I also tried Brightside, to allow dragging between desktops. I stopped using it quite quickly - can't remember why.I discovered gconf-editor. The Gnome equivalent of hacking the Windows registry. It's a dire user experience, but allowed me to set keyboard shortcuts.
It was clear Gnome had been stripped of standard Linux desktop flexibility in order to make it "easy" to use. And perhaps they succeeded. Gnome is easier to use in the same way that my car would be easier to drive if it had no gearstick. Certainly less stuff to be confused about - but I'm not sure how I'd get it to move. Gnome is easy to use for about the first five minutes - then it's stifling.
Added to this, things felt sluggish after WindowMaker. Not sure why something as limited as Gnome seems to be so heavyweight. I have no interest in eye-candy - I switch off animations and shadows and translucent windows and background images - they've always struck me as resource and time hogs. When I click minimise, I want the window to go away - I don't want to watch a cartoon of a window going away. Despite my lightweight approach, and Gnome's lightweight functionality, the computer was sluggish.
XFCE / Xubuntu Dapper
So when I reinstalled my aging home server (Athlon XP 1800+) I installed XFCE (Xubuntu). Not too much to say about this. XFCE looks nearly identical to Gnome - but is faster and more usable. Window dragging works properly with no additional software. Sadly Devils Pie is still a necessary evil. XFCE seemed less well integrated with Ubuntu than Gnome was, but if XFCE and Gnome were the only choices, I don't think I could make a good argument for Gnome.
XFCE is not sluggish even on my old hardware (which I work pretty hard). Not sure if hibernation works - the server is always on, so haven't tried.
A year passes…
Hibernation was failing on my laptop around 30% of the time due to problems with the Gnome background services. After hibernation, I couldn't get any Gnome-based windows to appear for about half-an-hour when it would fix itself. It's a bug that's well reported but without a fix. Plus I was increasingly using my laptop while out and about. The Gnome network selector is probably the worst piece of software I've ever used. Just awful.
So a couple of months back I upgraded my laptop to Kubuntu Feisty. This coincided with getting a work Macbook Pro.
KDE / Kubuntu
Hibernation has worked flawlessly since my upgrade - so that's my main requirement sorted.
And I love KDE.
KDE seems faster than Gnome (perhaps I just have better video drivers in Feisty). The font anti-aliasing makes for a very crisp screen. Applications load on the desktop I want them to, without Devils Pie or other workarounds. KDE is more beautiful to look at than Gnome. It has many options, generally presented in a non-confusing way and I wouldn't hesitate to recommend it to a newbie.
I think KDE is a stunning piece of software. I am quite critical and intolerant of software generally - as I sit here now, my only real criticism is that the network configuration tool is only marginally better than Gnome's.
Since switching to KDE I even feel a new love for my laptop…
… although that is partially helped by the fact that I'm also using the MacBook.
Apple MacBook Pro / Mac OS X
The MacBook is pretty. And I realise Apple stuff is a lifestyle/fashion choice. It has a nice metal case, a cool magnetic power supply and a stunningly bright screen - better than anything I've ever seen on a laptop.
It also has a silly single mouse button, a spongy unresponsive keyboard, a daft keyboard layout, an ill-conceived screen hinge and lights such that when the lid is closed I can't tell if it's on or off and it's DVD drive opens to the front preventing the use of most laptop stands. It has a wide-screen format (although it seems all current laptops have that) - wide screen is great for movies, but rubbish for just about everything else.
I'm getting off topic talking about the hardware. And you may laugh. But fashion choice aside, my Dell is a better designed computer.
Anyway. Mac OS X. Seems that Gnome and KDE are both influenced by it quite heavily (and I'm just assuming here that it's not the other way round). KDE seems to have borrowed some of the nice twiddles - such as the configuration panel. Gnome seems to have inherited it's cripplingly limited unconfigurable approach.
It doesn't have multiple desktops. That's a killer to my productivity. I generally can't switch off animations (just choose between them). I like a dark desktop background. Unfortunately I only appear to be able to choose between 10 possible background colours of muted pastel tones.
Essentially you don't seem to be able to do anything with your configuration that pulls you too far away from what Apple want - lest someone sees you using their hardware without the appropriate corporate look.Can't work out how to do keyboard shortcuts. Applications (and this isn't Mac OS X's problem I guess) tend to overuse translucency, so if more than one or two apps are running, the screen is horrendously confused. It's generally not possible to maximise windows to block out the background confusion. I endlessly find myself minimising things to work out what's going on. Font anti-aliasing makes characters fuzzy rather than crisp like in KDE.
I like the F9 window "deconfuser" function. But I'd swap it for multiple desktops and freedom to maximise and resize windows.
I apologise to Mac lovers if you've solved all these problems, or don't view them as problems. I'm new to Macs and maybe I've missed the point, or maybe the functions I want are all there. But I'm not new to computers - and I tend to blame the software if I can't work out how to do something I believe should be obvious.
I can see why you'd love Mac OS X if you'd only ever previously used Windows. Mac OS X would blow you away. And I believe there are some great apps available for Mac OS X that aren't available for Linux. But Mac OS X doesn't touch KDE's combination of power and flexibility while still being simple and intuitive to use.
Conclusions
So there we have it. My opinion as a user of many desktop environments. Use KDE.
I've now installed Kubuntu on the Mac. Linux on the Mac is a bit of an effort - it doesn't hibernate (but then, neither does Mac OS X). And it doesn't fix my issues with the hardware… but it pretty much works and makes me productive in a way that I couldn't be in Mac OS X.
KDE 4 is coming soon. I'm concerned. I've found a rare thing - a piece of software I love. I hope KDE doesn't get dumbed down in an effort to chase Mac OS X. Removing flexibility and functionality does not make a product more usable - I think that Gnome proves that less, is indeed, less.
Software Professionalism
The BCS is currently pushing the concept of professionalism in the IT industry. This is an attempt to move the industry a step closer to being one of the recognised "professions" - like accountancy, medicine or the legal profession.
This is to be encouraged and should be welcomed by software professionals everywhere.
A couple of weeks ago I was watching one of BBC Four's documentaries about Edwardians. It discussed how in that period, the middle classes started joining professional bodies in great numbers - particularly engineers, whose various industries had boomed over the previous century (although the the Edwardian link is tenuous - at least the Institution of Civil Engineers was nearly 100 years old by then).
One of the main reasons for the rise of the professions was to protect standards. "Professional" engineers wanted to recognise those people in the industry who had training in mathematics and physics and engineering principles, who had served their apprenticeships, did proper calculations before building things and worked to a high standard.
The professional bodies had barriers to entry based on knowledge and experience, with a disciplinary procedure if you breached good practice, with the possibility of expulsion if you really messed up. Clients could choose to use unchartered engineers at their own risk, but if you wanted quality work, with escalation procedures if problems occurred, then you would use a chartered engineer. Eventually such bodies were recognised in law, and chartered engineers became viewed alongside the other professions.
Software is new. There are many discussions around what analogies are appropriate (see the recent debate at Code Craft for a start), but ultimately it's new and there are no complete analogies - it's not engineering, it's not science, building software is not like planting a garden or building a house. It's new. But there are many parallels to the existing professions.
Software is complex, to do it you need training and education, you need to be well read; to do it well you need to have served an apprenticeship, the subject is constantly changing and growing and you need to constantly learn. It's as much a professional activity as law or accountancy or engineering or medicine - or at least, it should be.
When you go to a hospital you are treated by doctors regulated by a professional body, in a building designed by architects and engineers who are regulated by professional bodies. You are then hooked up to machinery using software written by… well, if the software fails (and you survive) you may have some comeback on the company that supplied it; but the people that wrote the code - they may just have been some Summer students or contractors whose names are long forgotten. I'm sure there are many checks in place to make sure this doesn't happen, there may even be laws around it, but ultimately nobody is regulating the practitioners.
Sure, 99% of software isn't about life and death. But it is complex, expensive and its failure can cause frustration and financial damage, lost time, lost data, lost business, legal problems - and sometimes worse.
So I applaud the BCS Professionalism in IT programme. There's work to do - perhaps "IT" is too broad and non-specific; eventually I would expect the barriers to entry to be raised; the grievance procedures need to be tested; etc.
But eventually students graduating in Computer Science will strive to enter companies where perhaps they can serve their apprenticeships and achieve chartered status in a few years after passing professional exams (as is the approach in the legal and accountancy professions). And chartered status would be recognised by employers and buyers of software services, and afforded the same respect as that associated to the existing professions.
Ultimately it will mean greater and more general respect for reliable software practictioners; greater governance over the industry, and greater respect for software practitioners within their companies - where often technically skilled practitioners are treated as the equivalent to production line employees, inferior to those who (for example) may be in non-technical managerial positions. I suspect such issues do not arise in legal practices, and software practitioners need to raise the bar of professionalism to take control of their own industry.
Nobody Knows Everything (Recruiting Programmers 101)
This is the first in a possibly occasional series stating obvious (but oft-ignored) facts about hiring programmers. Today's lesson applies equally well to hiring any technical staff, consultants, managers, lollipop ladies, whoever you want.
Some of this may sound obvious, but despite that, it's exactly the sort of stuff you (or your non-technical manager) can easily forget when you're under pressure to hire for that project which is running a bit late, and when you're perhaps a bit too busy to spend time recruiting. It's all too easy to forget the basics when confronted with a smooth-talking expert interviewee…
Main Definitions (no credit to Rumsfeld):
- Intelligent people know what they don't know.
- Stupid people don't know what they don't know.
- Naïve people think they know but don't really.
Secondary Definitions:
- Honest people say when they don't know something.
- Egotists don't say when they don't know something, but quickly go and find out, hoping you won't notice.
- Sneaky people don't say when they don't know something, but cover it with a flurry of technical terms.
Recruitment Advice:
- Everybody is a combination of intelligent, stupid and naïve (yes, including you). It's best to hire people who are intelligent more often than they are stupid or naïve.
- Hire honest people. Egotists are timewasters, and will always turn sneaky before they turn honest.
- Don't hire sneaky people. They can be alluring, giving you that warm feeling of saying "yes" a lot and sounding authoritative. You'll want to hire them, especially if you're under pressure: Don't. As H. L. Mencken said, "It is the dull man who is always sure, and the sure man who is always dull."
- If you interview someone who knows everything, then it's possible you may be naïve.
- If you work with someone who says "yes" a little too often when arbitrary technologies are discussed, then it's possible that they are sneaks.
- Nobody knows everything.
If you hire a sneaky egotist it's quite possible you won't realise until you find yourself in the office at 4am rewriting their code, so your interview process must find them out…
…Next Time: How To Know If They Know What They Say They Know.
Validating the State of Spring Beans - Take Two
Just an update to my previous post on the validation of Spring beans. Err, forget all that.
Spring 2.0 introduces the @Required annotation. You need to enable this in your config file:
And then you can annotate each required setter with @Required and Spring will barf on startup if that setter is missing from the Spring config.
It seems the annotation processor needs to be declared in each Spring config (if you have multiple config files, as I do).
I would still advocate writing and explicitly calling further validation code if you class needs it, but this is what you want in 99% of cases.
How Plain Are Your POJOs?
Back in the old days, when we wanted to write our model objects to the database, we put a bunch of CRUD methods in the classes to make JDBC calls to do what we wanted. This did its job and was easy, if a bit tedious, to program.
We refactored a bit over the years and got a lot of the CRUD out of model objects, but we still had to implement some interface, or rely on slow reflection code to map things to the database.
Then Hibernate came along and finally our model objects didn't even need to know there was such a thing as a database. Pure, clean, model objects that had data in when we needed it and from which changed data magically reappeared in the database. Nice. We achieved our goal of having model objects just being model objects, POJOs, and abstracted the database handing away to a place we didn't even know existed in five years ago.
And then we had Spring. Nice clean classes, dependencies being injected, the whole program elegantly concentrating on business logic instead of being littered with, well, whatever it was we used to have to hold our programs together. Suddenly whole new areas of code could be POJOs as well.
All very nice. But I was uneasy. Certainly my classes looked plain, but actually there was a finely balanced symbiosis between Spring and Hibernate and my objects. Yes they were plain old Java objects, but they had to be a very specific type of "plain". So not really that plain at all, in fact, I couldn't help thinking, shouldn't this level of plainness be enforced by some sort of interface?
Well no. This sort of "specific plainness" couldn't be enforced by an interface. It was in fact, closer to the duck-typing that the Ruby guys make such a racket about. Hibernate and Spring expected the methods to be there and if they were (and did the right thing), all would work, otherwise it wouldn't.
And that's where I expected this post to end when I first thought about writing it a couple of months ago. But recently, there have been some developments…
I've started using Hibernate 3.2 and JPA with Annotations. Suddenly my not-so-plain-POJO's are full of javax.persistence and org.springframework imports, and annotations litter the code. It's as if I've refocused my eyes, and the hidden structure imposed by the magic of Spring and Hibernate has materialised into the code.
So is this a good thing? I can declare my setters as @Required to make sure Spring's config is doing its job, and the Hibernate config has gone away, it's all in the annotations. So no need for a careful balance between a config file and the code. The various players are still co-dependent, but it's now a visible and robust symbiosis which will quickly let you know if something's been upset.
This new found syntactic crud in my code is a bit untidy, but syntax highlighting can help with that, and while I still miss my POJOs, actually deep-down I know they were never that plain.
There are some contentious issues; I think we need to ensure that the things we annotate in our classes are genuinely meta-data about that class rather than specifics of a particular framework. @Required is a Spring annotation, but if a value is required, it's required regardless of Spring. The maximum length of a String doesn't change whether we use JPA or some other persistence mechanism. Which things are conceptually "valid" for annotating may be a bit of an area to think about. For example, I don't think it's valid to be annotating the Oracle tablespace in which a particular table lives, or the name of a database constraint - so perhaps it's not valid to be storing table names and column names in the model objects? I don't know, perhaps we trade some purity of intent for convenience and clarity?
On the whole, I think the new way of doing things is good, and will reduce maintenance overhead by reducing the chance of errors; and where failures occur things will fail early and tell us why.
Annotations don't complicate the main Java code, but clearly express the contract between your POJO and the hidden forces which work upon it. The benefit of a compiled, typed language is the amount of validation which can take place at compile time (which otherwise you'd have to build into your unit tests anyway), annotations allow us to take that a bit further.
We're getting closer to methods being able to declare a complete contract for their usage - which would make debugging and maintenance of code much, much easier.
Validating the State of Spring Beans
I've recently started using Spring; and have a couple of projects on the go. One thing which has concerned me is the validation of bean state.
I'm a bit of a stickler for validating the inputs to all my methods, throwing runtime exceptions if invalid data is passed to public or protected methods, and using asserts in private methods.
The rationale for this is fairly obvious - the earlier you spot bad data passing through your application, the quicker you can identify and fix the problem. Bad data propagating through several layers of code can cause problems which are incredibly hard to trace. It's worth the overhead of the validation on each method (which is tiny, unless you do something stupid), and generally I'd leave assertions enabled on the production environment - they can be invaluable in tracing intermittent problems.
A good explanation of this is in Item 23 of the excellent Effective Java Programming Guide by Joshua Bloch.
Spring (or any other Inversion of Control/Dependency Injection framework) supplies you with complete, ready to use objects. You no longer construct very much at all with code (well, I'm currently experimenting with just how much I get Spring to do, and how my I do with old-fashioned Java). And that's what's concerned me - I can't just trust Spring to give me nice, valid objects.
It's not a Spring thing, but who's to say that the person writing the Spring config file will set all of the various attributes of the object appropriately.
Initially I decided that it would be best to instantiate beans via their constructors. This is an option in Spring, and I know this is the favoured means of initialising beans in other frameworks. This is good, as your bean gets properly constructed and you can validate the inputs. However, in the configs you have to specify the arguments to the constructor in the right order (rather than referring to parameters by name), plus you can end up with huge cumbersome constructors on your beans. Gets even more complicated if some parameters are optional. All this makes for unreadable config files and ugly code - which makes for poor maintainability.
Spring handles setter calls much more neatly than constructor calls. So this was the way to go. But when I come to use my bean, how do I know Spring has set all the right setters?
My initial response was to validate the various parameters in my public methods. Generally, using Spring MVC there is only one public method per class and this was the case with most of my classes. I tested the existence of the bean attributes I wanted Spring to set, and threw IllegalStateExceptions if anything was missing. I couldn't use asserts, because received wisdom is that it's "bad practice" to use asserts in public methods - because they can be switched off, and you don't want your public methods unprotected (see above).
As the number of these checks increased, the volume of…
{
…checks began make the code look untidy. And this had to be repeated in every public method of the class.
So I cheated and started using asserts. Now, each public method has a line:
And each class has a method:
{
assert someOtherAttribute != null : "'someOtherAttribute' is not set";
…
return true;
This has the benefit of each public method only needing a single line, and it can all be switched off in production, if you're so inclined, because they are real asserts.
All works nicely, is clean and readable code, and makes sense to me.
And, it turns out that my blind belief in "no asserts on public methods" was wrong. As is clearly stated in the Java Language Guide, "Do not use assertions for argument checking in public methods". Argument checking. I'm not checking arguments to the method, I'm checking bean initialisation state - which is (perhaps) fine to do in an assert.
Of course, asserts being okay in public methods to check bean state is only really valid because I'm using Spring and making some assumptions about how my bean will be used, and only expecting my asserts to check the initial state of the bean as created by Spring. Some rogue programmer could make use of the public setters that Spring requires to break the bean - which wouldn't be caught if the assertions were off. So perhaps they should be concrete checks rather than wishy-washy assertions?
I'll stick with assertions for now - while I believe in much validation, it's perhaps overkill to expect every public method call to check every aspect of the object state (and let's be fair, why should it stop at the boundary of the object, what about contained objects?). There have to be limits, and common sense should dictate where that limit is.
First Post
This is the first posting on my new blog. You won't believe the pain I've been through to get this thing working. Maybe I'll blog about it one day.