During my trip to Corropoli for the phpDay 2010 I took six trains to cover a total of 1000 kilometers. During the waiting periods in the train stations, I got to observe how the system is built and I found out that it reflects some principles of (software) engineering I apply everyday, as well as some antipatterns I try to avoid like the plague.
- Information hiding: at the various stations there are printed timetables which contain the list of departures. You do not get to know from where a train comes and this leaves open the possibility for the operators to change a train's course minimizing the amount of timetables to reprint. The list of arrivals is managed in the same way.
- Decoupling: the track where the train will pass is usually decided dinamically, basing on the type of train and on the currently free tracks. If we were modelling this domain, we would have a Train object, with its own identification number, which is kept in associated to a Track object at a particular time. We have to check that when a Train is on a Track (business rule), no other train is scheduled to use that track until the first one leaves (big mess if it happens). The two classes can evolve independently.
- KISS principle: Minor stations have fewer trains to manage, and typically have only one or two tracks. These stations thus don't need an electronic panel that lists where the couple track/train nor personal to update it: the timetable is printed on public board with the track numbers hardcoded in it.
- Consistency: every FS ticket from the high speed Freccia Rossa's one (200 km/h) to the regional train ones has the same size and color; this is not to be taken for granted in Italy. Thanks to this consistency you can print the tickets in any station equipped with a standard automatic machine.
- Dumb user interface (this is NOT to strive for however): in Bologna I spent some time hacking a vending machine with a Japanese couple before discovering that the same button served both to release the entered change AND to make it fall into the machine, depending on how deep you press it. This interface is difficult to grasp the first time you see it and we can infer that crafting a good user experience is a problem that spans more fields than coding software.
The interesting point is that these concepts are not a specific property of a young discipline like software engineering, but are a trait of well-built system. In one of his books Uncle Bob takes cities as an example: they are a large-scale system with components such as utilities (electricity, water, gas) and services which have to work together. System Metaphor is the name of an Extreme Programming concept which talks about describing the architecture of a software system as a real world system, to instantly transmit knowledge about it by comparison.
Thus, we do not need to worry about software being so different from many real world metaphors, because the principles that drive the creation of software are actually quite similar to real world engineering ones.
Where is software different?
Many of the material world metaphor for the software creation process fail in some aspects:
- software as a poem: unfortunately the code beauty does not count much if does not have business value.
- Software as a crop: we are able to influence the growth of a project much more than if it was an agricultural product.
- Software as a building: software is versatile and its parts can be interchanged at any time, it does not have strictly separate design and implementation phases like architecture.
- Software as a motorcycle (inspired by Pirsig): software does not wear out by using it, only if you add bloat or does not stay in otuch with the users needs.
Of course when we write code we live in a very malleable world, and the agility of easily changing code lead to the birth of iterative development as we know it. It is quite difficult to change the walls of an house once you have set it up in the real world, while rewriting a component is almost always an option (it only takes time). We are asked to produce maintainable software, that can change easily thanks to the decoupling between its different moving parts: no one asks an architect or a civil engineer to build a house which rooms arrangement or height can change easily basing on feedback from the user: they have to gather feedback at design time.
This is more an issue with material world technology than a software engineering's one: the way software is used asks for agility due to maintenance being the higher the cost factor: (enterprise) software evolves in the years to follow the process of its users (ideally: if a manager buy a package and feed it to his employees, they have to evolve instead to match the software process.)
We have the opportunity to craft a better experience than the one related to material tools, but still software is viewed as something that should contain its costs in many countries and companies due to its peculiar immateriality and ease of transport and duplication. But there are movements, like the Craftsmanship Manifesto, which aim for raising the bar from putting together a wooden hut to building a skyscraper.
Feel free to add your thoughts: where do you think software engineering is different from real world engineering?