Archive for April, 2011
Robustness is one of the most important qualities of any application, is also one of the most difficult to achieve. What follows is a list of what in my opinion are the 10 principal characteristics to be considered when designing any robust application.
Having the right transactionality in your application is critical to guarantee the integrity of the data. No matter which framework you use to manage the transactions, is important that you consider making transactional the system calls that require ACID properties. Some key areas to look for:
- Transaction modes.
- Transaction frameworks and APIs.
2.- Database access.
Modern frameworks usually try to abstract the access to the underlying database of the application, while this is certainly good, is also causing an increasing lack of understanding of what is happening behind the scenes. Being able to explain what is the SQL likely to be executed by your framework, and when is going to be executed will help you to create better database access code, and to optimize the database access, specially if you don’t have a DBA in your project. Some key areas to look for:
- Lazy loading.
- ORM frameworks and APIs
Multithreading is the next big thing in software development, is been there now for ages, but with the new hardware architectures going multi-core, multithreading is emerging as the new must-know skill. It is also critical to acknowledge that your code is probably already running in a multithreading platform so you need to consider it to prevent your code to fail. Some key areas to look for:
- Stateless services
- Unmodifiable beans
- Race conditions
4.- Logging and auditing.
Logging and auditing are one of the most underrated qualities of an application, especially for server applications. Is easy to forget in development how useful a log is when the application has already been rolled into production. Some key areas to look for:
- Consistent identifiers. Try to use the same identifier in every log message so is easy to track one thread of execution.
- Consistent format: If you have to grep or quey your logs, you will appreciate using always the same format for your log messages.
- Completion: It should be possible to track an entire thread of execution from the log being able to see the main events.
5.- Exception management.
An exception that gets thrown out to the user level is usually a sign of a fragile application, a proper exception handling can make you application more robust. I already wrote an article with some basic considerations regarding exceptions.
Invariants are conditions that need to be kept across several data structures to guarantee the integrity of the logic of the application. There are several design techniques or language features, as encapsulation, generics, enums… to help keeping the invariants safe. Something so simple as changing a list of constants to an enum or encapsulating two attributes that need to change in synchronization can make a huge difference building a more robust application.
7.- Disabling/Enabling/Swapping services or modules.
Shit happens, so you better be ready, being able to disable a service, or a module, or being able to write a dummy implementation to overcome a temporary incident, accounting for this in development, may save your day.
8.- Ubiquity and low coupling.
Being able to run chunks of your application independently, and at any time, is a sign of good design, and can also help you recover for unforeseen errors.
9.- Self diagnosis.
One very valuable feature of any service call is to provide with self diagnosis on error, so the cause for the issue becomes obvious and it facilitates the search for a solution.
Any non trivial system requires documentation. Good documentation made available to the right people can save you from many errors.
What is important in an application?
In software development there are only three measurable areas that encapsulate all that is important in an application: Rentability, quality and maintainability.
||Ultimate goal of any application. Determines if the amount of time and resources spent in maintaining the application are worth.
Main responsibles: Business, sales, marketing.
||Measures how well an application does what is supposed to do.
Main responsibles: System administrators, DBA, developers, QA.
||Measures how long it takes and how much it cost to successfully deploy a change/new development from the change request until is available for use.
Main responsibles: Management, developers, QA.
From these metrics, is important to understand two things:
- Rentability is the most important metric. No rentability = failure.
- Quality and maintainability are only important because they have an impact in the rentability. They basically represent the cost of maintaining and fixing the application.
Some examples of these metrics would be:
- Bank legacy applications. Very high rentability, very high quality but very bad maintainability.
- Successful web start-ups. High rentability, low quality and good maintainability. New web-apps that manage to get a lot of attention, with a lot of bugs, but with a small core that is easy to change.
I find it quite interesting how many developers seem to ignore these three previous areas, the mission of any software developer should be: Increase the rentability of the application through the quality and maintainabilaty.
Is important to note how code is not mentioned. The code is not an end, is a mean. If what you are doing doesn’t improve the quality or the build process, then, don’t do it. This maybe interpreted as an attack against some programming techniques, in particular refactoring, but is not. Refactoring plays an important role in maintainability, as any other engineering practice, they serve a bigger purpose, and is not the code, is rentability.
Maximising the quality
Some of the main aspects of quality to look for are:
Correctness: Correctness is about expectations. A software feature is correct if it fulfils the expectations of the customer.
Traceability: Traceability is about being able to explain what happened in the application in the past and why it happened.
Supportability: Supportability is about how easy is to fix possible errors/corruptions in the application
Usability: Usability is about how good the overall user experience is on the application, is usually about performance, UI design…
Robustness: Robustness measures how gracefully the application handles edge cases.
Scalability: Scalability is the ability to handle growing amounts of work in a graceful manner
Improving the maintainability of the application
One of the main specific areas where developers can make a bigger difference is the build. Having a bad build process is one of the biggest productivity killers in software development. A build process comprehends all the stages a change goes through since a developer commits it until it reaches production, including all the QA and deploys activities. The output of a successful build is a set of new features that work as expected in production. Any build process has two main characteristics.
Reliability. The reliability of the build process is a measure on how frequently builds that were supposed to be successful turned out to have bugs, and how critical these bugs were.
Performance. Performance is a measure of how long it takes to make a build attempt.
But is worth remembering that a non reliable build is useless, no matter how fast it is.