Don’t forget this in your app!

This post will start with some handwaving and claim that the most costly errors you can do while developing your application are:

  • Forget about localization (they speak what language?).
  • This means, among others: translating the UI, formatting names, dates, numbers and currencies, and even outright horrifically complicated stuff like right-to-left languages.
  • Forget about permissions (the janitor needs to log in where?).
  • Forget about time zones (they live there?).

I am happy to say that realPad got 2 out of these 3 right from the beginning. That is, if you don’t count the way we store money as integers (that flat costs how many cents?!). That is, if you don’t count item 4: pick long for IDs instead of int!

We are currently working on time zone support, and it hurts a lot. Time for Captain Hindsight, then!

  • Always use the latest version of your tools. Java 8 has, finally, a competent system for dates and times. In older versions you had to use an external library, like Joda Time (we didn’t even do that).
  • Any string visible to the user must be localized. For example, Apple has some nice guidelines. To make it simple for the people who will actually translate the strings, you can deploy a system like Weblate. We have been using it for almost a year now, and it’s been mostly great.
  • Any number or date displayed to the users must be formatted according to the local conventions. You may want to split the language and numbers/dates locale setting: for example, my iPhone is set to English language but formats numbers and dates using the Slovak conventions.
  • Always use an arbitrary-precision numeric type to represent currency. For example, in Java it’s BigDecimal.
  • Regarding time zones: each user must have a preferred time zone stored. Then you just follow this SO wiki. Simple!

I wish I had something really useful to say about permissions. Anecdotal evidence will have to suffice.

Our first approach was role-based: there was a fixed list of ~5 roles, each user belonged to one of them. Each “business” method was annotated with the role it required, and a “User” object was passed around as one of the parameters. AspectJ provided a way to check whether the user has the required role, and that was it.

publicvoidfoo(User user){
// … stuff only admins can invoke

Problem was, this was not really extensible enough. Different customers needed the roles to behave differently, and it just couldn’t be done. So we went for another approach:

Now, we have a list of permissions. Each user has a set of permissions associated with her, and the methods still require a certain permission to work, and AspectJ still checks whether all is fine. To make things even more complicated, we added a “permission extension” mechanism to all this, and I might describe it in a later post.

publicvoidfoo(User user,@CustomerId customerId){
// … getting some data from the customer

In conclusion, there are mistakes that are simple to fix, and some that are not. Be lean, break fast, but these mistakes you better avoid!

Originally published at