Saturday, January 10, 2009

Push vs. Pull or Why company mailing lists are evil

Everybody that works for a large organization knows the semi Observer anti-pattern. In some form or another at least. It works like this: The Big Boss thinks that you need to know, so he pushes information to you through email. He is too lazy to push this corporate spam to all personnel individually so you get added to a list automatically. At least some of your bosses don't know that there is such a thing as BCC so soon all personnel knows all the lists they are on.

The next step is that people start holding discussions using the email addresses for those lists. I've seen these types of discussions spiral out of control in different firms I've worked for. This causes unreasonable load and distraction for the employees and can even cause the whole email system to collapse under the strain. I can tell you this is not the first time something like this has happened.

What makes this behavior unforgivable, is that there is such a simple solution.

Use RSS or newsgroups to let people subscribe to replacements for these lists and clearly separate directed communications (to a few people) from news and open discussions. By using this simple solution (and working for a company that actually does this right), I've managed to reduce my incoming email by 80%. It is still some work to go through all the mails after a few days of inactivity, but the thing is it is not absolutely impossible anymore. The other immensely satisfying improvement is that most mail I get I actually want to read.

I do have thousands of unread items piling up in my RSS reader and nntp client, but those I know I can safely discard when they get stale. They don't eat up disk space and I can always search them.

There are reasons to keep lists in the company anyway. For example some employees are too lazy or stupid to subscribe to RSS lists and newsgroups, if you are legally required to send out a communique an email push might come in handy. In those cases: use BCC. If something should not be done, make it impossible. Guidelines for Reply-All and the pleas and threats to follow them are just more unneccesary noise.

So bosses all over the world, if you read this: be smart and stop spamming your employees, they hate you for it and they're right.

I saw another complaint about many emails in general. I bet that this guy is subscribed to his own blog using email. He ends his post with:
If you are the person with the idea to save us all, send me an email and tell me all about it. Actually, strike that. Drop by my house and tell me all about it. I don’t want your message to get lost in my inbox
I'm not a venture capitalist, but still the difference is striking: my mailbox is completely read, and I spend less than an hour a day to keep it that way.

Sunday, October 12, 2008

Syncing calendars... nothing is ever easy

I have a problem of managing multiple callendars. My wife has access to my Google calendar, my company has access to my Zimbra calendar. I use a Mac, and I like to use iCal if possible. I use Plaxo, TripIt and Dopplr, which provide ical interfaces/synchronisation, just like Google and Zimbra.

All this shouldn't be too original, so I expect that other people have this problem. Granted it is not an easy problem to solve, because synchronisation isn't easy. Let me first explain how I'm managing things now (and how I screw up). Then go over the options and then over what I really want.

Now I manage my calendars through CalDav. This works really well for a single calendar, but it does nothing for you in terms of synchronisation. If my office manager add's an appointment I see it show up in the right calendar, if I get a trip confirmation and send it to TripIt same story if my wife makes an appointment I can see it show up too. Nice overview, clear separation of calendars. Perfect, as long as I do the managing. That is the problem, my wife manages the calender of our private life, my manager manages the calender for the jobs. They have no idea what the other is doing.

So I screw up like this: if my manager plans for me to be abroad he checks with me and puts it in the calendar, then I have to make sure it shows in my private calendar that I'm abroad, otherwise my wife will plan something conflicting in the home calendar.

The underlying problem is that I am just one person, so everybody planning for me to be somewhere needs visibility on where I am. Main options:
  • Be more disciplined and copy things over
  • Use a single calendar and synchronize
The first option is what I'm doing now. Fine tuning this would mean I create a single calendar that lists my availability and make sure that all planners have read access to that from a single interface that they use for planning. The advantage is that this way the planners do not have to worry about fine grained appointments, just about available time (in a certain location).

The second option would allow me to be very lazy, but it would also result in a privacy issue where my manager can see that I went to a party on thursday evening or something. I don't care that much about privacy. I do care about my manager moving around my dentist appointment from the private calendar, so the solution is not ideal.

An ideal situation would allow me to share availability across calendars, and restrict write access and access to detailed information based on different calendars/sets of appointments.

The annoying thing is that there are no tools that allow this. Requirements are:
  • Have to use Zimbra for work
  • Have to use Gcal for private
  • Want to use iCal as interface
  • Want to integrate CalDav calendars
  • No manual syncing
The only way to get close would be to install different sync utilities for my mac and sync with a local calendar. The proper way to do it is to allow CalDAV calendars to be synced in ical, but there is no support for this in iCal natively. The only workable solution (other than discipline) is to run sync utilities like Spanning Sync and the Zimbra iCal plugin. This is bound to screw up my calendars at some point I'm sure...

Saturday, August 23, 2008

Update svn on Leopard to play nice with subclipse

Not so long ago I moved forward to STS 1.1 which is based on Eclipse 3.4 Ganymede. Of course I needed a svn plugin and then I ran into this issue.

Mac OSx packages an old version of collabnet subversion (1.4.x). And that doesn't play nice with subclipse. The fix suggested there is to use an old version because:

For Windows users, it is a simple matter of installing the new Subversion 1.5 client and making sure JavaHL is on the path. For Unix users, this workaround obviously defeats the purpose of having a distro with package management and requires manual installation of the libraries in the correct locations.

If you truly understand that and it is a blocking concern for you (notice the hint of sarcasm), don't read on. There is however a very simple solution to run the right version and just make it work.

  1. Download and install http://www.collab.net/downloads/apple/download.html
  2. sudo rm /usr/bin/svn* (you might want to check if you haven't got any other programs named svn* before you do this)
The second step is needed because the collabnet package installs simlinks into /usr/local/bin and the programs in /user/bin take precedence.

Once this is done you're good to go, and with the latest versions.

Wednesday, August 20, 2008

Correct Simple Singletons

This is going to be a very short blog. It's not about concurrency. It's about avoiding to think about concurrency. As was the original intent of this blog it is about being lazy, but still not being wrong.

Yesterday I read a very old blog while digging through the web for reasons to be scared of the volatile keyword. I found plenty, but this one is a gem: http://blogs.msdn.com/brada/archive/2004/05/12/volatile-and-memorybarrier.aspx. It's about .Net code, but the basic problems also apply in Java. The link to http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html is worth a read too.

If you can think about concurrency but you don't want to do it every day like me adhere to these rules when writing singletons:

When you plan on using the singleton write:

public class Singleton {
private static final instance = new Singleton();
private Singleton() {}
public static Singleton get() {
return instance;
}
}


When you don't plan on using the singleton, but you still feel the urge to implement it write:

public class Singleton {
private static instance;
private Singleton() {}
public static synchronized Singleton get() {
return instance;
}
}


When you're not going to use the singleton a lot, it is probably more memory efficient to just use a disposable instance, hence removing the need for the singleton at all. So the recipe goes like this:
  1. Don't use a singleton if you don't need to
  2. Use the simple (static final) variant if you do need a singleton
  3. Use the synchronized variant if you are intent on going on the downward slope
  4. Of course you are special, so go on and do it the hard way.

Wednesday, July 9, 2008

Don't repeat yourself, just quote yourself.

I just read an article by Dan North about how the DRY principle doesn't work with Test code. Obviously I agree with him, because it is almost trivial once you've figured it out on your own. I already met many people that did and were quite happy with themselves for it, actually that could have been me after I had about 1 year of experience with TDD.

When I read the linked blog I mused over the main counter argument against dropping DRY, it is actually the argument to adopt it: what about the maintenance hell of all that repeated code. Arguably if you use proper mocking or stubbing (especially mocking) you shouldn't have too much trouble with this, but wouldn't it be nice if there was a solution for this?

So what are the requirements:
  1. We want to get readable code (not requiring you to constantly switch source files or scroll)
  2. We want little writing effort (not repeating the same code snippet over and over)
Requirement 2. is covered by OO, AOP and friends, but they completely ruin 1. in certain scenarios (e.g. test code). To get 1. you will have to drop 2... NOT good enough!

I am a fan of wikis and as you might know many have a feature called templates that specifically targets these two requirements. How about template in code. Just add a template construct and let the IDE optionally show the actual code inline.

I like it.

Tuesday, March 25, 2008

My first mobile internet

I've just replaced my well over 4y old battle scarred Nokia 6100. It's not that it was really broken, but just that my definition of 'the basic necessities' has changed. Let me give an overview of the definition over the years:

In 1998 when I bought my first mobile phone:
  1. Be able to make a call
In 2004 when I got my third phone:
  1. Be able to make a call
  2. Be able to use sms
  3. Battery life at least 1 week/4h calling
In 2008:
  1. Be able to make a call
  2. Be able to use sms
  3. Be able to connect my laptop to internet
  4. Battery life 1 week

Now in 2008 I have a job that requires me to travel and I "need" to have internet at all times. I decided to do what operators have been blabbing about for 6 years now and combine my phone needs with my internet needs. We do have UMTS now so it should be OK, right? Right...

To put things into perspective I will just give some hints to how my 'basic' internet needs are pretty far advanced compared to my phone needs. I for example:
  • expect ANY website to render in under 0.5 seconds
  • routinely download files over 300M and don't expect to wait longer than it takes for me to get coffee.
  • store my complete life (contacts, documents, ...) online and don't expect to notice the difference.
So I got myself a unlimited data subscription and a UMTS capable phone (SE W660i if anyone cares). And I started connecting it to the internet.

Many geeks will look pitiful at my incompetence, but it took me 4 hours to get things working. Kudo's to http://www.taniwha.org.uk/ and the guys from SE for doing my providers and Apple's work for them. Funny that the guys that get the most money from me (Apple) are the least helpful in getting things to work properly. Ah well, I should have gotten an iphone, but that doesn't have umts... anyway, that's a whole different rant.

Now that everything works I am just curious at the speed I can get out of my new toys (http://text.dslreports.com):
40 kbit/sec
1.978s latency

Erm.. Those guys from telfort are really missing the point here I think. WTF!

When I made webpages last millennium the general rule was to keep images under 100k so that with this speed it would take me, say 20 seconds PER IMAGE to load the page.

I looked at http://www.umtsworld.com/technology/dataspeed.htm and the theoretical maximum is still pretty disappointing...

It's 2008 dammit, where is my flying car!

Tuesday, May 22, 2007

Comparing beans or why equality is subjective

In my project I use Hibernate and DWR so between my database and application I have to deal with Hibernate fiddling with my objects and between my client (browser) and application I have to deal with the DWR.

This all seems well and fine and generally it is. In fact kudos are in order.

However, there is no need to list all the key features again, you can just check the websites of the products for that. What I would like to describe is the fundamental problem of comparing objects that these frameworks do not solve.

The essence of the problem is that in a pure object oriented environment all objects have identity (== in Java) and when you go beyond the boundaries of your environment that law doesn't apply anymore. In other words: once
your application let's go of an object, that object is gone forever. To illustrate an example is appropriate.

Say in my application I have some simple user management. A User object can be persisted to the database and retrieved when a user logs in. The user can edit his profile (user properties) in the client and since I'm using Ajax i don't want the user to have to reload and redo his changes if I restart my application.

In real life each user is unique, so I expect the same from my application, database and client. Sounds simple, but it isn't. First let's have a look at the hibernate persistence layer. In the relational database there is no identity by default (it is impossible to distinguish two records with the exact same columns). This is easily fixed by adding a primary key to the table. Hibernate can do this for you. You just have to put some sort of Id property on your Pojo and tell Hibernate to use a sequence to fill in this property once the object is saved (eww).
Now there are three ways to obtain an object:
  1. create it yourself
  2. get it from hibernate
  3. get it from somewhere else (the client)
In the first case the Id will not be initialized (obviously, because Hibernate is in charge of that). In the second case the Id will definitely be initialized, otherwise the pk constraint would be violated. The third case is arbitrary. If the client got the object from the application in the first place there is a good chance that it has been saved before. In that case the client better keep track of the id. If the client is trying to create a new user there will not be an id.

Actually it is even a bit more complicated, as I might want to allow the application to pass objects to the client before they are saved. In this scenario the client and the application need to be able to negotiate identity between objects without polluting the id property that Hibernate needs to fill once the object gets saved. (If you get lost here it is probably a good idea to read up on Hibernate and the equals() method.)

Now take a note that I have been talking about identity and equality. Equality is the functional identity (i.e. two distinct objects in the jvm could be representing the same object from the users perspective).

If a user loads his User object in the client and after some changes he hits the save button, the application needs to be able to see that the existing User with a certain identity should be saved (resulting in a database update). You could establish this behavior with a smart implementation of the equals() method.

It is important to make a clear distinction between functional equality and technical identity. To illustrate suppose the application is a friends network. One user is logged in and updating his details. Another user is logged in and adding the first user to his network to do this he fills in the user form, the client sends the new user object to the application. The application needs to check if the user is equal to a known user to prevent duplication. Also there need to be two different instances of the first user. The identity of these user objects needs to be managed over the DWR pipes.

Now we have two objects in our application that are functionally equal, but technically distinct. This exposes the problem I'm trying to get at. Since the two objects are equal, but not identical either updates done in the first session do not show up in the second or you would have to constantly manage conflicting changes when either user saves the object.

Elegant solutions are most welcome.