Ten books that shaped me as a software developer – Part II (Books 5 to 9)

In the first part of my answer (books 0 to 4), I highlighted five books that influenced my career as a software developer. The list is not ordered, so the next five books aren’t inferior or better than the first ones. Every book on the complete list made a significant contribution to my knowledge and work ethic.

Clean Code

If we were to choose the holy book of software development, we probably couldn’t agree on one or even a dozen titles. And that is a good thing, because there is no one true way of software development. Clean Code by Robert C. Martin would maybe show up in the late contenders. But if we were to choose the most preachy book of software development, well, I have a favorite. This book is so loud that you cannot ignore it. And it is so opinionated that you’re either nodding your head like a heavy metal fan or writhing in averseness. That’s a good thing, too. Because it forces you to think. Your immediate emotional answer needs support by rational arguments and this book will provide you with ample opportunity to gather arguments for your consent or rejection. What this book probably won’t do is leave you unaffected. When it came out in 2008, it was an instant classic. You could spice up any gathering of software developers by making a statement about this book, be it pro or contra. And even today, ten years later, I would say that even if the loudness is deafening, the clarity of the messages makes this book a worthwhile read for every software developer. My grief with it is foremost that for a book called “Clean Code”, some examples of actual code are quite dirty or even plain wrong. Read it with an active mind and it will be a cornerstone of your professional career. But be careful, it seems that currently printed instances have physical quality problems.

Growing Object-Oriented Software, Guided by Tests

Ever since Extreme Programming hit the (european) scene in 1999, I was curious about Test Driven Development (TDD). I tried automated testing and unit tests whenever I could, read books and later watched videos about the topic. But I never grokked it. It just didn’t work for me and I didn’t even know why. My most feared trap was the one-two-everything syndrome, where you write two simple tests and then have to implement the whole algorithm to fulfill the third test. It was always the third test that broke my rhythm. I tried to exchange experience with TDD practitioners, but their own examples were mostly trivial and my examples always led nowhere (for reference: Try a simple Game of Life in TDD style). I felt dumb and inadequate. When Robert C. Martin (the author of Clean Code) told the developer world that you are either “TDD or not professional” (read the original from 2007 behind this paywall or the reprise from 2014 here or, even better, watch this discussion from 2012), that didn’t make me feel exactly great, too. But imagine my surprise when I started to read a book by two authors I hadn’t heard much of before with a title that reveals its intent only after a comma: “Growing Object-Oriented Software, Guided by Tests” (henceforth called the GOOS book). The book spoke clearly to me. Every step was actionable, even more so, the book acted it out right before my eyes. It was as if Steve Freeman and Nat Pryce, the two authors, were sitting left and right at my table and discussing actual code with me. It didn’t help that I read this book during a summer beach holiday. The beach and even the sun didn’t see much of me that year. I was busy learning about Acceptance Test Driven Development (ATDD), ports and adapters and all the other great content in this book. And the best thing was: it wasn’t theoretical, the examples in the books could be followed one a line-to-line basis. My experience with this book was unique and still is. It’s the best book about actual software development that I’ve read. You might enjoy it, too.

Domain Driven Design

Some years after the GOOS experience, another summer beach holiday was due and as usual, I included a software development book in my luggage. “Domain Driven Design” by Eric Evans came out in 2003 and was praised by some and ignored by most, including me. It took me ten years to finally read it and when I did, it hit me hard. Since my early days as a programmer, I tried to build a meaningful data model with actual types for each program I developed. But it occurred to me that I did it half-heartedly all the time. It shouldn’t stop at a data model, it should be a complete domain model. And for that to work, you need to grok the domain. I review a lot of my code before that insight and always find it funny how I invested effort in my models but more often than not stayed in the technical realm. I cannot say that my programming has changed much from the book, as most concepts meandered through the community since 2003 and were picked up by me mostly under different names. But my software development approach has changed dramatically. I don’t start my thinking from the technical side anymore. And that helps with “business alignment” and all the other magic words that finally have real tangible benefit. And I can now pinpoint when that alignment loosens and employ counter-measures instead of ending up in a special case hell. The best thing was that this book doesn’t require a laptop so I got to sit on the beach that summer with the book in my hands and my head in the clouds. It might be old, but it’s still gold.

Clean Architecture

I anxiously waited for this book to be printed. Not because I pre-ordered, but because I held talks, workshops and lectures about the topic before the book was available. And I wanted to make sure that I’m not telling nonsense. But Robert C. Martin took his time and delayed the deadline month after month. Then, nearly a year later, the book reached the stores in late 2017. So I would have to wait for my winter holiday to read it. I couldn’t wait and began right away. The book is a slow burner and feels like a long introduction. By the time the central proposition is revealed (and yes, it reads like good unagitated spy thriller at times), you’ve probably already figured it out yourself. And that’s a good thing in my mind, because it feels as if it was your idea and Uncle Bob is just there to nod and congratulate you for your intellect. This book is so many times less preachy than “Clean Code”. If we compare spy thriller literature, this is a John le Carré while Clean Code would be an Ian Fleming (James Bond). “Clean Architecture” is not about programming, it talks about software architecture, a topic that I missed greatly in my early developer years. I liked this book so much I even wrote a full review about it.

The Inmates Are Running the Asylum

All the other books talk about different aspects of programming, software development or related technical topics. But what about a book that raises a simple question: “Why is IT technology so complicated?”. And gives the answer: “Because we want it this way.”. That’s actually true. In a world without most of the restrictions of the physical world, we were unable to build solutions that actually helped us and came up with machines and software that overwhelmed most people. It needed a whole new generation of “digital natives” until concepts like internal operation modes (e.g. insert vs. overwrite) were intuitively understood. Not because they became simpler, we were just used to the complexity. Alan Cooper described the problem and gave at least hints for solutions in 1999, nearly 20 years ago. That’s the timespan of a generation. This book made me think hard about the status quo I silently had accepted with technology. It just was like it was, what else could there be? If I reveal a tiny bit of different approaches I can think of now, I’m often confronted with incomprehension. Not because I’m particularly clever and everyone else is dumb, but because there seems to be no problem if you’ve grown accustomed to it. If you want to see some of the pain other (older) people feel when interacting with technology and software, read this book. It is an eye-opener to common problems no software developer ever had. It is the first step into the world of UX (user experience), where it’s not as important if the developer feels alright but if the user feels at least adequate. It might be a classic and feel a bit outdated and weak on the solution side, but to understand the problem properly is the first step to appreciate possible answers. And Alan Cooper didn’t stop there. Read his ongoing series “About Face” (current version: 4.0) for lots of solution ideas.

Epilogue

And that’s it. These are the ten books I recommend everybody who wants to read good books about software development. And just a few days ago, another student asked me if I’m seriously recommending twenty years old books about topics that change fundamentally every five years. I am serious. If you read just one book of this list and judge afterwards, you’ll see what I mean when I say that there are timeless topics even in an ever-changing field like software development. Maybe you want to begin with “Refactoring” and compare it to the second edition (Java vs. JavaScript). The underlying concepts stay the same, no matter the syntax.
I hope you enjoyed this list. And I hope the student who originally asked the question got his answer. Are there books you want to recommend? Drop a comment below or blog about them! The average software developer reads less than one book per year. Maybe our insistence can change that a bit.

How I met my coding style

One of my students recently asked a question that really stuck in my brain: “Where did you get your coding style from?”. The best part of the question was that I didn’t have an answer, until now. I care about coding style a lot and try to talk about it, too. Here are some coding style related blog posts to give you some examples:

Code squiggles were a crazy idea that really provided readability value even after the initial excitement was gone.

Readable code means that you can read the code out loud and it makes sense to (nearly) everyone.

The student wanted to know how to gather the experience to write readable, elegant or just plain crazy code. The answers he anticipated were books or “trial and error”. I’ve come to the conclusion that, while both sources provided enormous amounts of inspiration and knowledge, there’s another single vital ingredient that rounds up the mix: care.

The simple answer to the question is that I cared enough about coding style to gather some knowledge in this field. The more adequate answer is that a lot of factors helped me to improve my coding style.

Books with code examples

Early in my career, I was always looking for programming books with lots of code examples. This is a typical pattern for the novice and advanced beginner stages in the Dreyfus model of skill acquisition. I felt confident when I understood a piece of code and knew that I could produce something similar, given the proper amount of time.

It took a few years of exposure to actual real-life programming to discover that most code examples in books are rubbish. The code exists only as a “textbook example” for the given problem, it isn’t meant to be actually used outside the (often narrow) context. If you stick to copy&paste programming, your code will have the appeal of a patchwork clothing made out of rags. It might fulfill the requirement, but nothing more. You can’t learn style from programming books alone. This isn’t the fault of the books, by the way. Most programming books aren’t about style, but about programming or solving programmer’s problems.

There are a few precious exceptions from the general trend of bad code snippets. For example, Robert C. Martin’s “Clean Code” is a recent book with mostly well-done code listings. The best way to separate ugly code from nice one in books is to re-read them a few years later and try to improve the printed source code.

I encourage you to read as many books about programming as you can possibly handle. Even the bad ones will have an impact and inspire you in some way or the other. Books are like mentors, whereas good books are good mentors. Reading a programming book again after some time will show you how much knowledge you gained in the meantime and how much there’s still to be discovered.

Other people’s source code

The large amount of open source software available to be read in the original version is a gift to every programmer. You can dissect the source code of rock star programmers, scroll over the vast textual deserts of “enterprise code” or digest little gems of pure genius inside otherwise rather dull projects, all without additional cost except the time and attention you’re willing to invest.

When you reach a level of code reading when other people’s code “opens up” to you and you start to see the “deeper motives” or the “bigger picture”, whatever you call it, that’s a magical moment. Suddenly, you don’t read other people’s code, but other people’s minds as they lay out the fundamentals of their software. You’ll begin to read and understand code in larger and larger blocks and see structures that were right there before, but unbeknownst to you.

I doubt you can gain this ability by working with textbook examples, as they are restricted in scope by the very nature of limited print space and a specific topic. The one book that accomplishes something equivalent is “Growing Object-Oriented Software, Guided by Tests” by Steve Freeman and Nat Pryce. It’s a rare gem of truly holistic code examples mixed with the essence of many years of experience.

Other people

As beneficial as reading other people’s source code is, talking with them about it raises the whole experience to another level. If you can get in synch well enough to get past the initial buzzword bombing to show off your leetness, you can exchange coding experience worth many weeks in just a few minutes. And while you are talking with them, why not grab a notebook and type away your ideas?

Most programmers I’ve met, regardless of their skill level, could teach me something. And I’ve had several enlightening moments of novice programmers pointing out something or asking a question in a way that really inspired me. You’ll have to listen in order to learn, as painful or overwhelming as it may be sometimes.

Most people are very shy and insecure about their abilities. Encourage them to tell you more and show your interest in their work. Several noteworthy elements of my coding style were adopted late at night at a bar, when a fellow programmer finally had enough beer to brag about his code.

Own achievements

This one will hurt. Remember the times when you shouted out loud “what the f**k?” over some idiot’s source code? Let this idiot be yourself some months or a year ago. Read your own code. Refactor your own code. Rewrite your own code. It’s the same proceeding our brain performs when we dream at night: It rehashes old memories and experiences and lives through it again, in time lapse mode. As long as you don’t dream about programming (I’ve started to code in my dreams very early and it keeps getting more abstract over the time), the only way to rehash your old code it to live through it again by working with it again.

You’ll put many past achievements into perspective, remembering how proud you were and being embarrassed now. That’s part of the learning process and really shows your progress. Just be aware that today’s triumph will undergo the same transformation sooner or later.

Practice is a big part of gaining experience. And practicing means playing around, making errors, trying crazy new things and generally questioning everything you’ve learnt so far. Try to allocate as much practicing time as you can get (besides reading those books!) and really hone your skills. This works exceptionally well with other people, at a code camp, a code retreat, a hackathon, whatever you call it.

The right mindset

This is the secret ingredient to all the things listed above. Without the right mindset, everything in addition to your day-to-day work will appear like a chore. This doesn’t mean that you’ll have to sacrifice all your spare time to improve your coding style. It just means that you won’t mind reading a good book about programming at the weekend if you’re really enjoying it. You cannot learn this attitude from books or even blog posts, it’s a passion that you’ll have to develop on your own.

I can try to describe a big part of my passion: Nothing is good enough. There is never a “good enough”. I’m not falling into despair over it, it’s just an endless challenge for me. Tomorrow, I will be a little bit better than today. But even tomorrow, I’m not “good enough” and can still improve. Sometimes, my improvement rate is neglectable for a long time when suddenly an inspiration completely rearranges my (programming) world.

I made my last giant leaps in coding style when I deliberately avoided parts of my usual habits during programming and tried to focus on what I really wanted to do right now and how to express it in the best way possible (for me). The result was astonishing and humbling at the same time: there’s so much knowledge to gain, there’s so little I know. But yet, I keep getting better and that really makes me complete.

A tale of scrap metal code – Part III

In the first part of this tale about an examined software project, I described the initial situation and high-level observations about the project. The second part dove into the actual source code and pointed out what’s wrong on this level. This part will summarize everything and give some hints on how to avoid creating scrap metal code.

About the project

If you want to know more about the project, read the first part of this tale. In short, the project looked like a normal Java software, but unfolded into a nightmare, lacking basic requirements like tests, dependency management or continuity.

A summary of what went wrong

In short, the project failed in every respect except being reasonable functional and delivering business value to the customers. I will repeat this sentence soon, but let’s recall the worst parts again. The project had no tests. The project modularization was made redundant by circular dependencies and hardwired paths. No dependency management was in place, neither through the means of a build tool nor by manual means (like jar versions). The code was bloated and overly complex. The application’s data model was a widely distributed network of arbitrary collections with implicit connections via lookup keys. No effort was spent to grasp exception handling or multithreading. The cleverness was rather invested into wildcard usage of java’s reflection API capabilities. And when the cleverness of the developer was challenged, he resorted to code comments instead of making the code more accessible.

How can this be avoided?

First, you need to know exactly what it is you want to avoid. Let me repeat that the project was sold to happily paying customers who gained profit using it. Many software projects fail to deliver this utmost vital aspect of virtually every project. The problem with this project isn’t apparent yet, because it has a presence (and a past). It’s just that it has no future. I want to give some hints how to develop software projects with a future while still delivering business value to the customer.

Avoid the no-future trap

http://www.istockphoto.com/stock-photo-5407438-percent-blocks.phpThe most important thing to make a project future-proof is to restrain yourself from taking shortcuts that pay off now and need to be paid back later. You might want to believe that you don’t need to pay back your technical debts (the official term for these shortcuts) or that they will magically disappear sometimes, but both scenarios are quite unlikely. If your project has any chance to keep being alive over a prolonged amount of time, the technical debts will charge interest.

Of course you can take shortcuts to meet tight deadlines or fit into a small budget. This is called prototyping and it pays off in terms of availability (“time to market”) and scope (“trial version”). Just remember that a prototype isn’t meant for production. You definitely need the extra time and/or budget to fix the intentional shortcomings in the code. You won’t feel the difference right now (hey, it works, what else should it do?), but it will return with compound interest in a few years. The project in this tale was dead after three years. The technical debt had added up beyond being repairable.

Analyzing technical debts

It’s always easy to say that you should “do it right” in the first place. What could the developer for project at hands have done differently to be better off now?

1. Invest in automated tests

When I asked why the project has no tests at all, the developer replied that “it surely would be better to have tests, yet there was no time to write them“. This statement implies that tests take more time to write than they save acting as a guideline and a safety net. And it is probably true for every developer just starting to write tests. You will feel uncomfortable, your tests will be cumbersome and everything will slow down. Until you gain knowledge and experience in writing tests. It is an investment. It will pay off in the future, not right now. If you don’t start now, there will be no future payout. And even better: now your investment, not your debt, will accumulate interest. You might get used to writing tests and start being guided by them. They will mercilessly tell you when your anticipated solution is overly complex. And they will stay around and guard your code long after you forgot about it. Tests are a precaution, not an afterthought.

2. Review and refactor your code

The project has a line count of 80,000 lines of ugly code. I’m fairly confident that it can be reduced to 20,000 lines of code without losing any functionality. The code is written with the lowest possible granularity, with higher concepts lurking everywhere, waiting to be found and exposed. Of course, you cannot write correct, concise and considerate code on your first attempt. This is why you should revisit old code in a recurring manner. If you followed advice number one and brought your tests in place, you can apply every refactoring of the book’s catalog and still be sure that you rather fixed this part instead of breaking it. Constantly reviewing and refactoring your code has the additional advantage of a code base that gets more proficient alongside yourself. There are no “dark regions” (the code to never be read or touched again, because it hurts) if you light them up every now and then. This will additionally slow you down when you start out, but put you on afterburner when you realize that you can rescue any code from rotting by applying the refactoring super-powers that you gained through pratice. It’s an investment again, aiming at midterm return of investment.

3. Refrain from clever solutions

The project of this tale had several aspects that the developer thought were “clever”. The only thing with “clever” is that it’s a swearword in software programming. Remember the clever introduction of wildcard runtime classloading to provide a “plugin mechanism”? Pure poison if you ever wanted your API to be stable and documented, just like a plugin interface should be. Magic numbers throughout your code? Of course you are smart enough to handle this little extra obfuscation. Except when you aren’t. You aren’t sure how exception handling works? Be clever and just “empty catch Exception” everywhere the compiler points you to. In this project, the developer knew this couldn’t be the right solution. Yet, he never reviewed the code when he one day knew how to handle exceptions in a meaningful manner. Let me rest my case by stating that if you write your code as clever as you can handle it, you won’t be able to read it soon, as reading code is harder than writing it.

Summary

Over the course of this tale, you learned a lot about a failed project. In this article, I tried to give you some advice (in the form of three basic rules) on how this failure could probably have been avoided. Of course, the advice isn’t complete. There is much more you could do to improve yourself and your project. Perhaps the best self-training program for developer skills is the Clean Code Developer Initiative (it’s mostly german text yet, so here is an english blog post about it), based upon the book “Clean Code” by Robert C. Martin (Uncle Bob).

Invest in the future of your project and stay clean.

Follow-up to our Dev Brunch August 2010

Last Sunday , we held our Dev Brunch for August 2010. We had to meet early in August, as there will be a lot of holiday absence in the next weeks. The setting was more classical again, with a real brunch on a late sunday morning. We had a lot more registrations than finally attendees, but it was said this was caused by a proper birthday party the night before. Due to rainy weather, we stayed inside and discussed the topics listed below.

The Dev Brunch

If you want to know more about the meaning of the term “Dev Brunch” or how we implement it, have a look at the follow-up posting of the brunch in October 2009. We continue to allow presence over topics. Our topics for the brunch were:

  • Clean Code Developer Initiative – The Clean Code Developer movement uses colored wristbands to subsequentially focus on different aspects of principles and practices of a professional software developer. Despite the name, it’s a german group with german web sites. But everybody who read Uncle Bob’s “Clean Code” knows what the curriculum is about. The talk gave a general summary about the intiative and some firsthand experiences with following the rules. If you read the book or are interested in profound software development, give it a try.
  • Non-bare repositories in git – The distributed version control system git differentiates between “bare” and “non-bare” repositories. If you are a local developer, you’ll use the non-bare type. When two developers with similar non-bare repositories (e.g. of the same project) meet, they can’t easily share commits or patches with the “push” command. This is a consequence of the “push” not being the exact opposite of the “fetch” command. If you try to synchronize two non-bare git repositories with push commands, you’ll most likely fail. The only safe approach is to introduce an intermediate bare repository or a branch in on of the repositories that only gets used by extern users. Even the repository owner has to push to this branch then. We discussed the setup and consequences, which are small in a broader use case and sad for ad-hoc workgroups.

Retrospection of the brunch

The group of attendees was small and a bit hung over. This led to a brunch that lacked technical topics a bit but emphasized social and cultural topics that didn’t make it on the list above. A great brunch just before the holiday season.