Tomorrow is the first day of Microsoft’s annual Build conference. I always enjoy Build, but this one is a little bittersweet. This would have been my first time attending Build in person. But due to the current global pandemic, Build has been converted to a digital conference.
Despite the pandemic, this year’s Build should still be a great time. Here are some of the sessions I think will be especially good:
Every developer is welcome, with Scott Hanselman and guests
This session sounds like a general overview of a modern development workflow, with a focus on Microsoft brands. On paper this doesn’t sound particularly interesting, however there are a few factors that should make this worthwhile:
Scott Hanselman is a great speaker and developer, and he tends to promote similarly talented people. I expect this session to be both entertaining and informing.
This is the first Build after the github acquisition, which probably means github will be more heavily featured in some of the developer workflows covered in the conference. I’m really interested to learn about this topic, especially with regard to potential DevOps workflows available on github.
The session claims to focus on a ‘modern development toolkit’, and we all love new and shiny things. Don’t lie to yourself.
The Journey to One .NET
As most .NET developers should know by now, Microsoft has been in the process of consolidating all of the different .NET implementations into a single entity. This consolidated framework will be known as .NET 5.
If I recall correctly, this consolidation idea was initially announced at Build 2019. Since then, everything I’ve heard about it has still been conceptual in nature. I hope that this session will be the first time that we get some some concrete information on this transformation, and if we’re lucky, maybe it will include a release announcement as well.
C# Today & Tomorrow
This is a talk that Mads Torgersen gives pretty much every year. It’s typically pretty tech heavy, and focuses on new language features in C#. This talk is essentially the CliffsNotes for the next edition of C# In Depth, and I love it.
I have seen Bill Wagner give talks like this as well, and they are always awesome. There’s nothing like learning about new language features that makes you want to go hack something up, or go refactor some ugly, crusty old code that would benefit from the new language features.
What’s even better is that potential upcoming features are covered too. Microsoft has been delving into the territory of demoing unreleased features more and more in past conferences, and C# is a great example of this. The spec is being developed and discussed in the open, which means even if you don’t watch the talk, you can find the information that Mads is talking about easily on the internet. And you can even contribute to the discussion on github. How cool is that?
Making every developer and team more productive from dev box setup to coding to deployment and debugging
This session is potentially more interesting to me than most devs, because I work on developer tools. As part of this, my team owns the developer machine setup, including providing input and testing on our VS deployment.
Part of my job is making the process of getting up and running as easy as possible for our developers. The past few Build conferences, we have seen cool new features being added to Visual Studio to make this process simpler and faster. I’m super excited to hear about the new developments in this area.
Amanda Silver is a great speaker, and she injects so much joy and enthusiasm into her talks that I am always energized and excited to pull the latest Visual Studio update after watching them. I’m sure this one will be no exception.
How to be super productive with Node.js and Visual Studio Code
I’m looking forward to this talk mainly because I absolutely love VS Code, and I have recently been getting back into Node.js development a little bit on the side.
I don’t remember ever hearing from this speaker before, but his past experience seems impressive. Hopefully this doesn’t just turn into an ad for Azure…
DIY Tech for BFFs
I think this is the only limited session I RSVPed for, and it looks like they’ll be doing these sessions over MS Teams with a cap of 10,000 attendees. I guess we’ll see how that goes.
I signed up for this session because it sounds like the presenters will cover some interesting, small projects that are easy to collaborate on. I’m always trying to get my friends to take part in these sorts of projects. Sometimes it even works! I think this should be a fun session.
So that’s how my next couple of days will go. It’s still a bummer that I won’t be able to attend in person, but hopefully we’ll move past this whole global pandemic situation eventually, and we can once again meet up in person from time to time.
Happy Build 2020 everybody, and I hope it’s a good one!
Over the past few years, I have had a few opportunities to get some hands on experience in unit testing. I’m still learning and improving my understanding of the topic, but I figure I can put together a quick post about the most important things I’ve learned.
Unit Testing is Primarily an Architecture Problem
Writing a single unit test against a small, pure function is an easy task. Throw some inputs at it, then test the expected output, right? If only all parts of our applications were this simple. Alas, as software engineers in 2020, we tend to write complicated, object-oriented code that is quite hard to test if it isn’t expressly designed to be modular in the right ways.
Are you calling out to a database? Well unfortunately that’s untestable. Communicating with a web API? Untestable. Writing to the filesystem? You better believe that’s untestable. Don’t get me wrong, we can certainly write tests that invoke the filesystem, the registry, and so on. But these are not unit tests. They’re exercising far more than a single ‘unit’ of functionality in our software system. In a true unit test, all we want to test is a single business need and nothing more.
Because of this constraint, we as developers must concoct an architecture that decouples our core business logic from these implemetation details. This is what enables unit testing. Fortunately, it just so happens that architecting for unit testing tends to align with good design practices in general. Most developers have probably heard of the SOLID prinicples of OOP. Nearly all of these principles apply directly to code that is easy to unit test as well.
Testing Legacy Code
So let’s say I haven’t been applying these architectural concepts to my codebase. In fact, let’s say that somebody (not me, definitely not me) has failed to modularize and apply any real architectural rigor to my codebase whatsoever…for the past 20 years of development…
We’ll then we’re in a bit of a pickle aren’t we? How can I prove that if I do A, then B will happen? There’s no way to test A, because in order to even do A, I have to first do C, D, E, F, G…etc until I have exhausted the alphabet analogy several times over. A legacy application that is not architected to be modular will be impossible to unit test without a lot of refactoring.
The guidance for this situation tends to be that we should refactor this code into something that is testable. But this reveals the fundamental contradicton of unit testing legacy code. We can’t refactor the untestable code into something testable without potentially introducing regressions. To avoid regressions, we need to have tests in place. Uhhhh, what?
Most of the resources I have seen suggest adding tests at a higher level first to verify that we aren’t breaking important business logic as we refactor toward an architecture that supports unit testing. This may mean system level tests, or full integration tests. At any rate, we will need to temporarily make our code (and tests) less maintainable as a means of refactoring toward something that is testable.
Unit Testing Greenfield Code
This topic is where I am currently still struggling. It’s extremely easy to succumb to analysis paralysis when you’re thinking a lot about about testability.
Oh fuck! That class I just wrote can’t really be tested at all can it? But…do I even care about testing that?
Maybe not. The first struggle I ran into after learning about all this unit testing stuff was that I didn’t understand which portions of the code even needed unit tests, versus those that are essentially an implementation detail. The crux of the matter seems to be that you want to be testing core business logic. Anything that deals with the specific implementation of this logic, and how it works with other systems, should be decoupled and made as thin as possible.
Beyond this point, I am still having trouble iterating on untestable code. I’m not doing TDD, so I’m writing the code before I write tests for it. But do I need to write beautifully testable code from day 1? Probably not. I think I have just been burned so many times on ‘prototypes’ that eventually shipped with no further refinement that I fear greenfield code written in a way that is expressly not testable. Maybe TDD is the only true way forward. I guess I’ll find out eventually.
These are the resources I have come across in my unit testing journey:
This is a very short book, which seems to be comprised of a handful of posts published in the author’s blog. If I’m honest, the quality is not great. It does seem like a direct transcription of the blog posts (with references to hyperlinks and all). However, it is a quick overview of unit testing and the eventual complications that will come. This book won’t make you a unit testing expert, but it does a great job of giving the reader the lay of the land on the topic as quickly as possible.
I covered this book extensively in my previous post. This is not a book about unit testing. However, the architectural techniques described in the book are essential to crafting code that is easily unit testable. Nearly all in-depth resources I have found on unit testing mention dependency injection as a core concept. I think this book does an amazing job at tying the two concepts together, along with other general software design guidelines.
Throughout most of the book, the authors present examples using what they refer to as “Pure DI”. Pure DI is essentially just doing Dependency Injection without an IoC container. Specific IoC containers aren’t covered in depth until the last few chapters. Until then, everything is done from scratch.
This approach seems to work fine for instructional purposes. I wouldn’t want to do it for anything but a trivial application, but it does show the core mechanisms behind all DI containers, and makes clear that they aren’t doing anything particularly magical. Pure DI is covered in depth later on in the book.
Apart from Pure DI, the authors introduce the extremely important concept of volatile dependencies early on. This concept is key for understanding the value of DI, proper unit testing, and clean software architecture in general. Page 27 contains a comprehensive definition of what constitutes a volatile dependency, but in short, it refers to any dependency that may be subject to change. This can mean a data access layer that hits the file system being reworked to target a database instead. It may refer to a module that is still undergoing development by a different team. It can even be as simple as a piece of logic that changes depending on the current date and time.
Whatever the situation may be, the goal of DI is to allow the developer to avoid depending directly on volatile dependencies, and to depend on abstractions instead.
After looking into DIPPP a bit deeper, I was delighted to find out that this is actually more of an architecture book than a basic introduction to Dependency Injection. The book kicks things off early in chapter 2 with a powerful example of a nontrivial, multi-layer application written in a tightly coupled manner. This example is then reworked in chapter 3 to invert the volatile dependencies, resulting in a loosely coupled version of the same application.
The reason this example is so powerful is that every developer has written the tightly coupled version of this application. When you’re a beginner, and for many people for the rest of their career, this is just how you write software. I’m not too proud to admit that it wasn’t immediately obvious to me how the loosely coupled version should be written. This example is great, because it clearly demonstrates the goals of Inversion of Control, and how to achieve them through DI.
…abstractions should be owned by the module using the abstractions. In this context, “owned” means that the consuming module has control over the shape of the abstraction, and it’s distributed with that module, rather than with the module that implements it. The consuming module should be able to define the abstraction in a way that benefits itself the most.
The book makes constant reference to the SOLID principles. One might think that Dependency Inversion is the only principle that comes into play with DI, but this couldn’t be further from the truth. As I said, this is more of an architecture book. Most of the concepts demonstrated via DI are motivated by one or more of the SOLID principles, and the authors never miss an opportunity to point it out.
DI Patterns/Anti-patterns/Code Smells
Once the book starts diving into proper DI patterns, four important concepts are introduced:
Your composition root is a centralized location, ideally near the entry point of the application, where the entire dependency graph is defined. This is a fundamental feature of DI. The other three concepts are different ways to provide a dependency to a consumer. Constructor Injection seems to be preferred over the other injection techniques. Unless there is a good reason why it cannot be used, the authors make clear that Constructor Injection should be used by default whenever possible.
After covering DI patterns, the book moves on to what it refers to as “DI anti-patterns”. This chapter title is a bit of a misnomer, because it covers both instances of DI being applied incorrectly, and coding practices that are effectively the antithesis of DI.
What’s the opposite of Inversion of Control? Originally the term Inversion of Control was coined to identify the opposite of the normal state of affairs, but we can’t talk about the “Business as Usual” anti-pattern. Instead, Control Freak describes a class that won’t relinquish control of its Volatile Dependencies.
The discussion around the control freak anti-pattern really hits home. Much like the tightly coupled application example from Chapter 2, everyone has written code like this. Prior to digging into some architecture books, I suspect that this is just what coding is for most developers.
This chapter, along with the one on code smells, should be a great reference for driving code reviews. Instead of saying “this is terrible code don’t do this”, you can say “this is considered an anti-pattern (or a code smell), and here’s why”.
Before reading this book, object lifetimes were just about the point where my understanding of DI started to dwindle. And if I’m honest, I’m still a little fuzzy on this topic after finishing it. An IoC container (or your Pure DI implementation) can create and release concrete object instances according to three different policies:
Much like the types of injection, some general recommendations are given for which lifetime to use and when. Singleton is presented as a reasonable default, at least for thread safe code. In the singleton lifetime, a concrete instance is created immediately in the composition root, and that same instance is provided to any consumer that depends on the abstraction. The authors make it very clear that the singleton lifetime is in no way the same as the singleton design pattern (or rather, anti-pattern), and that it doesn’t share the same downsides.
The use cases for the transient and scoped lifetimes mostly focused on thread safety and web request scope respectively. I feel that these lifetimes weren’t really covered deeply enough, especially the scoped lifetime. But perhaps I just need to go back and give that section another read to really understand it.
Interception and Aspect Oriented Programming
The next section covers what the authors refer to as ‘interception’, which is a way to implement Cross Cutting Concerns in a codebase that already uses DI. The examples of this include adding logging, auditing, etc without having to modify any existing code. This is mostly achieved through various applications of the Decorator pattern.
The interception idea is applied in increasingly generic ways, which eventually leads seamlessly into the next chapter on Aspect Oriented Programming. I haven’t read much about AOP before this book, and the book doesn’t go particularly in-depth on the topic either. The information presented makes me wonder how/if it works in practice, or if this is purely a case of software architects taking their geekiness to the highest extremes possible.
AOP is complicated enough that there are texts dedicated solely to this topic, so I’m assuming the information we get in DIPPP just grazes the surface. The authors do a decent job of describing the natural progression from DI to AOP however.
Specific IoC Libraries
The final chapters of the book cover three specific Inversion of Control libraries:
Each one of these libraries is covered in the exact same way, with the exact same examples. This section is a reference of sorts, and a good way to show how the ideas presented in the book are handled in practice using an IoC container. I skimmed through these chapters, but the main takeaway I got is that MS.DI is not a recommended IoC container, because it lacks some key features like auto-registration and auto-wiring of decorators. There are also limitations in the support for composites.
There is one major miss in this section that I think is fairly regrettable. MS.DI may not have all of the features that the authors expect in a full fledged IoC container, but it is notable in that it is an official, built-in solution for anyone developing .NET Core and ASP.NET Core applications. And even more notable is the fact that it is designed as a generic interface that can be implemented by other IoC Container authors. The authors of Autofac have done exactly that, creating an implementation that conforms to the standard MS.DI interface. .NET Core developers need not be immediately flummoxed by the use of an alternative IoC container.
I suspect that the reason this aspect isn’t covered may be that one of the authors, Mark Seeman, considers this Conforming Container idea to be a DI anti-pattern. When I first saw this article, it struck me as harmful dogmatism, especially in relation to MS.DI, but I’m certainly not experienced enough on this topic to say one way or the other. I also recognize that this article was published in May of 2014, about 2 years before version 1.0.0 of MS.DI was released. It’s possible that the authors have softened their stance on this issue, but I still would like to have seen it covered in DIPPP.
Problems and Potential Improvements
While the book was great overall, there is always room for improvement. After finishing the book, I don’t feel like I totally understand how to use the scoped and transient lifetimes. Some more concrete examples may help here. Also, part of the idea behind the title change between the 1st and 2nd editions is that the book is no longer exclusive to .NET, and can be useful as a general DI reference for all developers. To me, this is a bit misleading. All of the examples are in C#, and all of the IoC libraries covered are .NET libraries. There is some brief mention of Spring, but beyond this there is almost no discussion of any concrete tech unrelated to .NET. It’s still an amazing resource for DI in general, but I would hesitate to recommend it to someone who has no .NET experience at all.
On tone, the authors present their ideas in absolute terms, and at points this starts to sound like dogmatism. Service Locator isn’t “considered” an anti-pattern. It’s not that “some say” it’s an anti-pattern. It just is an anti-pattern, because Mark Seeman and Steven van Deursen said so. I get that this makes the text clearer, and the reasoning is always explained, but the way things are presented as undeniable, subjective facts rubbed me the wrong way in many instances.
Finally, the most glaring problem with this book by a country mile is the complete lack of any discussion of the human aspect of writing software this way. If I want to write a new application architected using DI, there are several people who have to sign off on this: my boss for one, maybe even my boss’ boss, and certainly my teammates who will be working on the project with me. I can’t just go into a cave of DI goodness for several months and come out with a gleaming pile of perfection that no one else in the company knows how to maintain. I might have to change the way I interview potential candidates who might work on a project architected with DI. How am I supposed to convince my team that DI is the way to go when well known developers and even godlike coding geniuses are still skeptical about DI?
Due to the way that DI turns on its head the way most developers typically think about writing software, at least a chapter or two is desperately needed to cover questions like:
How do I pitch DI to my team?
How do I introduce new developers to a codebase that makes heavy use of DI?
When is it appropriate to apply Pure DI vs using an IoC container? When it is appropriate to use DI at all?
How do I refactor toward DI without completely fucking everything up?
Perhaps this would expand the scope of the book too much. But some supplementary material on the web, or maybe a companion book covering this side of DI would be awesome.
Despite these flaws, reading this book was a great experience. Even information in the earliest chapters will change the way I write software forever. Having finished it, I feel much more confident in my understanding of Dependency Injection, and in software architecture in general. The authors frequently cite high-quality sources in the footnotes, which will no doubt promote continued learning and deeper understanding of the underlying architectural concepts.
I expect to keep this book on my desk as a reference for quite a while, and I strongly recommend that any developers interested in DI or architecture in general pick up a copy. If you’re like me, you will regret not doing it sooner.
Last weekend I attended a local developer event called Boston Code Camp. BCC is an informal gathering of Boston area software developers full of cool technical talks. It’s free, and pretty convenient to get to, so I try to attend whenever my schedule allows.
This talk was more of an exhibition of the flexibility of Xamarin Forms. The speaker aimed to build, deploy, and run a Xamarin Forms application on every supported platform. Aside from a couple of platforms skipped due to technical problems, he was actually able to build and run on nearly every platform.
The main point of the talk seemed to be to highlight the idea that a single (mostly) shared codebase can be deployed to many platforms, with only differing UI layers. He did explain that it is possible to detect which platform is being used at runtime and switch sections of code on and off based on this, but I gather that this is meant to be avoided whenever possible.
This was a pretty cool talk, although I’d love to see a followup talk that delves a bit more into the architecture of a nontrivial application targeting many platforms. The powerpoint and all of the demos for the talk are available on github at: https://github.com/JarleySoft/XFChallenge
I’m not particularly experienced with containers, so I didn’t get a ton out of this talk, but it was certainly interesting.
After some initial discussion, the speaker kicked off with his main assertion that the automatically scaffolded Docker setup from Visual Studio should not be used. For various reasons, he recommends creating everything from scratch on the command line instead.
If you’re going to use Docker, get used to the command line
The key to his alternate design is that instead of building the application normally and deploying it into the contianer, you should instead deploy the source code, then build and run it inside the container.
The speaker, a developer at Mill5 in Boston, mentioned that he will soon be putting up a full technical post with some more info on the Mill5 blog, so stay tuned for that if this sounds interesting.
This talk contained some great hiring tips, beyond just interviewing practices. Near the end was a great list of resources about avoiding bias, and hiring in general. I highly recommend checking out the slide deck.
Again, I won’t say too much about this talk, as the entire thing has recently been made available for free on YouTube. The main points were about the basics of async/await in C#, some common pitfalls, and a quick demo of the new async streams feature of C# 8.
This was a pretty interesting talk. The speaker, Jason Haley, is an independent consultant, and the talk went over over many of the special considerations that need to be taken when going into business for yourself. This included general financial advice, legal advice, information on how to find clients, how to deal with clients, and much more.
If I’m honest, before attending this talk, “Going Independent” sounded like a pretty appealing concept to me. Jason did a great job of disabusing the audience of this belief. He makes it clear that going independent requires shifting a significant portion of a developer’s time away from strict technical work onto the actual logistics of running a business.
This talk got me thinking about alternative ways of working as a software developer. A while back, I picked up a copy of Erik Dietrich’s Developer Hegemony. I haven’t gotten around to reading it yet, but from what I understand, it talks about a model of software development where programmers work in a co-op type situation, similar to a law firm.
Update (4.13.19): Jason has since posted a nice summary, along with the full slides on his own blog. If this topic sounds interesting, definitely go check those out.
This talk was all about Azure functions and serverless applications. A lot of this went way over my head, becuase I don’t have any experience in this area, but it was fairly interesting nonetheless.
The speaker presents the combination of Azure functions and Cloudflare’s free tier to build serverless applications that cost very little to run. His prime example of this was Troy Hunt’s PwnedPasswords tool. Hunt wrote a thorough post about a similar setup works, and how he is able to run the service very cheaply.
Beyond this, I came away with a handy list of links to check out on serverless development:
Over the past week or so, my teammates and I have been interviewing potential candidates for a summer intern position. It’s a development role, so of course, we have been asking some basic coding questions. We have also asked the candidates to solve a couple of simple programming challenges, both before and during the interview.
If you’ve ever been in an interview for a programming position before, the idea of coding as part of an interview probably sounds pretty normal. It is quite common to ask these sorts of questions, even to programmers applying to much more high level positions, strictly due to the small amount of “phony” programmers applying to highly skilled positions who actually cannot code their way out of a wet paper bag. We’ve all read the horror stories.
But that’s not what this post is about. This post is about what we do after we have concluded that the candidate actually knows how to solve very trivial programming problems. In of our current batch of interviews, as the last question, we have been presenting a coding problem which consists of three phases:
The First Phase
The first phase is just a simple text processing problem that we expect the candidate to solve in a specific manner. So far, no one has strayed outside of our assumptions, and no one has failed to solve this portion. Even so, this first part actually provides a smidgen of useful information. The main thing we have taken notice of is the candidate’s choice of programming language.
Due to the disconnected bubble of CS academia, all of these candidates know at least C and Java. And without fail, these are the languages that they claim to be the strongest in. A handful of our candidates chose to do the text processing problem in C, which is an immediate handicap. And indeed, all of the candidates who tried to solve the problem in C have had issues with pointer manipulation. It’s not so much the problems with pointers that concern me, rather it is the default choice of C to solve a problem that would be much easier in a language like Java (or Python, or C#, or whatever). For every candidate, we specified that they are allowed to use any language, even pseudocode, to solve this problem. So why would anyone choose C?
The Second Phase
The second phase of our question is just a test that the candidates understands and can apply a basic CS concept. In this case, the concept is recursion. I have begun asking this question in two steps, first by simply saying something like “can you solve this problem without using any looping keywords, like ‘for’, or ‘while’?” If the candidate seems stumped by this, we will connect the dots for them and mention that the concept they will need to use is called “recursion”, and so far everyone has been on board from at least this point.
I don’t believe that you can get even a year into a CS degree without being introduced to the concept of recursion, so I’m not too worried that asking this question is potentially alienating anybody. It’s somewhat arbitrary, but I think general algorithms that can be solved recursively introduce themselves in the real world much more frequently than anything involving sorting algorithms or red-black trees, for example.
The Third Phase (a.k.a, The Perl Phase)
Early on in the interviewing process, one of the guys on the team suggested a new type of coding question. As I mentioned in my last post, a large part of what my teammates and I deal with is a messy, legacy Perl codebase. So my teammate suggested, in not so many words:
Why don’t we have them try to write some Perl? Just say, “here you go, you have the full power of the internet”, and let them try to figure out how to solve a simple problem in a programming language that they’ve never used before?
This actually turned out to be a stroke of genius. It’s not a bad language by any stretch, but Perl is not exactly en vogue right now, so needless to say, nobody we interviewed knew even the first thing about Perl. This is a good thing. Remember, these are intern candidates we’re interviewing. A major part of being an intern is learning new things. If all you know is C and Java, you better believe you’re going to be learning some new languages if you’re going to work on our team.
To find out what the candidate knows, ask them about something they know…
In a similar vein, to find out how a candidate learns, ask them to code something in a language that they don’t know. For anyone who made it through the first two stages with no major issues, we presented this exact scenario to them. We gave them a clean browser opened to google, a text editor with Perl syntax highlighting enabled, and a terminal. Then we instructed them to do whatever they needed to do to write the same program as before in Perl.
Don’t get me wrong, we’re not cruel. For every candidate, we clarified that we weren’t really looking for a working solution at the end of it, rather we were just interested in how the candidate tries to solve a new problem. Let’s be fair here, the majority of what a developer does in day to day work is “advanced googling”. We wanted to find out how good these candidates were at searching for information and learning from it. There are a few things that I learned from this experiment:
Anyone capable of writing a basic computer program must also have some basic googling chops, and can come to some useful pages without too much trouble. Surprisingly, this did not turn out to be a particularly enlightening part of the process. No one really struggled to come up with good sources.
The way a developer consumes the information seems to be much more pertinent than actually being able to find it. One candidate in particular was skimming through many pages very quickly. While he may have come across some good sources, they were rendered useless by the candidate skipping over large portions of important information in favor of quick, small code samples. On the other hand, the only candidate who actually ended up with a working solution worked through the sources slowly, with an apparent goal of understanding the information.
This process can give insight into how a candidate works through problems. One candidate in particular, with a bit of prodding, showed that he was able to segregate the different pieces of logic in his program and test the correctness of each portion to find out where an issue may be present. One flaw in this approach was exposed by the sole candidate who was able to produce a working solution. She actually came to a working solution before ever running the application. This gave great insight into her ability to search for and process information on the internet, but it didn’t give any insight into the way she worked through problems.
All in all, I think this was a useful experiment in interviewing. During technical interviews, we are expected to do some very unnatural things, and this was a way to see how a candidate works in a more realistic environment. When is the last time you wrote a program longhand on a whiteboard, without consulting any sort of documentation, and without being able to run the code? It was probably while interviewing for your current job.
At work, one of the projects that my team maintains is a legacy Perl codebase. This project originally contained both the client and server elements of a homegrown build system, as well as a homegrown SCM system, among other things. This project was initially written by a sole developer in the 90s, and over the years it has been maintained by probably 10 or so developers, none of whom likely knew Perl before working on this project.
Obviously, this is not an ideal situation for code quality. And indeed, this project has some pretty bad code. I’m talking single letter identifier names, global variables, no use of OOP whatsoever, massive subroutines, and very minimal use of the module system. In short, it’s a mess.
Fortunately, a lot of this code is not actually used anymore.
It isn’t uncommon to come across a file that was last modified over 10 years ago. In certain source files, if you grab the name of a function from its definition, there’s a decent chance that a grep won’t return any other results for that name in the entire codebase.
For this reason, I have proposed a policy of legacy code non-proliferation to my teammates. The gist of this policy is that any time a developer is tinkering in a specific area of this project, any clearly redundant or unused functionality should be dropped along with any other changes that are occurring. The goal here is not to go out of our way to weed out unused code, but if we happen to notice any “dead branches” in the area we’re working in, we will prune them.
When dropping this old code, we will segregate the removal into its own submission, and it will be tagged with a standard bug number. That way, if some legacy functionality that we’ve dropped actually turns out to be super important, it’s a simple process to restore it. After ripping out the old code, we can continue working in this area of the project with less of a mental burden.
So how did we even get into this situation?
There are a few specific styles of unused legacy code that I have come across:
One thing I have noticed a few times is instances where someone refactored a piece of commonly used code into its own function in a module, but the developer failed to update all of the instances of this functionality to reference the module. Or perhaps they did do the refactoring, but they left the old implementation commented out, presumably for the sake of posterity. The fix here is simple. Replace the redundant code with the generalized implementation that someone has already written for us.
Another thing I’ve noticed is the use of boolean flags to toggle between new and old functionality. This practice is fine when actually testing out a new way of doing things, but once you actually make the switch for good, it is important to remove the dead code path. Again, fixing this is fairly straightforward. Find every branching structure where we toggle between the old and new functionality, and simply remove the old branch and any code that is exclusive to it.
The last scenario is simply code paths, or full scripts, that are no longer used. An example of this is a script I came across that used to be called by users directly, on the command line. There were several different ways that a user could call this script, with a handful of different arguments. Today, no one uses this script directly, rather it is called indirectly from a UI application in a fairly restricted manner. A large part of the original functionality is no longer required. Again, our task is relatively simple. Remove the unused script or code path.
By no means am I suggesting that we all go diving into our old legacy codebases and ripping out anything that seems unnecessary. However, if you are actively working in a legacy codebase, maybe employ some of these techniques to try to reduce the amount of cruft, with the goal of eventually honing down the codebase into a useful nugget of core functionality. Removing unused legacy code is the first step in making it easier to reason about the overall design of the application and facilitating future improvements.
As January wrapped up, I completed the first book in my reading list. The full title is What’s the Matter with Kansas?
How Conservatives Won the Heart of America by Thomas Frank.
The book covers the rise of right-wing populism among conservatives in US politics, and Frank uses the changes in his
home state of Kansas as a token for the movement as a whole. Using a barrage of references from literature, radio, and
television pundits, he outlines why and how the movement started, and then how its supporters actually began to succeed
in getting people elected to public office. Frank refers to it as the “backlash”, and it is essentially what turned
into the tea party movement.
The book is overall well-written, and appears to be built on the results of extensive research. Frank can get a bit
long-winded at points, diving deep into exposition of his interactions with local residents rather than simply
squeezing out the key morsel of information that he’s working towards. Apart from a few instances of this, I really
enjoyed the read, and I highly recommend this book to anyone interested in US politics.
What’s amazing about this book, though, is that it came out in 2004. Let that sink in for a minute. That’s about 5
years before the beginning of the tea party movement. It’s 12 years before Donald Trump was elected as a president
(supposedly) representing conservative populism.
Reading this book in the current political climate makes Frank seem like a soothsayer. Adding to this feeling is a
small section in the epilogue that talks about the state of the Democratic party. Frank posits that the Democrats are
becoming too friendly with big corporations, and are alienating working-class voters. It’s almost as if he had seen
the entire 2016 presidential election play out 12 years prior. Frank has a new book dedicated to this topic called
Listen, Liberal: Or What Ever Happened to the Party of the People?. Stay tuned for a future review of this one.
Being a flaming liberal myself, I have been immersed over the past couple weeks in the various movements that
have sprung up post-inauguration to attempt to bring the Democratic party back to its progressive roots to win back
some political ground. These are, you guessed it, populist movements that aim to get money out of politics and elect
modern Democratic candidates who work for the people, and not big corporations. Who knows, maybe we’ll see a successful
left-wing backlash in the coming election cycles. Hopefully it’s not too late…
Recently I saw a Facebook post from my cousin that caught my eye. He said that he would be reading 52
books this year, one book per week. This resonated with me when I saw it. I like reading, and I like
the idea of a well-defined, easily validated goal.
Don’t get me wrong, I do not have the willpower to read a book every week. However, I was inspired enough
to aim for a similar goal of my own. Last weekend I created a rough list of 12 books on a post-it note that
I will aim to read this year. The full list is:
Jan - What’s the Matter with Kansas - Thomas Frank
Feb - Don Quixote - Miguel de Cervantes
Mar - Our Revolution: A Future to Believe In - Bernie Sanders
Apr - We - Yevgeny Zamyatin
May - Scar Tissue - Anthony Kiedis
Jun - On the Road - Jack Kerouac
Jul - God Is Not Great: How Religion Poisons Everything - Christopher Hitchens
Aug - Breakfast of Champions - Kurt Vonnegut
Sep - The Inmates Are Running the Asylum: Why High Tech Products Drive Us Crazy and How to Restore the Sanity - Alan Cooper
Oct - The Great Gatsby - F. Scott Fitzgerald
Nov - Walden - Henry David Thoreau
Dec - Love in the Time of Cholera - Gabriel García Márquez
I may end up swapping one or two out here and there, but this seems like pretty good starting point to me. The
list alternates between fiction and nonfiction, and I’ve attempted to keep a reasonbly varied selection
to keep things interesting.
The main goal here is to keep myself reading, and I have created a similar goal to attempt to keep myself
blogging, so keep an eye out for monthly posts about each book at the very least. I’m currently wrapping up
What’s the Matter with Kansas, so there will be a post about it in the works very soon.
Apart from that, stay tuned for some posts that are actually about software development maybe?
Yesterday I attended a meetup at the Microsoft New England Research and
Development Center in Cambridge! Despite being in a different city, it was
only a few short miles from my overpriced apartment in Boston.
Networking and Pizza
This meetup was more organized than most, and included an actual schedule.
The first order of business was eating pizza and networking with other
developers. I chatted with a developer who works remotely for StackOverflow,
and another dev who is currently looking for a C++ gig.
Being my first meetup in the area, I didn’t know anybody, so it was good to
talk to a few people at least. During the networking portion I was mainly
distracted/bemused by the sights of Shawn Wildermuth and Miguel de Icaza
just…hanging out with everybody. It feels stupid to admit, but I guess I
didn’t realize that developers who have attained a “rock star” type reputation
are still only rock stars in the relatively small world of software
development. They don’t have handlers. They don’t appear from backstage all
of a sudden when the lights dim. They enjoy the free pizza just as much as
The primary objective of this meetup was to record an episode of Shawn’s
Hello World Podcast, which is currently
on tour visiting a bunch of cities across
America along with a handful of international stops. The podcast uses an
interview format where Shawn talks with developers who speak about their roots
and history in the development field. In this instance, the subject of the
episode was Miguel de Icaza.
Miguel talked about his roots in open source, and how contributed as a hardcore
OSS developer for a long time. He eventually moved into the world of closed
source software, only to be bought out by Microsoft, who then proceeded to
open source his product and give it away for free in an exercise of ridiculous
An interesting tidbit from the podcast was that Miguel considers
Gnumeric, a spreadsheet application,
to be the most beautiful code he has ever written, and he’s not above
admitting it. On programming forums, you’ll often see people asking for
examples of beautiful code that they can learn from. Maybe this could be a
The podcast was recorded live at the event, but based on the
upload schedule, it should be available on Shawn’s site within the next few
weeks. I highly recommend giving it a listen once it’s available.
After the podcast, Shawn did about an hour-long demo/introduction to
If you’ve seen any of his
you’ll know that he is somewhat of a subject matter expert when it comes to
web development on the Microsoft stack, so I was very excited for this part.
After seeing Shawn’s presentation, it has never been more clear to me that
ASP.NET Core is effectively Microsoft’s response to the development style
of Node.js with Express.
This is not a bad thing. In fact it’s great! C# is a beautiful language,
ASP.NET is a great thing in my opinion.
With the standard ASP.NET MVC project template, you’re given a massive pile
of included features that you don’t even know what they do, and virtually
every resource for learning the framework kind of just rolls with it. It
reminds me of people starting with Java as their first programming language,
and being told to just ignore most of the language features you’re required
to use just to get a simple “Hello, world!” printed to the console.
So Shawn started his demo from basically nothing. All he had was a console
application which listened to web requests. During the talk, he slowly added
and configured pieces of middleware from Nuget, demonstrating the flexibility
of the new framework. Even fundamental things that you’d assume are included
by default were actually added to the base web app:
Support for serving static files
The .NET Framework itself
These were all included as Nuget packages and tied into the web application
as middleware. It was a pretty compelling demo, and like the podcast, the
code should be available in the coming weeks at Shawn’s
github repo for the
Overall, this was a fun and interesting event. I definitely hope to go to
more like this in the Boston area. I met other local developers, I learned
new things, and I even got some free pizza out of it. What more is there to