“Sexy girls”

One of the main project my company works on is analyzing mobile phone bills for companies – a company gives out mobile phones to all its employees, then they get a huge bill every month, often delivered by post and printed on (perhaps literally) many reams of paper.

We analyze all such files electronically. That’s what we do.

I was analyzing a new file format the other day, using live data from one customer. One service used by an employee is called “sexy girls”. Great stuff. I’m going to go out on a limb here, and assert that was some non-work-related stuff.

Outlandish newlines

A file recently turned up from an external partner. Our software was having problems parsing it. I opened it up in TextPad (text editor for Windows) and everything looked fine. Obviously I consider our software to be perfect so I was a little perplexed as how this file could be causing problems…

It turned out there were newline issues. Opening the file in a hex editor revealed the file used \n\n\r for newlines, i.e. 3 bytes.

I am amazed by (at least) the following facts:

  1. The fact that a file uses such newlines.
  2. The fact that any text editor can just open files using this newline scheme.

My PC’s door

pcToday I wanted to use some software i have on CD on a new computers. Obviously modern computers don’t have CD drives. One “mini PC” I have at one of my offices, however, does. My plan was, today, as I’m at this office, to use the CD drive to create an ISO of the disk. (It’s my computer, doesn’t belong to an employer.)

However, for some time, the “door” of my little mini PC has been stuck. It worked fine at my old office sektor5 (= i could open it to get to the CD drive) but it never worked at the new company hiQ. I’ve tried it a few times (to get to the reset button) but could never get it open, it seems stuck (in the case of the reset button i just turned it off and on then, using the main button which is outside the door).

Today, i decided, it’s only a PC, it’s only plastic. If it really doesn’t open then, well, I might as well force it and break the door if necessary. There’s no point having a nice-looking PC door, if it doesn’t work, and you can’t actually use the equipment inside.

So, basically, today I tried really hard to persuade it to open without breaking it, but it just wouldn’t open it. So i forced it, now the plastic broke, now i can use the CD drive, so in a way everything’s good.

I now realize that the problem was I was trying to open the door the wrong way; the hinge was on the other side. If only it’d occurred to me to try and open it the other way, I would still have a beautiful door, nothing would have been broken. I don’t know why this just didn’t occur to me at all.

Now my PC looks like shit with a broken door hanging off it, and all completely needlessly.

That makes me sad.

Recognizing URLs within plain text, and displaying them as clickable links in HTML, in Wicket

I have just, out of necessity for a customer project, written code which takes user-entered plain text, and creates out of that HTML with URLs marked up as clickable links.

Although marking up links in user-entered text is standard functionality, Stack Overflow would have you believe that it’s not something that should not be attempted, as it cannot be done perfectly. This is technically correct, however, users are accustomed to software which does a best-effort attempt, and customers are accustomed to take delivery of software meeting users expectations.

The software I have written is available as open-source, either as a Java class with the method encodeLinksToHtml which takes some plain text and returns safe HTML with clickable links, or as a component in the Wicket web framework called MultilineLabelWithClickableLinks.

Finding links within text is not as easy at it seems

Users may enter with/without protocol (http://). Domains may or may not have www at the start. There may or may not be a trailing slash. There may or may not be information after the URL. Having a whitelist of acceptable domain endings such as “.com” is a bad idea as the list is large and subject to change over time. Punctuation after links should not be included (for example “see foo.com.”, with a trailing dot which is not part of the URL)

The software matches “foo://foo.foo/foo”, where:

  • Protocol is optional
  • Domain must contain at least one dot
  • Last part is optional and can contain anything apart from space and trailing punctuation (= part of the sentence in which the link is embedded)

Quotes are not allowed because we don’t want <a href=”foo”> to have foo containing quotes (XSS).

Making links clickable is not as easy as it seems

Facts:

  • Conversion from plain text to HTML requires that entities such as “&” get replaced by “&amp;”.
  • Links such as “foo.com/a&b” need to get replaced by “<a href=’foo.com/a&b’>foo.com/a&amp;b</a>”. (“&” in URL needs to stay “&” in the href, but needs to become “&amp;” in the visible text part)

Therefore,

  • One cannot firstly replace entities and then markup links, as the links should contain unescaped “&” as opposed to “&amp;”.
  • One cannot firstly encode links and then replace entities as the angle brackets in the link’s “<a href..” would get replaced by “&lt;a href…” which the browser would not understand.

Therefore, the replacement of HTML entities, and the replacement of links, must be done in a single (complicated) pass, rather than two (simple) passes.

2 of 30

How would you diagnose the following bug?

  • A number of checkboxes representing user interests (Football? Music?); user can select/deselect their interests.
  • Software has worked well for years in production.
  • Suddenly intermittent reports start coming in that sometimes some checkboxes get unchecked by themselves.
  • You test live, you test on the test server, all is good.
    But the reports keep on trickling in, leading you to suspect that it isn’t just user foolishness (e.g. not understanding how to use a checkbox, which I wouldn’t normally put past users..)

This happened at Uboot around 2005.

I’ve forgotten how it came to pass that we fixed the bug. But the bug was this. Perhaps it sounds obvious once explained, but it was anything other than obvious at the time, especially given the fact it was completely unreproducable.

The software was coded in Perl5, and I hadn’t coded this particular screen myself. But, I had no reason to suspect that anything was wrong with the code, as, as I say, it had worked well live for years.

In Perl, “everything is a string”, apart from that, in fact, that’s not true at all. “everything appears to be a string; but might not be” describes the situation better. If you have a string “foo” then it’s stored as a string. If you have a string like “45″ then it’s stored as an integer internally and converted to/from a string as needed. If you have a string like “45.6″ then it’s stored as a double internally and converted to/from a string as needed. (Or it might be more complex than that, I’m not sure, perlnumber)

Supposedly this makes everything “easier” if you treat everything as a string. But I have no anger towards the junior developer who coded this screen who believed, as things appeared to be strings, things actually were stings. I mean, why wouldn’t you think that?

The checkboxes were stored in the software as a huge bit field. Perhaps this wasn’t the best representation, as that doesn’t scale (if you want to store 100 interests, you’re going to have to change the approach). But, that was the representation that had been chosen and, as I said, this had been online and worked well for years.

At some point, someone had decided to augment our 64-bit servers with some 32-bit servers. So you can imagine the rest. 2 out of 30 servers were 32-bit, 2 out of 30 clicks went to those servers, our dev server was the older 64-bit server, all our software had been developed on the old 64-bit servers. So 2 out of 30 clicks, all interests apart from 32 of then got lost.

Lesson learned (or not, as the lesson would have to be learnt by the programming language community): If things appear to be strings, make sure they actually are strings. Or, make sure it’s obvious that they’re not strings.

Had the software been written in Java, this couldn’t have happened as, independent of machine word size (32-bit or 64-bit) each Java numeric data type has a defined width, and is guaranteed to behave identically on any JVM implementation.

Time wasters

I was inspired by Paul Graham’s essay How to Lose Time and Money. In it, he talks about things that seem like work (they are not fun, you do them at the office) but which are actually a waste of time. Because they’re not so obviously a waste of time like sitting in front of the TV all day during a weekday, one needs to take extra care of them.

I’ve definitely had days when I might as well have sat in front of a TV all day—days at the end of which, if I asked myself what I got done that day, the answer would have been: basically, nothing. I feel bad after these days too, but nothing like as bad as I’d feel if I spent the whole day on the sofa watching TV. If I spent a whole day watching TV I’d feel like I was descending into perdition. But the same alarms don’t go off on the days when I get nothing done, because I’m doing stuff that seems, superficially, like real work. Dealing with email, for example. You do it sitting at a desk. It’s not fun. So it must be work.

I suspect, as an employee, as one gets paid anyway, one doesn’t take care of these things at all. I remember, at one employment, some mandatory software updates started installing themselves on my PC, that took one hour of my time when I couldn’t log in or do anything. It didn’t bother me much (in fact it was almost a good thing). But I’m not in that situation, I need to produce as much value for my customers per unit time as possible. Either so I can increase my rates as much as possible (as I am providing so much value), or so I can decrease them as much as possible (as I only need a certain amount of money per month to eat, and I can become cheaper than my competition.)

Incidentally, I sometimes think that sitting in front of the TV wouldn’t just be equivalent to time-wasting tasks, it might even be preferable. In front of the TV there’s a ceiling on how much money one can spend (a pizza or two..), at the office one might get the idea to invest in things like new equipment, new SaaS subscriptions sucking money from one every month, hire some employees, …

So here is my current list of things I waste time on, which I hereby resolve to waste less time on in 2014:

  • Context Switching—From one project to another, or from one technology to another. It always takes a certain time, perhaps 15 mins, to switch ones brain from one environment to another. That time doesn’t benefit society in any way.
  • Working at weekends—Superficially this seems to increase productivity per unit time (e.g. per week), but in fact one is then mentally tired for the rest of the week, leading to one Saturday’s work at the cost of multiple weekday’ work.
  • IT administration—My customer doesn’t care if I buy a new computer every 2 months or every 2 years. But each time a new piece of equipment comes in, it has to be chosen, ordered, unpacked, physically installed (e.g. monitor arm), if it’s a PC then software needs to be installed, WLAN password entered, etc. This is just lost time, it’s not productive.
  • Organizing office space—For example choosing offices, choosing and installing tables, worrying why the printer or router doesn’t work. (Thankfully this one I’ve got sorted out, I work out of co-working spaces such as sekor5, which costs money, but everything’s provided.)
  • Ownership of superfluous stuff—It took me some time to get someone to officially live in my old flatshare room. In this time I was paying the bills, the person who was living there was paying me, etc. It seemed like “work” in that I did it during work hours, it needed concentration and accuracy, it clearly needed to be done (otherwise the bills wouldn’t have been paid). But in fact this was just useless administration which didn’t yield me or any customer any benefit. The same case was true when I owned a car I didn’t really use, and had to service it, etc.
  • Multiple computers—Having installed SQL Server for one project on my work PC, I was off-site and wanted to do some work on my laptop, and found SQL Server wasn’t installed, so I had to download it, install it, configure it, etc. This is work nobody benefits from, which could have been avoided if I just had a single laptop which I also used in the office, or if I didn’t work off-site and thus didn’t have a laptop, or if I logged in to my work PC remotely, or did more stuff on the cloud, etc. It takes ages to install my Eclipse workspace, for example.
  • Re-installing computers—Same as multiple computers. I don’t really ever do this myself, but I know other people who do. (One colleague at one company decided to spend the whole day installing Linux. The boss sent an important email containing a task that was actually relevant to the business, and when he hadn’t done the task, he protested, “how could I have done it? I didn’t know about it, I was re-installing…”)
  • Slow computers—I generally think that I work as fast as my brain can go, which is generally slower than any piece of technology. However, when my laptop lost WLAN and had to be rebooted, I think I lost 40 minutes in total. One doesn’t notice it, one believes it’s necessary, but this time I timed it and realized, this is ridiculous, nobody is benefiting from this 40 minutes of my life. But again, it’s not fun, so it feels like work.
  • Multiple software branches—We made a branch of one of my customers software for a long-running project. We refactored just about everything. In Java with e.g. Eclipse this is easy to do. Rename a core method and then every usage of that method gets renamed automatically, maybe 5-10 usages per file. We had to continue to add features to the main branch though. Every time we merged, it was a nightmare due to so many methods having been renamed. Avoid long-running branches and refactoring in them; the customer has no benefit from this time expended. (And it’s definitely not fun…)
  • Status meetings—“Only one hour a week!” But there are only a certain number of hours in the week. If I have five projects, each requires a status meeting, and some of them are at random times e.g. in the afternoon, then soon the whole week is gone. It feels like work (the customer demands the meetings, after all) but the customer isn’t going to get the project finished any time soon, even if they don’t realize that. (More info from another great PG essay)
  • Pointless project management—Answering emails from customers such as “when will it be ready?” or from employees “what shall I do?”. Thanks to LiquidPlanner we now have that under control; there is a single place in the cloud all customers and employees can log in and answer these questions themselves without slowing me down, and incurring costs for the customer.
  • Invoicing, tax accountancy, etc.—As a business owner there is a certain amount of work I am required to do, which isn’t programming. Collecting my employees’ timesheets. Making invoices out of them. Sending them. Recording which ones are paid. Following up unpaid ones. Sending all my bank statements and associated documents to my accountant. I do this during work time and necessarily I must factor in this time when deciding how much to charge my clients when I actually do work. But the customer isn’t paying for anything which they really want. I need to streamline this process.
  • Travelling—Thinking I’ll go and see a friend and then just work from their location for a week or so. Flying, even a single hour of flight, basically takes the whole day, once you’ve packed, gone to the airport, flown, got your baggage, got to your friends’ place, etc. Not to mention planning the trip, communicating with the friend, buying the tickets (comparing prices in multiple browser tabs), printing off the boarding pass, potentially organizing somewhere to stay, a co-working space. And then you’re tired and might need one or two days to recover. Travelling is nice, but all of the above is a complete waste of time, in the sense it isn’t helping your business or your customers.

Successful project management with Liquid Planner

I was told recently there is a certain inflection point a company reaches when it gets to about two employees. I certainly experienced this inflection point this year, w.r.t. dealing with projects and tasks. I decided to implement LiquidPlanner around Q2/2013, and am very happy with the decision.

(Note: I am not affiliated with LiquidPlanner in any way, none of the links in this are affiliate links, this is my own impartial opinion.)

The Problems

  • I didn’t get the feeling the customers really knew what was going on in the projects. I would often be called upon to give status meetings, send email status updates, etc.
  • I didn’t get the feeling the employees really knew what was going on. I kept task lists on paper (had worked for me when I was working alone!). I would occasionally send these lists via email. This required time to do, and these emails would slowly get out-of-date, so it wasn’t obvious for the employee what to do.
  • It was difficult to answer questions such as “If Martin works less, what effect will that have on the launch date?”
  • Also questions like “if the web designer gets delayed, what effect does that have?” (Certain tasks must get delayed, but for tasks where screens have already been done, they can get moved forward)
  • “If we add a new feature, how will that impact the deadline?”
  • As a consequence of not being able to easily answer the above questions, this had the knock-on effect that decisions, which could only be taken after knowing this information, couldn’t be taken.
  • Despite the above, I spent a lot of time doing project management! (21% of my time in Jan, 36% in Feb, 40% in March)

The Solution

Clearly there is enough information on the LiquidPlanner homepage for those who are interested. And there are other features such as time-tracking and financial estimations of remaining work which I am not using. But here are the key points regarding how I use it.

  • One one view, as a project manager, you have a hierarchical list of tasks and you can set attributes of those tasks, write comments, estimate them, manage dependencies, assign them, and so on.
  • On another view, as a worker, you just see a flat list of all your open tasks, ordered by their priority, and you can just work through them, estimate them, assign them to someone else, comment upon them, etc.

Here are the points I think are necessary to my workflow, and which LiquidPlanner does better than its competition:

  • Task durations—Either the project manager or the worker themselves can estimate how long tasks will take. Some other systems simply have lists of tasks but without being able to enter durations, it’s not possible to ask questions such as “how long will the entire project take?”
  • Duration ranges—You can enter “this task will take between 8 hours and 12 hours”. These allow you to enter not just your estimation but also your uncertainty (will it take 1h-8h or 6h-7h?). This is combined using a statistical model to estimate the duration and uncertainty of the final project deadline. Only FogBugz and LiquidPlanner could do this as far as I could see.
  • Dependencies—It seems to me than any project I do has some dependencies: the front-end only once the back-end and the HTML is done, HTML only once the Photoshops are done, Photoshops only once the requirements are done. This needs to be modelled, so you can not only see what tasks are ahead of you, but which you can already start on now. To estimate the completion date, you need to know this information as well. Many systems don’t support this, such as trac and basecamp.
  • Critical Path analysis—I can select any task, and say “show me the critical path”. This takes into account what tasks an employee must complete before they can complete the given task, and also any dependencies to tasks which must be completed by other employees.
  • Tasks can be organized hierarchically—I always got annoyed by systems like “trac” which just had a flat list of tasks. Each time you looked at your tasks they seemed to be in a different order. I find hierarchically arranging the tasks in a tree-view much more convenient.
  • A living plan—At least at one of my customers, I go to their office, there is a huge multi-page MS Project Gantt chart on the wall. I’m sure they’re proud of this chart, I’m sure it took a long time to produce. I’m sure it “feels” like they’re doing good planning. But they’re not. This plan doesn’t get updated. It’s irrelevant as soon as it’s printed. A central cloud system gets updated as new tasks are found to be necessary (e.g. bugs), and as old tasks get done, perhaps faster or slower than they were initially estimtaed to take.
  • Update remaining hours (not % through task)—If you’re half way through as task, you can update the system with “I worked 4 hrs, I have 6-8 hrs to go”. I prefer this to saying you’re 50% through the task, which necessarily refers to the original estimate, which is almost certainly going to be out-of-date now that you know more, now that you’ve worked 50% of the task.
  • Online—I want to have a single place everyone can log in and see the state of the project. Thus I don’t need to compose emails telling everyone the current state, and the customer saves money by not having to pay me to do this. This discounts tools such as MS Project.
  • Part-time employees—I can enter the fact that most of my team work e.g. 30 hours or 10 hours a week. It takes this into account when predicting the end-date on projects based on the effort remaining.
  • Provides information, doesn’t take decisions—I know best who can do what, etc. It doesn’t provide any facility to “balance” work e.g. by re-assigning something from one employee to another.
  • Email notifications—This seems like an obvious win, and most task tracking systems, e.g. Redmine, offer the facility to inform people when things happen. However, there’s a big difference between doing this right, and doing this just mediocre. If a person updates a ticket a few times within a few minutes, Redmine sends individual emails, LP sends only one. If you alter something yourself, Redmine sends you an email about it anyway, LP does not. After one weekend I literally had 200 emails in my inbox (using Redmine), which doesn’t inspire one to read each one carefully.
  • Reply to email notifications—If you get an email from Redmine, and reply to it, it just gets lost. If you reply to an LP notification about a task, what you’ve written becomes a new comment in the task. This allows people who are “tool-averse” to still be part of the conversation.
  • @Mentions—If you are writing a comment on a task, maybe you want to mention someone. Simply refer to them as “@David” in the text and they’ll get an email. (As above, they can reply to the email and what they wrote will get added to the task as a comment.) In this way you can bring people into the conversation, and keep the knowledge in a system visible to the entire team, and away from individual inboxes.
  • No “priority” or “importance” field—I don’t like it when you have to say “this task is high priority”, “this task is medium priority”. Everyone uses those statii differently. (Or worse, when one has to enter both “priority” and “importance” fields! That difference is subtle, which everyone understands differently.) In LiquidPlanner there is just a big (hierarchical) list of work. The work higher up in the list gets done before the work lower down in the list. You are free to rearrange this order as you like.
  • No drag & drop of task bars in the Gantt chart view—Some tools allow you to take a task and drag it to the left to mean you’ll do it earlier. I don’t know why you’d want to do that. In LiquidPlanner you state the order of the tasks, and their estimates, and who will do them (and it knows how much that person works), and LiquidPlanner tells you when the task will get done.
  • Customer Portals—A customer of mine can log in and only see their projects, incl their tasks, deadlines and estimated completion. Nevertheless, my employees are shared between various customers (if Martin is working on X, he can’t be working on Y). The scheduling happens across all customers, however each customer sees the information relevant to them.
  • Not all task visible on the Customer Portals—A checkbox per task allows you to specify if this task should be visible on the Customer Portal. For example “Add new field” is something the customer cares about and understands. But “Investigate NullPointerException in log” is perhaps not.
  • Good employee onboarding—There is a nice 5-minute video which explains to employees how to use the “my work” section, perform estimates, and so on.
  • Convenient time tracking—On Redmine, to record hours, you enter a number into a text field. You are obliged to use Excel, or a piece of paper, to record when you start things, so you know how long you’ve taken. With LP you freely right-click on any task and click “start timer”. If you were working on another task, the timer for that task gets suspended. In this way tracking your time becomes effortless: no Excel needed.
  • Checklists—If a task comprises of many steps, it’s too “heavyweight” to create individual tasks for them. In LiquidPlanner each task has a list of checkable items. For example, I use these to record bugs I encounter as I’m developing a feature. In other tools I add “comments” with bulleted lists, but it’s difficult for other people to get an overview of what’s done and what’s still to do.
  • WYSIWYG editing—If a business guy is to create a task, I don’t want to explain a new markup syntax to them. Rich text boxes with buttons like “B” for bold have been around for 20-30 years. LiquidPlanner supports such a rich text box, other systems such as Redmine do not.

Conclusions after 9 months

LiquidPlanner has found good adoption by my team, and has solved all of the above pain points. It has excellent customer support. We are happy with it and continue to use it. However,

  • Expensive—At $29/month/user, which for my 3-5 users, quickly escalates to €100/month, and the months go by and suddenly you found you’ve paid €1k. If there’d been a piece of software offering a one-time license fee of €1k I would never have bought it; yet now I’ve paid more than that, and the total amount spent keeps on increaseing each month.
  • Some have not adopted it—Some customers, and people they manage, were unwilling to adopt LiquidPlanner. They prefer to work with other systems, and keep me out of the loop. As these have no estimation abilities, questions like “when will we be finished?”  cannot be answered. As long as I have no visibility into the tools I cannot manage the project (although it’s my job to do so.) This is a political problem, not one a product can solve: the customers don’t want to feel like they lose control. I don’t think LiquidPlanner, or any other tool, can solve this. As long as the customers wish to pay me for weekly meetings and writing emails about status, then I suppose I shouldn’t complain too much, even though they’re acting against their own interests.
  • No undo—If you make a mistake, you’ve got a manually revert it.
  • No VCS integration (git, Subversion, ..)—This is not a feature I have really ever used in competing project management systems but I know that other people do.
  • No Wiki etc—I know other solutions such as Redmine come with an integrated Wiki. Honestly I think such a thing has no place in a project management tool. One can just install a Wiki separately. But no doubt there are those who disagree, so it’s worth mentioning.
  • SaaS only—There is no option to download and install LiquidPlanner on your own servers. This might make it the wrong solution for sensitive data. I think that the NSA won’t gain access to many trade secrets by seeing my task list. But I know others disagree. FogBugz would be a good choice in that case.
  • Timesheets only record duration—When I bill customers I like to show start/end times of each piece of time I’m billing e.g. “2pm-4pm=2 hrs”. But LiquidPlanner only supports recording the number of hours done, not at what time they were done.
  • No collaboration on estimation—Someone (anyone) can update estimates of tasks. There is no facility to say “three people think it’ll take 5 hours, one person thinks it’ll take 1 hour, so the system determins it’ll most probably take 5 hours”.
  • No resource balancing—I am working with small teams of 3-10 people. I know who is the most appropriate worker for what task. (Workers can also claim work themselves, if I get it wrong.) However, working with 1,000 person teams, one would need a facility to say “I need 100 software developers, who are available, who ideally have this skillset”.

Business 2013

This is a report of business activities in 2013. (Similar to the report for last year, 2012).

My employee MartinL (software development) has remained with me for most of 2013, although returning to university in the latter half of the year. New employee DavidZ (software development) has joined.

I have been getting into outsourcing for a few years. Not for the obvious reason of reducing customer costs (that’s just a side-effect), but for the fact that good people in Vienna are often already engaged. I don’t want to have to tell my customers “We can do the project, but only in 6 months..” so I’ve had to look for other alternatives. We’ve had some good and bad experiences (as it to be expected), but now I have at least one person who delivers excellent quality and is very reliable.

I have diversified away from just software development into doing project management, requirements, photoshop and html, javascript. This has been made possible by my extended team.

I have also started to do basic websites, based on WordPress. This is not the most lucrative line of work, and I’m not sure if it’s a good direction to go in, but it seems to be what the market demands. And I don’t like to say “no” to customers :-)

A sadder note in 2013 is that I’ve started to use KSV (debt collection agency) to collect money from some of my customers. It seems there was a lot of unwillingness to pay by some of my customers (not all!). Henceforth I shall be taking a harder line; any customer with any debt will not be able to order new features at all (even if they are very persuasive salespeople).

We have taken the following software online for our customers 2013:

  • firstbird has been architected and programmed by myself and the team. This was a major undertaking, over 1.5k hours of effort. Companies can post job openings, Employees of the company can recommend people for the jobs. Companies can rate and hire candidates. Employees are kept in the loop all the time via feeds and various email notifications. Employees get points, monetary rewards and badges for their efforts. Information posted and captured from Facebook, XING, LinkedIn and Google Contacts. PDF CVs automatically generated from XING and LinkedIn information, etc.
  • mobilreport imports mobile phone bills and analyzes them. We have 40+ paying customers; big companies in Austria and Germany with large phone bills covering up to a few thousand employee mobile phones. We take the call log data from the mobile provider and parse them. Often these are very nasty formats, e.g. CSV files where certain cells contain unescaped “,” characters, i.e. parseable only by heuristics. The operators have no desire that you parse their data, apply learnings from it to save yourself money. So they’re not keen to fix such bugs. We now support the following formats: A1 AT (EGN and 2 Landline formats), COLT AT Landline, Telering AT, T-Mobile AT, T-Mobile DE (CSV and EDIFACT), Vodafone DE (EDIFACT).
  • For one major customer in Austria we extended mobilreport with the facility to calculate employee limits (i.e. employee gets a phone from the company, may use up to €20 per month, the rest gets deducted from their salary; bosses may use up to €100, various calls don’t count). They are informed about their limit exceedance via SMS.
  • mobilreport now has the facility for employees to log in and see the calls they’ve done with their company mobile phones. SSO from the company’s intranet to our system means the employee doesn’t have any extra passwords to remember.
  • Demonstration for a major Austrian vendor of a “command and control” center for police, with various projectors, controlled via iPads. A “game” was described in XML (firstly this scene, then if the user selects “send car” then this scene..), this is parsed on the iPad, commands sent via XML over HTTP to VLC instances connected to the projectors. Used web-technologies; written in GWT by MartinL and myself.
  • Extended a PHP system, back-end for an iPhone application for authorization and location tracking, with various pieces of new functionality (DavidZ)
  • Matchmatrix event site (alas the event was a failure so website was taken offline and I was never paid; case is with debt collection at the moment.)
  • Calendargrads website was implemented in WordPress for under €500 (logo was not done by us)

Jetty doesn’t show errors on web application start-up

From a certain version of the “jetty” package in Debian Linux, if the web application didn’t start up (servlet init() throws an Exception), this error wasn’t logged anywhere. The solution is to install the libjetty-extra package.

sudo apt-get install libjetty-extra

It took some amount of experimentation to find the solution. I don’t know why you’d ever want to not log errors; i.e. why the logging of errors is an “extra”.

Jetty is a Java web server, similar to Tomcat, it’s my server of choice. It’s simple, doesn’t seem to do much apart from run WARs, and (apart from this issue) I’ve rarely had any problems with it.

Wrapping IDs in objects

In Java, I like to wrap ID values in objects, rather than just passing them around the code as their native “int” or “long” or “String” values.

The reasons are twofold why using an object is better:

  • Code becomes more readable, for example foo(LoginId x) is more readable than foo(long x). (Although perhaps neither foo nor x are good names, so perhaps the example over-exaggerates this improvement.)
  • The compiler can do more checking. If you pass a job advert’s id (as a long) to a function expecting a login id (as a long), the compiler cannot warn you of your mistake. This becomes particularly relevant if you have a function taking two IDs and you pass them the wrong way around.

Things to consider when writing such an “ID object”

  • Do not allow the ID contained within the object to be null. Having “LoginId x” where x is not null, but the value contained within x is null, makes no sense. (For example, use primitive types if dealing with numerical IDs, as they cannot be null.)
  • If the ID is a string, don’t allow this string to be empty; same as above.
  • Implement equals and hashCode methods so that these IDs can be used within Sets, or as keys within Maps, or as keys in Wicket drop-downs, or wherever.
  • Make them serializable.
  • Make the ID attribute a “public final” attribute. That means useless getter methods can be avoided, from the object itself and from client code.
  • The object should have a single constructor which takes the value and sets it in the attribute.
  • Implement toString so that the debugger can display the object usefully.