There are plenty of learning resources on software best practices. Sprinkled in between all the well-intended advice are warnings about common pitfalls. We could do with a lot more of these warnings and think about why we keep doing the same things wrong. What makes anti-patterns so irresistible?
Stamping out bad habits
Many famous rockstars are self-taught and often received no formal music training at all. Not so in classical music. Any book that claims you can teach yourself to play the violin or become an operatic soprano without the aid of a tutor sells you a false promise. I must have paid my cello and singing teachers slightly more than I ever spent on university tuition fees (granted, these were only 700 euros a year in the Netherlands at the time). None of all this music teaching has brought me any monetary return on investment, whereas my programming hobby has paid out nicely. Sure, I must have consumed hundreds of books, blog posts and tutorials, and of course I wrote many thousands lines of code on hobby projects. However, all of this was largely unsupervised. I learned the most from working alongside more experienced programmers. These people didn’t only teach me new things, but most importantly they weaned me off some ingrained bad habits.
Education is as much about showing how to do things properly as it is about stamping out the bad habits that come natural but are nevertheless wrong. You really need a teacher to do the latter, especially for any pursuit that is more physical than intellectual, like sports and the arts.
Coding isn’t that much different. Yes, if you’re an experienced Java programmer you can teach yourself Kotlin, no problem. But when it comes to more generic principles you mustn’t assume that just knowing the right ways will always keep you on the straight and narrow.
Bad habits are not a popular subject
Here’s why diet books don’t work: they suggest that all it takes is pointing out what healthy foods you should eat. Yet we all know that staying away from the fattening junk is the really hard part. There’s no shortage of books on healthy coding practices. There’s the clean coder, the pragmatic programmer, the humble programmer. Frankly, I’ve heard quite enough success stories. Give me the book “how to avoid being a dysfunctional pedantic twit” or “We wasted everybody’s time, tens of millions of dollars and still have nothing to show for it”.
Code quality is as much an indicator of underlying personal attitudes and team dynamics as it is of developer proficienty. I believe that both good and bad patterns result from only a small number of positive and negative attitudes and behaviours. These are important markers for the success of a software project.
The hall of shame is no laughing matter
You can’t write great code if you’re an inexperienced programmer, but you can certainly always write bad code no matter your experience or IQ. Anti-patterns aren’t always committed by bad programmers but they’re always the result of unconscious bad habits.
The hall of shame is of course the daily WTF , where the most glaring incompetence is exposed to ridicule for the coding community, thankfully anonymous. What bothers me though is the implicit assumptions that we, the readers, know better and have nothing to gain from it but a chuckle. But anti-patterns are no joke. Just because you can avoid beginners mistakes doesn’t mean you’re immune to committing the really major cock-ups. I can warmly recommend Scott Rosenberg’s Dreaming in Code about the ill-fated Chandler project, which comprised some of the best programmers, hand-picked by none other than Mitch Kapor of Lotus fame. Chandler, you ask? Exactly.
My personal top 3 of good habits
Here’s my personal top three attitudes that are most instrumental to building quality software and teams:
- Pride of collective ownership.
Without this you will care less for your own quality and that contributed by others. Note that you can be be proud of a particularly clever bit of code, but that doesn’t count if it confuses your colleagues or conflicts with their code. So you need…
- an attitude of always wanting to help, really the same kind you can often find in family-run hotels or B&Bs, where nobody gives you the feeling that it’s just a job to them.
- Meanwhile you have to stay firm about quality and professional standards, Most software is written for the long term. Others will probably be working on it after you leave. You have to display good stewardship, which having an eye for the long term.
Especially points 2 and 3 can be at odds: it means having to say no more often. It means standing your ground ocassionally and insist that some things are non-negotiable.
I confess that all this is hard. Just put the above list of saintlike qualities in the negative and you get a sense of what we’re battling with on a daily basis. Unclear management commitment to a product’s roadmap kills the sense of collective ownership. This lack of commitment leads to indifference about quality, and there’s nothing more contagious than indifference. Code quality will suffer, and poor quality is a slippery slope. There’s just no fun if the best you can do is make things slightly less bad.
Self-centred attitudes on the other hand lead to a host of toxic effects within a team: it’s being overly confident about your own abilities, bragging, tunnel vision and envy. It’s a cliche that programmers are on average more communicatively inept, socially awkward, pedantic and self-centred, but it wouldn’t have become a cliche if there wasn’t a grain of truth nonetheless. Several grains actually. Maybe even enough to bake a small loaf.
The dangerous short term
The upside about these two team-killing attitudes is that they stand out to the good observer and you can act upon them. There is another category of bad habits that seem less destructive on the surface because they don’t do as much harm to team morale, but can be equally damaging to long-term product quality. I’m talking about being too focused on short term result and not looking back at lessons learned. We tend to do it because code is written today, to be shipped next week. We don’t exactly please our stakeholders if we delay the release to upgrade a few old libraries. So this never happens until these libraries are ancient, unsupported and a security vulnerability .
There’s a host of anti-patterns that come from bad housekeeping and not looking back: the boat anchor , the dead end , the Lava Flow , Continuous obsolescence . And what else but pride and tunnel vision could lay at the root of the Golden Hammer and intellectual violence ?
Vegetables and raw nuts
If clean code is vegetables and raw nuts, anti-patterns are hamburgers with coke and ice-cream. Their appeal is much like junk food: we’re drawn to it naturally. Sometimes we feel the need to impress others and sometimes some private concerns outweigh any code you’re working on at the moment so you just want it to work quickly and go home. The occasional anti-pattern becomes a problem if you’re unwilling to learn from your mistakes or ashamed to admit to them. I’ve made tons of mistakes. There aren’t many pieces of code I’ve written at any stage in my career that couldn’t have been improved at a later glance.
There are always people who are deliberately vicious and manipulative about taking the maximum amount of credit for the least amount of work. Rest assured: they tend to work in the financial industry and don’t wear a t-shirt to work.
Elegant delegates in Kotlin
Kotlin has given us some really killer features . Some are obviously useful (null safety), while others come with a warning, like operator overloading and extension functions. One such ‘handle-with-care’ feature is the language support for delegation...
15.11.2017 | 5 Minuten Lesezeit
Anti-patterns part 2: Coding is the biggest Golden Hammer of all
In my previous post I explained how software anti-patterns are symptoms of bad habits that can be endemic to entire teams. Today I want to talk about what is perhaps the most infamous of all: the Golden Hammer. Actually, it’s a collection of hammers...
9.10.2017 | 6 Minuten Lesezeit
The most useless knowledge of all
There are things a programmer needs to know, no excuses. There are things you can’t possibly all remember, so it’s fine to look them up when needed. There is the business domain the software touches on that you need to know. And then there’s knowing...
10.9.2017 | 5 Minuten Lesezeit
Not everything that is vital is also your core business
Large software projects have many vital concerns, such as authentication and authorization. Despite the wealth of available libraries in the Java ecosystem we seem to be re-inventing the wheel far too often. Keep the focus on the core business of your...
- Software architecture
16.8.2017 | 5 Minuten Lesezeit
In defence of pedantic tools
Outline We aim to please the customer at short notice and always overestimate our capacity to comprehend a system as it gets more complex. That’s a recipe for technical debt. The antidote to this psychological shortfall is more team discipline in writing...
- Agile methods
2.8.2017 | 7 Minuten Lesezeit
Mocks or the real thing? Tips for better unit testing
Recently I had to bone up on some of the new features in Mockito 2 and Powermock , though more out of necessity than from genuine curiosity. Powermock and Mockito 2 let you fake static methods, final classes and even constructor calls, but this has ...
- Agile methods
16.7.2017 | 8 Minuten Lesezeit
Essentialism for developers
Essentialism – the Disciplined Pursuit of Less by Greg McKeown is a book with an essential message: much of life is irrelevant distraction and we would all be happier and more productive if we learned to strive for less, but better. I encourage you ...
2.7.2017 | 8 Minuten Lesezeit
The vicious circle of bad test code and how to break it
SUMMARY Compared to the great advances in programming languages and tools, the day-to-day practice of how we actually code is messier than it should be. Especially for long running and complex products building things right is just as important as building...
- Agile methods
6.6.2017 | 9 Minuten Lesezeit
CRUD operations on Spring REST resources with Kotlin
In this practical, hands-on post I would like to share some of my experience in building REST services wih JSON and Spring(Boot) using Kotlin. All examples can be transferred to Java, and if you use the indispensable Lombok library it doesn’t even look...
2.4.2017 | 7 Minuten Lesezeit
Integration testing strategies for Spring Boot microservices part 2
This is the second part of my earlier post about strategies for integration-testing Spring Boot applications that consist of multiple (rest) services. You can find the accompanying sample application in my gitlab account: git clone firstname.lastname@example.org:jsprengers...
27.2.2017 | 8 Minuten Lesezeit
Integration testing strategies for Spring Boot microservices
SUMMARY: Unit tests are a necessary condition to clean code, but today’s convention-over-configuration frameworks like Spring Boot are often used to build applications consisting of multiple services. You need some way of ensuring that the parts are ...
13.2.2017 | 9 Minuten Lesezeit
Web frameworks and how to survive them
SUMMARY: Frameworks that help build the web apps of tomorrow must keep up with all powerful new technology there is on offer. At some point your application has to adapt, and that is never a painless process. You can avoid a total rewrite however if ...
12.1.2017 | 8 Minuten Lesezeit
Kotlin’s killer features
SUMMARY: Kotlin is a new JVM language fully interoperable with Java bytecode. It is clearly inspired by Scala, but has a different design philosophy, a much gentler learning curve and some really helpful features like null-safe types. The Importance ...
3.4.2016 | 10 Minuten Lesezeit
Caching de luxe with Spring and Guava
Summary We generally don’t optimize expensive operations in code until they create a bottleneck. In some of these cases you could benefit a lot from caching such data. The Spring solution is non-intrusive, highly configurable yet easy to set up, and ...
14.3.2016 | 13 Minuten Lesezeit
Sensible mutation testing: don’t go on a killing spree
This is a follow-up to my earlier post about mutation testing (MT). To recap: MT helps you ensure that your unit tests are any good. The framework manipulates your compiled code by inserting small changes (mutants). It then re-runs your tests and expects...
26.2.2016 | 6 Minuten Lesezeit
Mutation Testing: Watching the Watchmen
You can’t do without automated (unit) tests if you want to stay on top of the ever increasing complexity of software projects. A mutation testing framework ‘watches the watchmen’ by inserting small changes into your compiled byte code and then validating...
25.1.2016 | 7 Minuten Lesezeit
Dein Job bei codecentric?
Agile Developer & Consultant (w/d/m)
An allen Standorten
Gemeinsam bessere Projekte umsetzen
Wir helfen Deinem Unternehmen
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Do you still have questions? Just send me a message.