Here, I'll focus on one particular problem - making technical changes that require the buy-in of a whole technology group. These are drastic changes in the codebase - introducing a new framework, switching your ORM, adding a new type of database, adding a new level of automated testing. I see leading technical changes across a codebase as one of the key responsibilities of a senior developer, and I've led several of these in my career. (The data loading infrastructure we built on the Rackspace Cloud Control Panel stands out as probably both the most work and having had the most overall benefit for the product.)
My model for leading technical change is:
- have an idea
- anticipate resistance
- come with code
- implement everywhere
The goal here is not for you to 'win' - it's to make things better. The best ideas should win, no matter where they come from. If you've got an idea, it's on you to make its strengths shine through, but to abandon it if a better one comes along.
Have An Idea
Having the right idea really helps! But how can you develop ideas into the right ones to bring to the team?
Follow your passions. I'm particularly passionate around testing - better tests, faster tests, and making sure that tests catch things that our customers otherwise might. I'm less passionate around other things - after going overboard on SOLID earlier in my career, I find it really hard nowadays to get worked up about object factoring. "Are there tests? Okay, I can probably live with your particular preference for object responsibility." That's my internal "technical compass" and yours is likely to be completely different. If you're passionate about something, you'll have a lot more fun finding a way it can be improved.
Know the problem space by seeing how other people solve the problem. Engineering isn't science. The same concepts are continually reintroduced as part of new libraries - new technology is really just solving the same problems as the old technology, in a better way. Frontend build tooling is a good example here. I've gone from hand-rolled Maven plugins to Jawr to Closure Compiler/LESS/YUICompressor to Gulp with Browserify, and now primarily use Webpack. Each of these tools solves the same basic problem - building a frontend codebase into one that can be served to the client with a minimum number of HTTP requests. However, at each level, the tool takes on more and more responsibility. Webpack's CSS loader will automatically inline small PNGs and rename background images/webfonts into filenames based on an md5 hash so you don't have to manually purge your CDN on upload. The core concepts haven't really changed since I started doing webapp development five years ago - combine your frontend assets into a few files, shrink them as small as they can be, and utilize caching as much as possible. Putting ideas in the context of past problems both ensures you are solving real problems and allows you to leverage ideas that have worked for other teams across the industry.
Okay, so you have an awesome idea. It would definitely improve things - happier customers, happier developers. Unfortunately you can't do this one all by yourself. Now how are you going to sell this thing to the team? Here I mean "team" as basically anyone who might conceivably care about this. Generally this includes anyone working in the same technology area.
Don't assume a solution will win purely on technical merit. Again, engineering isn't science - solutions need to be implemented by actual people. It's foolish to expect that just you think that a solution is technically superior that your peers will also see this. It's up to you to sell the idea to the rest of the team.
Identify potential detractors. Knowing how people are going to react to your suggestions is pretty important. Based on what you know about them, which members of your team might oppose the idea? Of course, if there's a disagreement, there might be an opportunity to strengthen the idea and make it into an even better one. I try to have these types conversations in a 1-1 setting - "hey, I was just thinking about X, what do you think? any problems you can forsee?" Getting early feedback from individual team members will almost certainly result in a better idea - and you want the best ideas possible. (Meetings can be a good place for brainstorming, but not great for working through issues that detractors might have as the immediacy doesn't tend to encourage careful analysis.)
Come With Code
Okay, you're reasonably certain that this idea has a chance to see production - related work checks out, other members seem broadly okay with it. What's next?
Present the idea to everyone. You'll want to present this in a formalized way to everyone, maybe using a set of slides before digging into the code, maybe block off a conference room for an hour, maybe bring it up in a scheduled team retrospective team. These formalized presentations are really important in creating mind-share around new ideas and I strongly recommend them. Synchronous time lets people know this stuff is important and also helps create a positive narrative around an idea's acceptance on the team.
You must implement a prototype. This prototype doesn't need to be "ready to merge", but it does need to be a basically complete solution to the problem at hand. You can't have a meeting to propose a big piece of work that you'll only do if the team agrees. You are basically producing a demo. Demos can cut corners on certain things (tests for one), but the main goal is to prove that the idea is a viable one and will work within your codebase. It's not useful to suggest a solution that is done outside of the context of your technology stack.
Where can you find time to create this demo? You'll want buy-in from your supervisor (if they're a good one hopefully they'll encourage you!) Otherwise (to steal a line from Hunter S. Thompson), I hate to advocate nights and weekends, but they've always worked for me. (I do understand this isn't how it works for everyone...)
Awesome, the meeting went well. You've got some good feedback from the team about the way forward and it seems like you're on track to install the idea into the codebase. The awful old ways are dead, time for the new way.
You are the advocate, you must finish the job. Even after a whole team presentation, you can't expect everyone to understand everything that was proposed. They'll still be digesting the details and you are the expert on those, having implemented the prototype - you know its ins and outs. That means it's up to you to continue the legwork of getting the idea installed.
Provide good examples in the codebase. You can't expect everyone to do the right thing in the codebase just because they were at that meeting. You need to provide them with good examples in the codebase - showing them what code to mimic, basically. Just because you've provided a solution that works in one case doesn't mean that you can expect other people to generalize it to other cases - assume that you must provide leadership until the idea has been firmly implanted and other people have innovated on top of it.
Sometimes doing it everywhere is a waste of time. Of course, sometimes doing it "everywhere" would be a huge time sink and of questionable utility (this is a bigger problem in a large codebase). You may have a less-frequently updated part of the code which doesn't see a lot of development. Going through and updating this code might not end up being a good investment. On a past project, after redesigning our popover pattern to "frameworkize" the separation between the view (what the user saw in the popover) and the controller (what happened when clicking save), we chose to leave a section of our site with 18 different popovers unconverted and following a legacy inheritance-based pattern. While this made future updates to that section a hassle, I'm not convinced it was the wrong choice - we infrequently made changes to that code and over time the popovers were gradually migrated to the new pattern over the course of various hack days (though I'm sure a few of the old ones still remain).
A Recent Example: Improving Tilt's Lightboxes
The basic idea that I came up with was to use react-router for our lightboxes; we eventually landed on using query parameters for the state of which lightbox was displayed (you can see an example of this on my Github). This solved the technical problem - relatively simple, would allow redirect URIs to return to the page on mobile, and allow an easier development workflow.
I had to build team buy-in: we had recently introduced a different lightbox framework that had (finally) decoupled the "next" and "previous" concepts from an individual lightbox view (this was important because certain lightboxes would appear both inside and outside of various multi-step wizards flows). I worked with another team member to make sure that we were still carrying forward the good things from the previous refactor while introducing yet another pattern.
After this, I converted a few lightboxes from our site to use the new code, and presented a complete working demo at a retrospective: worked through some toy examples, displayed the real examples, and walked through the implementation with the team by projecting code onto a monitor. I got a list of takeaways from this, implemented them one-by-one, then got final signoff from the team in the form of a code review that I made sure to have everyone look at.
For final implementation I converted every "new-style" lightbox in the site to use the new solution - except for a flow that was under active development by a different product team. To minimize disrupting that team I held off on converting that flow beyond a "proof of concept" branch that I periodically rebased. Finally, about a month after using the new solution everywhere else, we converted that final flow and then deleted the classes associated with the old setup.
I found this example a really fun challenge - I got to learn react-router better (an exciting technology that allows for some really powerful development patterns), building team buy-in wasn't a given because we had just changed lightbox frameworks again back in December (meaning there was fatigue around yet another pattern), and the work involved in installing it turned out to be surprisingly challenging (specifically around Internet Explorer support). We've continued to build on top of this lightbox framework but that isn't to say that it will survive forever - it's always waiting to be improved further by the next great technical idea.
In this article I've walked through my thought process around leading technical change. Change leadership is a pretty important topic in general, outside of the technical context, and there are a lot of great resources out there - the book Switch is a really easy to read book about change leadership from a business perspective. Leading technical change is exciting because done right, it can lead to both better customer outcomes (less bugs around edge conditions) and a better developer day-to-day experience (less cognitive load around handling those edge conditions). Plus, you usually get to delete a lot of code!