I’m going to cover some relative basics today. At least, they’re basics when it comes to differentiating between static and dynamic code analysis. If you’re new to the software development world, you may have no idea what I’m talking about. Of course, you might be a software development veteran and still not have a great idea.
So I’ll start from basic principles and not assume you’re familiar with the distinction. But don’t worry if you already know a bit. I’ll do my best to keep things lively for all reading.
Static and Dynamic Code Analysis: an Allegory
So as not to bore anyone, bear with me as I plant my tongue in cheek a bit and offer an “allegory” that neither personifies intangible ideas nor has any real literary value. Really, I’m just trying to make the subject of static and dynamic code analysis the slightest bit fun on its face.
So pull your fingers off the keyboard and let’s head down to the kitchen. We’re going to do some cooking. And in order to that, we’re going to need a recipe for, say, chili.
We all know how recipes work in the general life sense. But let’s break the cooking activity into two basic components. First, you have the part where you read and synthesize the recipe, prepping your materials and understanding how things will work. And then you have the execution portion of the activity, wherein you do the actual cooking — and then, if all goes well, the eating.
Static and Dynamic Recipe Analysis
Having conceived of preparing the recipe in two lights, think in a bit more detail about each activity. What defines them?
First, the recipe synthesis. Sure, you read through it to get an overview from a procedural perspective, rehearsing what you might do. But you also make inferences about the eventual results. If you’ve never actually had chili as a dish, you might contemplate the ingredients and what they’d taste like together. Beef, tomato sauce, beans, spicy additives…an idea of the flavor forms in your head.
You can also recognize the potential for trouble. The recipe calls for cilantro, but you have a dinner guest allergic to cilantro. Yikes! Reading through the recipe, you anticipate that following it verbatim will create a disastrous result, so you tweak it a little. You omit the cilantro and double check against other allergies and dining preferences.
But then you have the actual execution portion of preparing a recipe. However imaginative you might be, picturing the flavor makes a poor substitute for experiencing it. As you prepare the food, you sample it for yourself so that you can make adjustments as you go. You observe the meat to make sure it really does brown after a few minutes on high heat, and then you check on the onions to make sure they caramelize. You observe, inspect, and adapt based on what’s happening around you.
Then you celebrate success by throwing cheese on the result and eating until you’re uncomfortably full.
Static and Dynamic Code Analysis Back at Your Desk
Hopefully you have an inkling as to where I’m going with this. But in any case, I’ll get specific and bring it back to the world of programming.
In some senses, the kitchen recipe offers a good representation for code that you write. Source code is the recipe itself. It represents a sequence of instructions, intended to be carried out at some later time and date. Like a recipe, the code should be readable and suitable for communication with other humans.
But like a recipe, source code is all theory until you compile it and see what it does. At this point, the compiled and running executable looks like the act of cooking. The recipe comes to life, and you see it doing tangible things in the real world — making things appear on the screen, sending signals to printers, and infuriating you with unhelpful error messages.
Now, source code isn’t static analysis, and compiled executables aren’t dynamic analysis. Rather, static analysis is reasoning about source code — your recipe. And dynamic analysis is reasoning about your runtime behavior — the cooking.
The Nature of Static Analysis
A while back, I wrote a detailed introduction to static analysis. In that post, I used a different kind of analogy but still described the essential nature of static analysis.
Static code analysis involves examining source code and making inferences about the future from it based on data. These inferences might include predictions about what will happen when you run the software, such as highlighting likely sources of bugs or security issues. Alternatively, you can use a static analysis tool to identify code that will be hard to maintain. Or you can simply gather data about the code to help you make decisions. And you can do this with automated tools or by simple manual inspection, such as with code review.
Static code analysis has some significant advantages. Running your code in production or a production-like environment is expensive in a variety of ways. Looking at the code is easy. Think back to the recipe example; reading over a chili recipe is easier than cooking the chili. And identifying and fixing errors at this point in the game is also significantly cheaper. Measure twice, cook once.
The Nature of Dynamic Analysis
Now that you’ve read through a good bit of this post, hopefully you understand that you routinely perform dynamic analysis. Every time you fix a defect in your codebase and then run the code to verify the fix, you perform dynamic analysis. Every time you write and execute a unit test, you perform dynamic analysis. And yes, every time you fire up the application and just play with it to observe it, you perform dynamic analysis.
Of course, tooling exists on the dynamic side as well; it doesn’t all have to be you futzing manually with the application. Dynamic security and performance analysis tools exist everywhere. Have you ever run a memory profiler? Done a load or stress test? All of these represent automated dynamic analysis of your code because all of them involve running your application, performing experiments, and recording the results.
In some senses, there’s simply no substitute for this, as with tasting what you’re cooking. The proof is in the chili. Static analysis provides potential savings and important insights, but dynamic analysis confirms or refutes those hypotheses.
Leveraging Static and Dynamic Code Analysis
If you were going to guess what I’d advise about reconciling these approaches in your overall strategy, I imagine you’d be right. You need them both. But what you may or may not realize is that you already do both.
Every time you read and reason about what your code (or someone else’s) will do, you’re performing static analysis. And every time you run your web app to see whether you fixed the bug saving to the database, you’re performing dynamic analysis. In these cases, you’re just doing it manually.
So yes, you need both, but you already do both. What you really need to do is make sure you’re doing both efficiently, by automating as much of it as you can. These days, you can pull up recipes on your smartphone and cook them using all sorts of fancy gadgets. Make sure you’re as slick with your software tooling as you are with your personal devices.