Thursday, 21 May 2009

Tree-hugging hippy nonsense

I fear this may categorise me as some kind of freaking liberal communist hippy nutter, but genuinely I'm curious: Why isn't public transport free? Or, more accurately, is there any good reason why public transport shouldn't be free?

The obvious one, to my mind, is that not everyone uses it, so why should everyone pay for it. Except, you know, I'm not convinced that's actually true. Say you drive everywhere, and never use public transport. Your roads are kept clear(er) just because there are lots of other people that aren't driving on them. You're in effect using public transport to keep your motorway nice and quiet. Another issue, I guess, is that you'd have to raise taxes and that would make a government unelectable. Well, to begin with, what you do in government seems to have little to do with how electable you are. Manifesto promises seem made to be broken - and once you're in power, until the next election you can do whatever you like. Maybe I'm being too cynical there. But the argument that you'd need to raise taxes and that would therefore make you unpopular... I'm not sure I buy that either. Obviously, yes, you'd raise taxes. But we already pay for public transport. Due to the hilarious, incompetent and spectacularly wasteful way our railways are run, we as a nation frequently subsidise private rail operators that have failed to perform. Whilst still paying big salaries to their directors and, in some cases, even managing to be profitable enough to pay their owners dividends. On top of that, which comes directly from our taxes, we pay to use public transport. Does it really matter whether we pay our money to the tax man or to the transport companies? It comes from the same source and goes to the same sink. The route is irrelevant.

I understand that it's a bit of an extreme position, and as such I should at least propose some benefits. So here goes:

The big one is that right now we have the issue that having a car - and using a car - are for most people the primary mode of transport. Because it's convenient, and because (tellingly) public transport is often too expensive. Now, we're funding public transport as a society anyway. The benefit of having a public transport system is that it's relatively efficient, keeps the roads relatively quiet, has less potential for the spectacular number of accidents and fatalities, and is massively more efficient in terms of maintenance to the user. There's clearly a social benefit to having a decent public transport system - you get more people to work on time, more reliably (yes yes, if it's working well), and you no longer force people to be dependent upon the constant outlay of having a car, maintaining a car, fuelling a car, driving a car, and not crashing a car.

Now I'm not saying that we should outlaw cars or anything crazy like that. They're really handy. I'm just saying that - like with the NHS - surely the base level of transport that we expect society to have (because society relies on it) should be covered by the society as a whole. And once you take that step, why charge for it? Make it free at point of use, and you'll see usage increase. You have to pay for that, but what comes out of your taxes is no longer coming out of your pay packet when you want to go somewhere. You can keep paid upgrades to first class, that's fine. And if you really want to drive, you can pay extra and do that too.

But just because you want to drive a shiny car, that doesn't abrogate you of the responsibility to pay your social debt and fund the base level of transport. You're chosing to use something beyond the basics that society requires, so you should pay for that in addition to the basics, not instead of.

Wednesday, 6 May 2009

Look at the state of your code

Recently I've been working to re-implement an application from scratch. Not normally a sensible thing to do, but the codebase of the original was so far from being maintainable that you couldn't see maintainable from the highest point of the code on a clear day. With a telescope. Ostensibly the main reason it was such a mess is that as the application rolled out, there were an ever-increasing number of tweaks, special cases and optional extras which needed bolting into it. After a bit of thought, though, it seems to me that this is almost entirely not the case.

The root of the problem is that the code was never really designed before it was written. There were no pen-and-paper diagrams, whiteboard sketches or rough attempts at figuring out a structure prior to getting "stuck in" and hacking out code. It's a common mistake, it seems, that writing code is the important, difficult bit. It's really, really not. Figuring out how the code should hang together, that's the important bit. And as part of that figuring out both what the job you need it to do is, and what it might need to do in the future is. Now, obviously, you could take that too far - abstract enough and you just specify a thing that does something. Can't really design that, right? Well... sort of. But you know the special case of what it needs to do right now. Abstract all those things: If you need to be able to accept an input from an edit box before you fire the McGuffin that does your big cool number crunching task, then isn't it a good idea to make sure that you don't care where you get your data from? Yes, in this case it's an edit box, but why make life difficult for yourself in the future? You're going to get your data from something and in your first cut, that something will be an instance of an edit box. Next week it might be a piece of custom hardware. Design the way everything hangs together right, though, and aside from writing the code that details internally how you get data from the hardware, none of the rest of your code changes.

So far, so obvious. I'd hazard that no one really disagrees with that approach. But what really struck me with this project is how cool state machines are, for doing the above but with your business logic program flow. What you see in a lot of projects is a section of code that tells your system to do stuff - either the main loop, or the equivalent for the subsystem that you're looking at. Within it you'll often find a collection of conditional or a case statement. With the project we started with here, that had... I hesitate to say "grown"... mutated into a gigantic cascade of conditionals. Following what the hell was going was difficult, because there was no easy to reference concept of what the system thought it should be doing at any given point. It becomes difficult to add functionality, because checking what conditional statements are going to be executed is far from trivial. And on top of that, where do you sensibly add your code? Most likely as another conditional in the big list - making it even harder to get the next revision in. And because you've had to mess with the internal flow of the entire system, you've potentially destabilised what you had to begin with - even sections of the code you didn't think you changed.

So, here's an alternative approach: Let's abstract our central functional loop. It's going to take some data into it, sit there performing some function until it's done, return some data which determines what needs to be done next then pass whatever data it thinks might be useful out to the next iteration which will do the same thing. So what do we need to do this? Let's define a generic state object which will take care of Doing Stuff. We don't care what it does. We can give it access to a message queue so it can throw data out to non-state based components of the system (such as a GUI or some hardware), so there's no worries about it needing to have access to data that the central class shouldn't really relinquish - we can just pipe data out through the central controller class. Equally, we can pipe data in through the main controller loop. As much data as we like, and of any type. The state object can decide what to do with it, or junk it if it decides it's irrelevant. All we really need to define for the generic state is a HandleData() a Run() and a member variable to tell us when it's finished, and ready to move on to the next state - and, ideally, give us an idea of how this state finished. A binary works well here (success/fail), but you could use anything I guess, provided you can keep track of your state progressions. Now, we can define our states totally independently. Chaining them together into an application is just a case of defining a flow tree for the controller which tells it what state comes next for a given exit condition on the current state. You can define that in XML or whatever and parse it at runtime - no coding involved. The main control class becomes trivially simple - it just sits in a loop piping data into and out of the current state until it's told that the state is finished, then looks up the next state from the flow table and makes it current.

The neat thing about all this is that you inherently know what the system is doing all the time - it's just a state machine. You want to know what code is running when it's in a given state? The code in that state object. You don't have to figure out what conditionals are valid right now - just look at what that state does. You need to add functionality? Either change how the relevant state works if it's a simple change, or add a new state if you want the system to do something new. Then just update your flow table. Need to take something out? Just edit the flow table. You maintain tight encapsulation of your business logic the whole time, but at the same time get a very extensible framework. And because you're not modifying the existing code at all, you've drastically limited your ability to kark something up by mistake - you've got to either mess up your state flow table, or pass garbage into a state while at the same time managing to convince it that the garbage isn't garbage. A well-designed state object should be pretty resillient to this, and a well designed controller should do at least some amount of sanity checking of the state flows it loads to give you confidence that you are trying to run a system that has a chance of being stable.

Now, there's a downside to this: you pretty much have to stop and figure out what you're trying to do as a state machine, rather than hacking in some conditionals. Well, I say downside. Figuring out an actual state machine is probably a good idea in many cases - you've had to formalise what you want to do before you go ahead and try to do it.

Obviously, you don't always want to take this approach - if you're writing heavily optimised, time critical code then you maybe have other considerations to worry about. And no pattern is going to be right all the time, but I would hazard that unless you've got a good reason not to design your code using state machine architecture then it's probably a good idea to at least consider taking this approach. Especially if you know that you're going to need to add or modify functionality in the future - it really does make modification amusingly easy.