You are here

How one year in DevOps changed my life as a developer

public://pictures/2688fbe.jpg
Noam Kachko, Software Engineer, HP

I've been a developer for eight years. It's what I love to do. My team works on a DevOps product for developers and QA that leverages Jenkins CI for test automation. Jenkins is a complex tool, so I'm also working on a feature that offers a simpler view of how Jenkins works. In this way, developers, QA, and automation engineers can use it to run code on different configurations that simulate our continuous integration (CI) environments without too much bother.

While I love what I do, I also love to try new things. A few years ago, our DevOps team needed new infrastructure. I happened to be at the right place at the right time and was given the opportunity to transfer over to the DevOps team and take charge of the project. I ended up spending a year learning about Jenkins, Git, Maven, and other tools that the DevOps staff work with every day. I learned to respect the DevOps view of large organizations and how important and difficult it is to maintain the quality of a large product that is being developed by many groups and teams. My DevOps experience completely changed how I approach software development.

Here are five things I now do differently as a result:

The Journey to Enterprise‐Scale DevOps: Becoming DevOps Determined

1. Think "automation"

I used to happily commit code once it had passed a prescribed set of unit tests on my machine. Today, I have a much wider view of the processes that kick into gear when I do a "commit." Before I hit "Enter," I ask myself, "How will QA write automation tests for this code? How will it run and be tested in our CI environment? Who else needs to run this code? How easy is it to reproduce the right environment to test it?"

You might call this test-driven design (TDD), but it basically boils down to the understanding that I develop code in an environment that is merely one of the many configurations in which my code must run. Here's a concrete example: when something fails in the CI environment, it's helpful for the developer debugging it to reproduce the environment where the defect was detected. The problem is that this is very difficult to do. Without the right knowledge, building the environment can take longer than fixing the defect.

To overcome this, using the knowledge of Maven that I gained during that year in DevOps, I wrote a script that would build an environment that mimics the CI server's environment for any developer who needs to debug my code. With my script handy, the developer can focus on fixing the defect rather than fiddling with the environment.

2. Write tests for continuous integration (CI)

Tests that pass on a developer's machine often fail when running on the CI server. My experience with DevOps has taught me to consider the differences between my own machine and the CI server when running tests before I commit my code. For example, when I test a piece of code on my machine, that's all I do, but when a CI server goes into action, it may run many processes simultaneously.

This extra load may cause delays as different processes get shifted in and out of context. It's exactly this kind of timing variation that exposes bugs in untested corners of your code. To simulate these specific timing delays, I run tests through a proxy that artificially introduces delays similar to those the CI server may encounter. This exposes more real-life scenarios of our CI environment and enables me to write more robust tests.

[ Report: Gartner Magic Quadrant for Software Test Automation ]

3. Log messages wisely and connect the stack trace to Git

Before DevOps, I used to spew out messages to log files for nearly every line of code I wrote. I found that helpful when trying to debug my own code. But let's take a step back and look at the bigger picture of a CI server that builds code committed by many developers. If every developer does what I did, the log files will eventually become completely unmanageable. The developer who wrote code that broke a nightly build may not necessarily be the one who has to debug it. If the log is filled with a load of useless messages, it's going to be much harder to analyze and deduce where the problem lies. The answer is to log useful messages in strategic places in the code. Relevant messages mean less noise, which means quicker fixes.

Another useful method to use with log files is to connect the stack trace to files committed on your source control. A stack trace indicates the exact point where the code failed. Linking each class in the stack trace to its corresponding file in source control exposes which developer last modified the code and is therefore familiar with the change that broke the build.

4. Get "concurrency aware"

In our early DevOps days, life was relatively simple. Our CI server ran a series of tests on a single server, then shut down. If anything went wrong, it was easy to ferret out where the problem laid. Today, we have progressed and things are much more complex with many processes running concurrently, which can create concurrency issues. For example, one issue I encountered was data cropping up in unexpected parts of the code. After analysis, I found that the cause was stateful Spring beans exposing their data while being accessed by other concurrent threads.

Yes, concurrency issues are very hard to debug. It's not that I didn't know this before, it's just that I didn't really consider it when writing code. Today, after dealing with enough issues during my year in DevOps, I can pick out the parts of my code that may be vulnerable to concurrency issues and make sure I log messages accordingly. I'm generally more "concurrency aware" and also more adept at debugging concurrency issues in particular.

5. Take care with dependencies

A year in DevOps gave me much more intimate knowledge of CI, and namely, a better understanding of what happens to all those build modules that different developers commit to GitHub. The way one module uses dependencies can create issues for another module, such as circular dependencies, classpath problems, or all-around dynamic-link library (DLL) hell. I use this knowledge to construct projects wisely to minimize the number of dependencies I expose, and I only publish those parts of code that I have to.

My year in DevOps had a profound effect on how I develop code and on my life as a developer in general. Exposure to the many tools and types of infrastructures that DevOps uses gave me a more forward-thinking attitude that looks far past my own machine. Now I see how my code needs to work with surrounding developers' code. But more than that, it gave me a new set of skills I could apply in my daily work as a developer.

Not everyone can develop a Jenkins plugin to solve a problem. Not everyone understands your customer's viewpoint as they integrate newly purchased infrastructure. These are invaluable lessons I learned while in DevOps. For any developer out there, I strongly recommend making this foray into the unknown, even if just for a short time. An even stronger recommendation is for team leaders to send at least one team member on a journey through DevOps.

Image source: Flickr

[ Webinar: Paving the Last Mile to Production: Putting the "O" in DevOps ]