Newlines are free.

Avoid creating really long lines of code.

Many programming languages allow you to contain a frightening amount of logic in a single line of code. This can lead to very dense code that is hard to read. This style of writing has its origins in command line interpreters, a method of entering commands that predated visual editors.

While that may have been convenient fifty years ago, it causes problems for us today. One of the goals of your code should be to make as easy to read and understand as possible. Remember, when writing code, you are composing a message to future programmers that will try to communicate your intent. Thus, the clearer the message, the better.

It does not cost anything to add newlines to your code. Thus, one suggestion is to avoid making long chains of methods on a single line of code. Instead, it will be much easier to read if each method call is on its own line. (Also, long chains of method calls tend to create brittle, tightly coupled code.)

For many years, about 80 characters was the rule of thumb for the maximum length of a line of code. This was because many visual editors used terminals that rendered on a screen that was only 80 characters wide. With long, descriptive class, method, and argument names, it is easy to go past this size. Ultimately, if people have to scroll windows horizontally to see all the code, it will be more difficult to read and understand.

Kent Beck’s Rules of Simple Design, #4

The code must minimize the number of classes and methods.

YAGNI: You Aren’t Going to Need It. Don’t add features that weren’t explicitly requested. Write the code that satisfies the tests, and then stop.

Don’t overengineer solutions. Avoid having a complex network of a dozen microservices when one service can get the job done.

If you can remove code without violating the other rules, you should. While keeping the number of methods to a minimum, do not break the prior rules. You must still keep things dry, express intent, and pass all of the tests.

Deleted code has fewer bugs. If it doesn’t belong, get rid of it. Otherwise, someone will try to use it later.

Kent Beck’s Rules of Simple Design, #3

The code must contain no duplicate code.

Keep the codebase DRY: Don’t Repeat Yourself. Refactor out common code to its own subroutine.

Keep an eye on SPOT: Single Point of Truth. There should only be one place where any algorithm or equation exists. If you need to modify it later, you only need to change it in one place. Otherwise, you’re prone to have bugs where only some instances are updated.

Smaller methods and classes with repeated ideas should be extracted out to their own entities. Future changes only need to happen in one place.

Kent Beck’s Rules of Simple Design, #2

The code must express the intent of the programmers.

Choose good names. Variable, method, and class names should be obvious and clear. Don’t be afraid to have long names. Don’t re-use names.

Keep methods small. A reader should be able to tell at a glance what a method is doing and how it is doing it. Under ten lines is ideal.

Use standard nomenclature. Don’t use words that aren’t appropriate to the domain. Don’t use metaphors or similes. Say what you mean.

Never be cryptic or clever. Avoid complex algorithms and obfuscated code. Programming is not an intelligence contest. The easier it is to understand, the better the code will be.

Use comments appropriately. Comments should explain why, not what. If you can’t tell what the code is doing, then the code is too complicated.

Kent Beck’s Rules of Simple Design, #1

The code must run all the tests.

This makes refactoring safe. This is one of the most important things, as it allows future people to come in and alter or expand the code safely. One of the most common sources of bugs in codebases that aren’t covered by tests is to have a new feature unintentionally break existing functions.

The tests communicate the design. When the tests are written well, they lay out the plan of what code will be necessary to implement the feature.

The tests describe the desired behavior. Tests shouldn’t simply prove that a function does what it is supposed to do. They should be worded in such a way as to tell the reader what the desired behavior is.

The tests tell you when you are done. Don’t write code that isn’t needed to satisfy the tests. Don’t write code in anticipation of features that haven’t been requested. You aren’t going to need it (YAGNI).

Watch your body language.

How you express yourself affects how you are perceived.

The need for this skill is obviously reduced in these days where everyone is working remotely. Furthermore, many people don’t even use video when they are collaborating via Slack and other tools. Still, it is an important skill. And someday, eventually, you will likely have conversations in person again.

When you have interactions in person, or even via video, it is crucial to portray yourself with an air of confidence. There are many nonverbal cues that people will pick up when they watch you. This include how you stand or sit. Try to maintain excellent posture.

Also be very aware of your gestures. If you have none you may be perceived as limp or tired. On the other hand, if your hands are all over the place, you will appear unfocused and easily confused.

It is hard to monitor your bearing because you usually can’t see yourself. It can help to record yourself and study your own movements from a different angle. It also helps to have a friend who can give an honest analysis. Either way, making improvements to your bearing will benefit you down the road.

Learn from Occam’s Razor.

Among competing hypotheses, the one with the fewest assumptions should be selected.

This isn’t exactly a new idea. Actually, one could think of it as a 700 year old programming technique.

Consider two approaches. One method requires you to specify a lot of dependencies. Methods have over seven parameters. Complex machinations occur, requiring all of the objects to be “just so” in order to function. The class assumes that everything is perfect. Unfortunately, this class also has many reasons to change. When any of its dependent parts changes, the class needs to be rebuilt, possibly re-engineered. This makes the code rather fragile, leading to major support issues in the future.

In the second approach, classes and methods are kept small and simple. The number of dependencies is kept to a minimum. Since each method has only one job, it only has one reason to change. With fewer dependencies, the methods are easier to test.

Simpler is generally better. A class that makes fewer assumptions is more testable.

Use instrumentation.

Don’t try to optimize your application by guessing which part is slow.

Performance problems can be very frustrating. It is often unclear what the cause of the slowness is. If developers spend a lot of time and resources addressing the wrong aspect of the problem, they may find that the performance problem continues to exist. Thus, it is critical to determine what the real cause is.

The smarter move is to use instrumentation to find the cause. Leverage several different monitors to narrow down the cause. Use a profiler on the application and get real data.

The bottleneck may be in an unexpected place. The more data you collect, the more clues you will find, bringing you closer to solving the puzzle.

Beware Hofstadter’s Law.

It always takes longer than you expect, even when you take into account Hofstadter’s law.

Estimation is hard. You’re basically asked to predict the future. Somehow, you’re to predict everything that will go wrong, all of the hidden gaps in requirements, all of the surprises in the code, each unexpected system outage. Personal interruptions, illnesses, emergencies, surprise side projects, changes in priorities. Since no one can properly predict the future and all of these events that will impact your schedule, you are doomed to get it wrong.

Sadly, people tend to be optimistic and fail to take all of these things into account. If only there would be just an expected amount of interruptions, then they could deliver based on some kind of schedule. The real world is cruel seems to always add more surprises.

There are many things you can do to improve your estimation skills. Some of it comes with practice. Ultimately though, the best course is to get out of the business of predicting the future. It’s better to deal with more certain things.

Instead of estimation, turn your focus to delivery. Predictions are nice, but what people really want is delivery. After all, the desire for prediction is simply a question of “when”. When will they get what they want?

So, give them what they want. Deliver. Better yet, deliver often. Several small deliveries will be better received than occasional, late deliveries. And with frequent deliveries, they are much less likely to be late. This makes for a much happier client.

Don’t write flaky tests.

Stop chasing your tail with unreliable tests.

Tests that fail randomly are more trouble than they are worth. A suite might pass for you but then fail for someone else, giving you a harsh code review. Or worse, a failing test might pass long enough to get into production.

Tests should always pass or fail given one version of the code. There should never be tests that “sometimes” fail. You certainly wouldn’t accept a flaky specification, so demand that all tests are deterministic.

You need to be able to rely on the test suite with complete confidence. Otherwise, everything is going to slow down dramatically and your development costs will increase as well. Furthermore, without a reliable test suite, you’ll have to hire a department of quality assurance testers which will also slow things down and increase costs.

Hold the line. Refuse to accept flaky tests.