Architecting with the Millennial Engineer

You have a web application that you have maintained for a few years, relatively bug free, and stable. Your business is growing and you’re adding new features so you go out and find a new software engineer – a millennial engineer – just out of school. The new engineer is eager and excited, quickly sets up their machine, downloads the code, and then looks with horror. They tell you they need to “refactor” everything since it is old, outdated, and has performance problems; that same application that has made you money and has been functional to this day. You sit there puzzled and don’t know what to say.

Sound familiar?

Welcome to the Age of Millennials.

New frameworks, languages, and applications have turned application development from creating and maintaining long-term assets to creating short-term code that is more easily replaced than maintained. Along with deficiencies in formal education – if universities were doing that good of a job of teaching what is actually needed, companies would not need to train new graduate hires in development programs as long or as hard as they do now – has created a perfect storm where young great engineers are graduating but are unable to help carry forward today’s systems in sustainable ways.

This article will break down some of the most popular themes and how we can architect our software to deal with them along with ways to potentially coach and mentor different behaviors. Architecture is about communication and nothing is more important than communication with the newest members of our team.

“I can make a <better> library for this.”

There is a strong affinity to the following statement “Hey, if I use this, there’s probably 100,000 other people who need to use this, so I will convert this to a library.” The statement itself is correct, but the focus turns from application development to library development. Comparing the older Maven Repository to the newer NPM module directory we see a growth explosion on the NPM side of things. With Node being one of the newer tools used by Milennials, this is something to watch.

So what can we do to avoid this? The answer lies in the engineer’s own statement thankfully. If there are that many people who need to use this functionality, chances are pretty good it already exists. A good example of this is StringUtils in Apache Commons. A lot of times there is tunnel vision on finding ways to contribute, while there is a lack of focus on utilizing what already exists. I’ve met a few engineers that were just mind-blown over the fact that StringUtils could handle whitespace, nulls, and empty string appropriately and that the library has existed for years.

“It won’t work for more than three users”

While the number can change, three seems is a common figure given the number of processors a machine generally has (four). This of course is the multithreading problem. It’s a tough concept that some frameworks and libraries try to smooth out (Go, Node, Scala, etc.) for developers, but it’s a concept that’s lost unfortunately in the education space. I’ve encountered very few students that can properly describe a semaphore. Other frameworks such as Rails and the Ruby programming language with its Global Interpreter Lock (GIL) just make the problem worse.

This one is unfortunately harder to deal with BUT not impossible. Developer management of threads is a disaster waiting to happen, but thread-safe programming is not. Localizing variables, and providing clean and clear interfaces for interactions that are pass-by-value only reduces the changes of side-effects in internal code. Languages such as Java and .NET make this easy to do. Static code analysis tools (like Firebug and Fortify) encourage this as well too. Encouraging immutability and singletons (when appropriate) also encourages thread-safe programming which will be extensible over the long run.

“I’m building a whole new function/method for this”

Instead of reusing the existing code and overloading an existing method, the engineer decides to rebuild the entire method from scratch. This generally happens in older code bases that are extremely overwhelming. Instead of tracing the invocation stack and appropriately augmenting with a new Facade or Adapter, they go ahead and just attempt to re-write everything, hoping to re-optimize all the existing Facade work and/or overloaded implementations and create one little pretty function/method.

Hopefully there’s a bunch of unit test code in your application that immediately breaks along with all the implementation compilation errors that will occur. This problem though is easily correctable and is easily identifiable. Setting up gut checks on changes, whether it is by story pointing, or just common sense; a simple functional update probably shouldn’t need 20 different files rewritten completely for a one pointer story. Schools teach overloading very well, but is sometimes lost once the engineer hits the real world. Mentor through this so they understand to overload the working unit.

“I’ve abstracted the abstraction then deleted and rewrote it all.”

This is not necessarily said, but takes the last point, of overloading to the extreme. A common scenario is trying to “future proof” a framework/solution. Instead of building a solution that we can refactor and allow it to evolve, the engineer focuses on writing it once, writing it the “right way”, and if it’s wrong, they will just write it all over again. Overloading becomes inferior to the delete key and all earlier structures get lost in this thought process.

This unfortunately is part of growth. The engineer ends up in what I call upfront shock. I’ve seen Junior and Senior engineers get stuck on this, so it’s not just a Millennial engineer problem. What ends up happening is no work gets done because everyone trying to solve every problem upfront. This completely goes against the entire Agile model. The architecture may have some holes and may not solve every edge case, but instead of trapping exceptions and evolving, we wait until the perfect solution is found. Instead of adapting, interfaces get destroyed which complicates long-term development across teams as the interfaces are the cross team communication platform. This is a huge problem in enterprise development with a lot of open source frameworks in the JavaScript world these days. Abandonware and/or breaking rewrites have dropped confidence a certain amount, especially with popular frameworks (I’m looking at you Angular). While some times required, the volume of them has seemed to increase over the years.

I <3 the Millennial Engineer

The next generation of engineers are highly engaged and motivated, which make them great people to work with. With the right coaching and mentoring, they will turn into your ninjas, rock stars, top guns, etc. in no time. Understand them, help them grow, and don’t let them get stuck in these pitfalls. The worst thing you can do is toss them into a corner as an “Independent Contributor”. Show them how to do things right, help them understand the processes, help them understand what matters from a business – as school doesn’t (time is money, we need to deliver today, risk v. cost, etc). We’ll tackle education failures at another time 😉