Archive for March, 2010
Are you using too many technologies in your projects? The 7 anti-patterns for technologies, frameworks and other technicalities in software development.
One of the most recurrent and common mistakes in software development is to focus too much on technologies, frameworks, middleware and other technicalities. It is like forgetting that our mission is to produce killer applications, not to make sure we use the most powerful tools available.
The following are in my opinion the main 7 anti-patterns related with them.
Anti-pattern 1: Hiring people based on the amount of technologies they know.
Hiring people is one of the most clear and common situations where we let the technicalities drive our decisions, and it is also one of the most delicate. It is as if we only care about how many technologies the candidate knows, rather than looking for good coding or design skills, which are much more important.
Anti-pattern 2: Picking up technologies without knowing if they are necessary.
We have all probably been there. The project is about to start, and the first thing we do is list the technologies and frameworks we think may be suitable for the project. It is like creating a shopping list with all the products we fancy from the supermarket. In my opinion it is better to start as simple as possible, and add technologies and frameworks only when they are required or when they will make the developers life easier.
Anti-pattern 3: Overusing a technology.
“When you have a hammer, everything looks like a nail”. Imagine that it’s been decided that Spring is going to be used for dependency injection. Next think you know, Spring is used to create all the objects in the application, and the configuration file has thousands of lines of code.
Anti-pattern 4: Cover design flaws with technologies.
Performance comes to mind immediately when discussing this anti pattern. It is very common when performance is poor to blame and focus on the technologies involved, but in my experience, performance problems usually have their root cause on how the implementation was designed.
Anti-pattern 5: ALWAYS Prefer new technologies and frameworks to a plain approach.
There are some developers that if they find something that can be done with a new technology they automatically discard a plain approach, and that is not always good. It is worthwhile to remember that technologies, frameworks, middleware… come at a price to the project. They require maintenance, learning, support, configuration…
Anti-pattern 6: Prioritize extensibility when it is not necessary.
One of the most common reasons I have heard for using new fancy technologies is that they deliver an extreme degree of flexibility and configuration not achievable otherwise with a plain approach. While this may sound wonderful, it is also true that most of the time they were not necessary for the project, so using them will only increase the risk of over engineering the application.
Anti-pattern 7: MDT – Management driven technology.
This anti-pattern usually goes like this: Your manager reads a magazine/article which talks about a new super-duper technology, he gets all excited, the next day in the office he makes the announcement: “I’ve found the solution to all of our problems, from now on we are going to use ________ !!” (fill in the gap, with the fancy technology of your choice)
After several years developing software, I have acquired a very a strong opinion on how software should be developed, I actually have come to the conclusion that everything boils down to 10 principles, that if well implemented, will make any software development successful.
1.- Customer first.
“If we don’t take care of the customer… somebody else will.”
Customer first means focusing from a customer perspective on real value for the product being developed, other aspects as: contracts, requirements, technologies… should take a secondary role in the project.
Not focusing on the customer in one the top 5 five non technical mistakes made by programmers.
2.- Code quality.
Even though code quality is something very subjective, (all code is crap), it drives many important aspects as: how hard is to maintain the application or how hard is to take on board a new developer.
In my opinion, the main indicators for code quality are: simplicity, readability, robustness and testability. Other qualities as performance or extensibility, if not required, will over engineer your application.
People are the most valued resource in software development, not the technologies. They are the ones that make the difference between a mediocre product and an excellent product, but they need to be empowered
Empowerment is the process where people is encouraged to be proactive and take decisions. Some of the most effective mechanisms to empower are: coaching, pairing or delegating.
There is an excellent article from Tony Morgan explaining the difference between a classic delegation approach and empowerment.
4.- Continuous integration.
Integration is, from my experience, a major issue in software development. Waiting to integrate at the end of the project or after a big chunk of functionality is completed, is always a traumatic process.
Continuous integration is the process that guarantees that every piece of code committed is automatically integrated in the system. Remember that continuous integration goes beyond continuous compilation.
This article from Martin Fowler, is one of the best references online about continuous integration.
Iterations provide continuous feedback. Continuous feedback is important because it reduces the amount of uncertainty in software development.
While iterations are usually only related to agile methodologies, it is important to remember that there are other methodologies as RUP which also use iterations and they are not part of the agile family.
6.- Automated testing.
Allows refactoring and iterations, provides confidence and if well implemented, enhances the correctness of the final product. To automate tests you may consider some facts about testing and some advices on how to write a good test suite.
No matter how much care you put on coding, on your first attempt, you are going to be wrong. Refactoring is the practice by which we keep changing the code to meet the changes necessary to introduce in the system.
8.- Informal architecture.
Big design upfront (BDUF), unless you are NASA and can expend 50-60% percent of your project time on it, is a complete waste, but so it is coding without any preparation. Informal architecture is a compromise solution where architecture is discussed in an ongoing basics and is persisted in light documents, boards or similar.
Software development is ONLY about communication. The customer explains to the software development team what he wants to accomplish so that the software development team can explain it through code to a computer.
10.- Avoid waste.
Waste accounts is one of the major productivity killers in software development: unnecesary meetings, unnecessary requirements, unnecesary process, unnecesary documentation, being some of the most common and dangerous.
From among all the qualities that make good code, robustness is one of my favourites. Robustness can be explained as a measure of how hard is to break someone’s code. The opposite of robust code is fragile code; an example of fragile code would be having a class with all its member variables marked as public.
My concern with robustness is that is usually overlooked, is not placed as a priority for some developers, which in my opinion is a mistake. The main problem with fragile code, is that for its correct behaviour, it depends on how the code is being used, and that, in my experience, is synonym of bugs.
The benefits of having robust code are many, some of the most important ones are:
- Easy to change. Robust code is easier to change because external factors don’t affect its behaviour .
- Less bugs. The more robust the code is, the less combinations that cause a bug in the code.
- Better integration. Robust code is predictable, so from an integrator point view, is always going to have the same behavior.
- Consistency. Repeat this with me “Robust code, works fine no matter who, when or how it gets called”.
To help spot fragile code here there is a list of common fragile code patterns.
- Public getters / setters / fields.
- Bad equals / hashCode / compareTo methods.
- Code duplication.
- Use of plain constants when an enum should be used.
- Not providing with any factory or build pattern for complex objects.
- Dependency on global variables.
- Coding against implementations and not interfaces.
One of the things that upsets me from modern frameworks is that they push you to create non robust code, they sometimes force you to have default constructors, getters and setters for all instance variables… but there’s no much we can do about it, and sometimes the advantage of using them is worth the hacking, but, from my point of view, fragile code shouldn’t be accepted in any other scenario.
Test code deserves a special mention. Test code is usually seen as not as important as production code, and this causes lots of developers to write very fragile tests. I am sure that anyone who has work in a large project using automated tests will absolutely agree with me that there is nothing more tedious than changing 10 lines of test code for each line of production code that changes, and that can be prevented with robust test code. So when writing test codes, please keep in mind that you have to care for it just as much as if was production code!!!
Find in this article the 10 characteristics of a robust application/service.