Making mistakes is important to your growth as a developer. I like to say that software development is a series of errors and corrections (or problems and solutions, if you prefer). For me, I know that if I hadn’t made all the mistakes, I wouldn’t be the great developer I am.

Developers make mistakes; It has to be because we’re human. Making mistakes is a natural part of the development process. The real problem isn’t that we make mistakes — that’s inevitable. The problem is that sometimes our mistakes make their way to our customers and, at best, they are embarrassing and, at worst, they cost the business time and money.

What we need as developers are tools and techniques that help us catch errors before they happen. Fortunately, we can learn from the mistakes of others, and we have access to a wide range of techniques and practices that we can deploy as we go into production to mitigate the risk of mistakes up front.

In this article, we’ll look at various techniques that can help. Using a combination of these technologies gives us room for error, which in turn gives us room to learn and grow as developers. It also helps us detect errors early and minimize the risk of disruptive changes in production.

Personal Developer Techniques

I divide these techniques into two parts. First, we’ll cover things you can practice on your own, and then we’ll discuss things you can practice with your team. As you can see, there are many things you can do yourself to improve your development practices.

Iterative coding and small commits

This is something that every developer can do. When you write your code iteratively in small increments, you can test and commit each code change independently, taking small steps in the direction of your current overall plan. Small changes are easier to test and verify than big ones; They are also more likely to flinch when things go wrong.

When things get bad, you can safely reset your working copy. Although you will lose your current modifications, they won’t be too much because you only made small commits.

This technique is so important that it’s actually the most basic rule of my development philosophy: When you code in small, simple increments, you keep the code running. *

At the end of the day, a lot of small, well-tested code commits add up to a lot of new, working code.

Test code manually

Testing your code manually is a necessary but underrated part of development. Play with your code! Know what it really does, not just what you think it does. This is the best way to catch bugs before the code leaves your development machine.

You can test your code in your REPL, from the command line, or use your front-end; You can use the VS Code REST Client to test your REST apis and even create your own testing platform if you need to. There are many ways to test – just make sure you’re really testing your code.

Manual testing is a great starting point for both new and experienced developers who are building new products. Since automated testing involves a lot of costs, it’s generally a good idea to make sure your product is viable before investing in automated testing. Also, you need to do manual testing well before you can do automated testing well — how can you automate something you don’t know how to do?

Even if you have graduated from automated testing, you still need to return to manual testing from time to time. Not to mention that someone on your team is going to do manual testing anyway — if exploratory testing isn’t done, you won’t be able to find bugs that developers can’t imagine.

Set up your test environment

If you don’t have a fast and efficient test setup on your development machine, consider this the first thing you need to address in your development environment.

You’ll want to have a script or framework that you can get up and running and have your application ready for testing in a short amount of time — the sooner the better. The compose command in Docker is good for this, and even better, compose is now built into Docker.

You also need easy access to real-world data for any tests you plan to run. You need database fixtures, or test data sets, for different Settings of your application. These test data sets don’t have to be complicated — a set of JSON files will do the job. Then you need a script to quickly load data into your test database.

It is also important that you have a test environment that is similar to a customer-facing production environment. Your company should provide this for you — if they don’t, they can’t complain when software bugs show up in a real production environment.

You can also ensure that your development environment is configured to match the test and production environments, or as much as possible. Use Docker for this — it’s a great way to ensure that what works in development works in production, and for your teammates as well.

Code self-review

Self-review is something every developer should do, even if you’re doing peer review.

Reviewing your code before submitting it is probably the easiest way to find errors in your code before anyone else does. Self-review should be quick — assuming your submissions are small, it shouldn’t take long to review each one as you work.

Use the diff feature of your version control software to check your changes. Make sure you understand your code changes and why or why you are doing this commit. If you don’t understand, don’t submit yet. Take a moment to think about it.

Try explaining your code to an imaginary friend sitting next to you. Some people like to explain their code changes to a rubber duck.

Check your work before you let others check it. You might be surprised to find out how many mistakes you can preemptively catch through constant self-censorship.

Practice defensive coding

To deal with Murphy’s Law, we should practice defensive coding frequently. It is naive to think that our code will always work, and we should prepare for the worst. Our code throws unexpected exceptions (usually in production, when we don’t expect them), our apis are used incorrectly, and the input to our functions is garbage. Ultimately, anything that can go wrong does.

So, we should assume that things will go wrong and make sure our code handles it gracefully.

How can we find out? Through the…

Defensive testing

You should actively attack your code to determine how it reacts. Randomly add exceptions to your code and see what happens. Deliberately using your API in the wrong way. Pass garbage input to your function. Randomly burn servers — chaos engineering — to ensure that your distributed system is fault-tolerant.

When you know how your own code fails, you’re better able to handle such failures.

Automatic test

We’ve already covered how necessary it is to test our code every time we change it. Before each production release, we had to test the integration code from the entire development team.

Once you’ve learned how to test your code manually, why spend hours laboriously testing it manually when you can put it on automatic? There isn’t much code today that can’t be tested automatically. We can use taunting to isolate our code for unit testing, or we can reap real benefits through integration testing or end-to-end (E2E) testing.

Automated testing means that we can rerun our testing process at any time without having to invest our own time.

Admittedly, automated testing is a big investment. We need to be sure it’s a worthwhile investment before we go in, but for medium – to long-term projects, automated testing will most likely save you a lot of time and money — not to mention it may catch some embarrassing errors that would otherwise go into production.

Test-driven development

Test-driven development (TDD) takes automated testing and puts it front and center in the development process: our development is led by the testing process.

TDD achieves an amazing result that you may have to see for yourself to truly believe. It’s a shock when you try TDD for the first time and realize that your code works flawlessly the first time you run it. It’s rare for code to work correctly the first time — there are always problems — but with TDD, it’s quite normal for your code to work perfectly the first time, depending, of course, on the thoroughness and reliability of your tests!

Perhaps the most important thing about TDD is that it allows you to think about testing from the start, which helps you refine your ability to create code suitable for automated testing.

TDD changes you as a developer. Post-tdd developers write higher-quality, better-designed, and better-tested code. Even if post-TDD developers don’t do TDD, their code will have fewer errors, purely because they pay more attention to what they write.

Invest in your skills and development environment

The last thing you can do as an individual developer is to constantly and consistently invest time in improving your skills and upgrading your toolset. Always learning and improving. Always looking for tools and techniques to make a difference.

We are privileged to be developers in an era where we have access to a vast and growing tool ecosystem. We can choose from programming languages, frameworks, and software and testing tools. You need to understand what’s out there and how it can help you deliver more reliable code — so make sure you’re on top of the latest and greatest in the field.

Developer Team Technology

Now, let’s step up to the team level. In the following sections, we’ll review a series of techniques you can practice with your team.

Peer code review

Getting a new set of eyes on your code is a more important step than reviewing your own. The next time you’re ready to push code, ask your teammates to come and see your code changes. Review diff by DIff. Explain what you changed and why you changed it. If you are working remotely, submit a pull request and subject it to virtual review before accepting it.

Do this because your reviewers have a different perspective, and they may find bugs and defects in your code that you don’t — or can’t — imagine.

Peer code review is also a great way to promote communication and share learning experiences within your team. It can also improve your team’s ability to take criticism — though be careful to make sure it’s benign. Toxic and unconstructive criticism is not welcome and should not be.

Note that this is not to blame you for problems in your code. This is about getting the team to work together to improve the product and find those problems that might arise during production.

Branching strategy

A simple and robust branching strategy is easy to implement and can help isolate problematic code. You can also use branches to buffer customers from problems.

It doesn’t have to be complicated. I like to use the following branches: main, Test, and PROd. Creating these staging points means that your code must pass through multiple checkpoints before it can be applied to your customers.

Developers push code to Main, which means their code is often integrated. This helps avoid merge conflicts and ensures that development teams work together to integrate their code and fix any problems that occur.

This is the foundation of continuous integration, an important practice prior to continuous delivery, and the foundation of continuous delivery. When Main fails, it is the team’s responsibility to figure out what the problem is and fix it.

Assuming that the main branch is healthy when the function is ready, main is merged into Test. You can now do a lot of testing on Test before merging into PROD and forcing changes on customers.

Prioritize defects

Are you working on a code base that is already full of bugs and problems? Your focus should be on reducing the flaws you already have. A faulty code base or poor development environment can cause problems in and of itself, but it can also reduce developer motivation — which in turn increases the number of problems that go into production.

Before adding new features, focus first on fixing the worst existing bugs.

Of course, there’s a balance here — we have to keep adding new features to keep the business growing — but it’s a trade-off. With the right team structure, we can continually improve our code base to make it more reliable and resilient to failure while implementing new features.

Make sure you have a long-term vision for the health of your product. It may take a long period of persistence and sustained effort to deal with it effectively.

Pair programming

What do you do when you have a thorny problem that is proving difficult to solve? You ask someone to sit next to you and help you solve the problem. Pair programming takes this to the extreme: pairs of developers work together to solve problems side by side.

The benefit here is simple: two sets of eyes see more problems than one person. Pair programming helps developers find problems faster and more reliably, but it can also greatly improve and expand your experience. There is no faster way to improve your game as a developer than by working in pairs with someone more experienced.

Once you get into the rhythm of pair programming, error-free code becomes very smooth. It’s like a game of table tennis in which players collaborate to keep the ball in the air for as long as possible.

The agile “stop Line”

Agile development can be traced back to the roots of lean production introduced by Taiichi Ohn of Toyota. In his system, if any worker in the factory found any problems, they could stop production. The problems were then fixed and production restarted. They don’t tolerate any manufacturing mistakes.

As developers, we should do the same. Don’t tolerate problems with your continuous integration or continuous delivery systems. If these automation systems fail, the development team must stop working on other projects and focus on fixing them. These are early warning systems for problems and checkpoints at which code enters production. They are our last line of defense against the mistake of reaching the customer. Maintaining these systems should be a top priority for the team.

But — what happens when the problem is actually generalized into production? Should we try to fix them in production? That’s a hard no!

Gather evidence and document reconstructions as quickly as possible. Then, for the sake of your customers, roll back the disruptive changes to the previous working version to restore functionality as quickly as possible. Once the stress is gone, you can reproduce and fix the problem in a test environment or on a development computer, where it doesn’t bother the customer.

conclusion

Programmers make mistakes. Mistakes happen. This is a fact of development, but it doesn’t mean our customers should be affected. There are many ways to find — and then fix — problems early in the pipeline.

Since we can reasonably expect problems, we should always be looking for solutions.

Use the techniques outlined in this blog post to reduce the risk of errors all the way to production. Your development needs will be different, but you have a responsibility to keep your mistakes from happening to your users.

The postKeeping mistakes away from productionappeared first onLogRocket Blog.