The Agile Architect
How To Be a Superhero Software Developer, Agile or Not
If you've seen any trailers for movies lately, you know that superheroes are the new hotness. In a blatant rip-off of the genre, our Agile Architect describes how to have your own secret origin as a super software developer.
Everyone who knows me knows that I collect comic books. I've long passed the days when I was somewhat ashamed to admit that a grown man's favorite super-hero is The Green Lantern. Now I'm taking the next step and writing about them in my purportedly technical column. For those of you waiting for an agile angle to this, trust me. I'll get there. For those of you happy to read about comic books. Cool! So let's dive in.
There are two main aspects to comic book collecting: collecting as a financial investment and collecting for enjoyment. While there are many people like me who purchase and read comics for enjoyment, I am always amazed at the people who collect comics only for investment purposes. They don't even read the comics they buy. In fact, there is a relatively recent initiative in comic book collecting to "slab" comics. That is, to have their condition professionally graded, then entomb the comic book in a sealed, archive quality plastic sleeve with a certificate indicating the condition. At this point, the comic book becomes, to me at least, a worthless commodity to be sold or traded purely for its perceived value. In other words, its valuable because somebody else is willing to buy something that they also cannot read or enjoy.
Many of these investors spend a boat-load of money buying the new hot book on the shelf. I've seen people purchase hundreds of copies of a single book, thinking that each copy would someday bring them a fortune. It doesn't.
In truth, if you are truly interested in making money on comic books, you should gather up as much money as you possibly can and invest it in a few (or even one) near-perfect copy of an early issue of a well known character like Superman or Batman. If you can afford to purchase and hold onto a copy of Action Comics #1 from June 1938, the first appearance of Superman, you are bound to make money. If you buy 200 copies of anything on the shelf today at $3 to $5 dollars apiece, they will probably bring you 25 cents apiece in a few years, maybe $1 if you are lucky.
But if you collect comic books because you like to read them, and you buy the things you like to read, every once in a while there's a gem that makes it into your collection before it becomes valuable.
So how does this relate to software and agile? I've been working with a group of recent Ph.D. physicists who are interested in moving from academia into commercial software development. While they are extremely bright and have some advanced algorithm programming skills, it's gotten me thinking about how to succeed in the commercial software industry. And as you may have guessed, there's a parallel to comic book collecting and it boils down to this:
You can spend a lot of time chasing after the latest hotness, but in the end, your ability to craft professional-grade software depends on the investment you've made in understanding the fundamentals and your enjoyment of the current state-of-the-art technology.
That's it. Pretty simple.
And now I'm going to run the risk of complicating it by trying to explain it.
First of all, I did not say not to learn the new shiny hotness. Just like with comic book collecting, there will be new technologies that catch your interest, either because they are directly applicable to your work or just because. Go for it. Learn it. Learning new things expands your horizons and gives you new insights into your craft.
But, just as there isn't enough time to read every comic book published each month, we are long past the days when we can learn every new technology that comes out. You can certainly read about them and play with them at a superficial level, but there isn't enough time in the day to be an expert at everything. And if you try, you won't have the time to learn any of them well. Better to pick the ones that you need for your current projects or that you truly enjoy and learn them thoroughly.
And it's a tough choice, because there are all kinds of cool things out there, ranging from the Internet of Things (IoT) on the edge of our networks to Big Data distributed through our data centers, from iOS and Android native apps to highly available Web services fronted by Angular, React or any number of other web frameworks, from noSQL databases to Raspberry Pi's, and so much more. Oh, and let's not forget the drones!
And while you are learning the cool things, make sure you understand the fundamentals, the things that don't change based on which technology you are using at the moment.
Here's a list of some things I think every commercial software developer should know, agile or not, in no particular order.
- Conversational UML: The Unified Modeling Language is a standard way to express object-oriented ideas. I've been in too many design discussions with developers who don't know UML who struggle to express their ideas to others. And even if they do, the artifacts they leave behind, e.g. whiteboard drawings, are indecipherable to anyone that comes late to the discussion. With UML, anyone can walk up to a diagram and understand its intent. Now, I'm not suggesting spending huge amounts of time learning all the nuances of UML. That's why I call this conversational UML. Just like any language, you need to know enough to express yourself. The UML is there to facilitate the conversations, not to replace it.
- Design Patterns: The book "Design Patterns: Elements of Reusable Object-Oriented Software" by Gamma, Helm, Johnson, and Vlissides introduced the concept of design patterns to the world. It is still required reading today. Perhaps one of the single most productive learning experiences I have had as a software professional was absorbing this book over a weekend. If you've written object oriented software, you will recognize these patterns in your own work. Understanding them and being able to name them allows you to write better, more expressive software that can concisely convey the intent of your design through the use of these patterns and their names.
- The Open-Closed Principle, Dependency Inversion Principle and Dependency injection: OK. This isn't just one thing but they are all related. The Open-Closed principal, which says that you should design things that are open to extension but closed to modification, sounds impossible to achieve but is quite simple if you understand dependency inversion, that the outside system should define the dependencies of an entity not the other way around, which can be implemented with dependency injection. In other words, when you build a class, function, etc., it should not have knowledge of the outside world. Anything external that it needs to function properly should be given to it. I acknowledge that this is very much an object-oriented concept. As I am learning more about functional languages, I'm curious to see if there is an analogous concept.
- Version Control with Branching and Merging Strategies: Every developer that works in collaboration with others needs a basic understanding of how to use a version control system to manage their code base. Modern tools like Git provide great power in terms of the ability to easily create diverging branches of code and subsequently merge them back together. But the tool by itself doesn't make managing code easier. In fact, it can help you to quickly make quite a mess of things. Understanding concepts like a stable master branch strategy, an unstable master branch strategy and Branch By Abstraction and how these are different from branching as code promotion strategies can make your life much easier.
- Automated Testing: Automated testing comes in many flavors from low-level unit testing up to large scalability testing, from functional testing to user acceptance testing, from performance testing to integration testing. And these can be done in a variety of ways from after-the-fact testing to the more agile test-driven and behavior-driven development. Knowing how to build robust tests, and knowing which tests not to write, can mean the difference between stable, well constructed software and a real mess of missed deadlines and broken promises.
- Build Systems: Having the ability to build your software in a single, well-defined, well-controlled environment avoids the "it works on my computer" syndrome. Build systems like Jenkins and TFS not only compile your code but can also deploy and run all of your automated tests. Having a reliable build system is an important step in creating a successful devOps strategy.
- Deployment Strategies: Having a well thought out deployment strategy for your software is important to ensure its stability in production. I've seen too many companies build their software in place on their production systems. Since they've bootstrapped their way, they have no repeatable process to stand up another system. When their product is successful and they need to replicate it, e.g. for scaling to support more users, they have no mechanism to do this. Understanding how to deploy your software means you can set up multiple identical, or nearly-identical, development, QA and production environments at any time.
- Memory Management: While many modern languages don't explicitly require you to manage memory directly, it's still important to understand how your software allocates and frees memory. If you haven't learned a lower-level language like C that requires you to allocate and deallocate memory explicitly, then you run the risk of being too cavalier in your trust of garbage collectors and other automated memory management solutions. Any system can have memory leaks if you don't understand what they are doing under the hood.
- Performance Tuning and Testing: Every developer needs to understand when and how to tune performance. Prematurely optimize and you run the risk of creating unnecessarily poor designs. Don't think about optimization at all and your software may die by a death of a thousand cuts. That is, too many slow implementations scattered throughout your code making it impossible to optimize. Of course, agile practices can help alleviate that issue.
- Debugging: I'm not just talking about how to use a debugger. I am talking about general techniques to track down defects in your software. Knowing how to debug your code is important for multiple reasons. First, it means that you can track down defects quickly. Second, it informs you on how to best instrument your code to help track down problems while supporting the production application.
- User-Centered Design: This is a slightly different beast from the topics above. Everyone on a software team, not just the UX person or the developers, should understand the importance, benefits and practices of user-centered design. I once worked on a large multi-tiered application where one of the developers said, totally seriously, "Let's build the server first and then see what it can do." Umm, no.
So there you have it. Superman, science and software all wrapped up with a neat little bow. I didn't really tell you how to be a software superhero nor did I provide you with an exhaustive list of skills that modern software developers need. But I hope I at least got you thinking about your own skills and how they line up to the list above.