I read a few technical specifications every week from our current and potential clients, and there's one thing I can't take anymore; I have to write about it: 99 percent of the documents I'm reading don't have glossaries, and because of that, they are very difficult to read and digest. Even when they do have glossaries, their definitions of terms are very vague and ambiguous. Why is this happening? Don't we understand the importance of a common vocabulary for any software project? I'm not sure what the causes are, but this is what a software architect should do when he or she starts a project—create a glossary.
Manager. Controller. Helper. Handler. Writer. Reader. Converter. Validator. Router. Dispatcher. Observer. Listener. Sorter. Encoder. Decoder. This is the class names hall of shame. Have you seen them in your code? In open source libraries you're using? In pattern books? They are all wrong. What do they have in common? They all end in "-er." And what's wrong with that? They are not classes, and the objects they instantiate are not objects. Instead, they are collections of procedures pretending to be classes.
There are plenty of books, articles, and blog posts about team morale. They will all suggest you do things like regular celebrations, team events, free lunches, pet-friendly offices, coffee machines, birthday presents, etc. All of these are instruments of concealed enslaving. These traditional techniques turn employees into speechless monkeys, programming under the influence of Prozac. Their existence and popularity is our big misfortune. Let me present my own vision of how team morale can be boosted on a software team—a team that has a good project manager.
The decorator pattern is my favorite among all other patterns I'm aware of. It is a very simple and yet very powerful mechanism to make your code highly cohesive and loosely coupled. However, I believe decorators are not used often enough. They should be everywhere, but they are not. The biggest advantage we get from decorators is that they make our code composable. That's why the title of this post is composable decorators. Unfortunately, instead of decorators, we often use imperative utility methods, which make our code procedural rather than object-oriented.
I received a haircut today, and the niceness of my hairdresser led him to fill the appointment with courteous questions about how I wanted my hair cut, what size of clipper he should use, how long the sides should be, and how much should be removed from the front. He also offered me many types of shampoo and a cup of tea. All this reminded me of the work we do as programmers, and I decided to write a short post about it. I've already mentioned before that trying to make a customer happy is a false objective. This hairdresser was a perfect illustrative example of this very mistake. By the way, in the end, I wasn't happy, and he got no tip. How could this happen if he was so friendly and nice?
I was recently accused of being against functional programming because I call utility classes an anti-pattern. That's absolutely wrong! Well, I do consider them a terrible anti-pattern, but they have nothing to do with functional programming. I believe there are two basic reasons why. First, functional programming is declarative, while utility class methods are imperative. Second, functional programming is based on lambda calculus, where a function can be assigned to a variable. Utility class methods are not functions in this sense. I'll decode these statements in a minute.
In Java, there are basically two valid alternatives to these ugly utility classes aggressively promoted by Guava, Apache Commons, and others. The first one is the use of traditional classes, and the second one is Java 8 lambda. Now let's see why utility classes are not even close to functional programming and where this misconception is coming from.
At teamed.io, we work in distributed teams and keep all our communications in tickets. Besides that, we encourage every developer on every project to report bugs whenever he or she finds them. We even pay for each bug found. Once in a while, I see bugs reported along these lines: "Can someone explain to me how to design this module?" or even "I haven't used this library before; please help me get started." My usual answer is, "This is not a school; nobody is going to teach you here!" I realize this sounds rather harsh to most developers who are just starting to work with us, so here I'll try to illustrate why such an attitude makes sense and is beneficial to both the programmers and the project.
Disclaimer: I'm talking about software projects here, which PMBOK defines as "temporary endeavors undertaken to create unique products, services, or results." If your team is engaged in continuous development or maintenance of software, this concept may not be relevant.
First, no matter what the methodology is, we all write software for our users (a.k.a. customers, project sponsors, end users, or clients). Second, no matter what the methodology is, we write incrementally, releasing features and bug fixes one by one. Maybe I'm saying something absolutely obvious here, but it's important to remember that each new version should first of all satisfy the needs of the user, not of us programmers. In other words, the way we decompose a big task into smaller pieces should be user-targeted, and that's why you always work top down. Let's see what I mean through a practical example.
Code reviews (a.k.a. peer reviews) must be a mandatory practice for every serious software development team. I hope there is no debate about this. Some do pre-merge code reviews, protecting their master/development branch from accidental mistakes. Others do post-merge regular reviews to discover bugs and inconsistencies after they are introduced by their authors. Some even do both, reviewing before merges and regularly after. Code reviews are very similar to a white-box testing technique where a tester looks for defects with full access to the sources of the software. In either case, a code review is a great instrument to increase quality and boost team motivation.
However, it's not so simple to do them right. I would even say it's very easy and comfortable to do them wrong. Most code reviews and reviewers I've seen make similar mistakes. That's why I decided to summarize the four basic principles of a good reviewer as I see them. Hopefully you find them helpful.
Maven is a build automation tool mostly for Java projects. It's a great tool, but it has one important drawback that has motivated the creation of similar tools, like Gradle and SBT. That weakness is its verbosity of configuration. Maven gets all project build parameters from pom.xml, an XML file that can get very long. I've seen POM files of 3,000-plus lines. Taking into account 1) recent DSL buzz and 2) fear of XML, it's only logical that many people don't like Maven because of its pom.xml verbosity.
But even if you're an XML fan who enjoys its strictness and elegance (like myself), you won't like the necessity to repeat yourself in pom.xml for every project. If you're working on multiple projects, code duplication will be enormous. An average Java web app uses a few dozen standard Maven plugins and almost the same number of pretty common dependencies, like JUnit, Apache Commons, Log4J, Mockito, etc. All of them have their versions and configurations, which have to be specified if you want to keep the project stable and avoid Maven warnings. Thus, once a new version of a plugin is released, you have to go through all pom.xml files in the projects you're working on and update it there. You obviously understand what code duplication means. It's a disaster. However, there is a solution.