At my company we put a big emphasis on code reviews. We encourage devs to pull request code fairly regularly to keep PRs relatively small (when possible) -- before so much code has been written that it's not really possible to change course without blowing up deadlines. We encourage our junior devs (who might not be capable of identifying bugs or proposing fixes on code written by a senior) to ask questions in their code reviews -- to verify assumptions, to request an explanation of how something works, confirm that a particular edge case has already been considered, etc. It can be hard to get a junior dev comfortable with doing this (questioning a senior dev), but even if the junior isn't identifying bugs it will often lead the senior to better understand their own code and the architectural concepts that underpin their own coding decisions. Like the author points out, this only happens because the senior dev endeavors to explain their work to the junior dev (Protege effect). Also, a good many times it leads the senior dev to re-consider how they wrote something and they might add a revision to address a possible edge case not previously considered. I hadn't thought of it this way before, but this is the Socratic method that the author talks about.
We also put a big emphasis on in-code comment writing -- largely following the commenting principles laid out by John Ousterhout's "A Philosophy of Software Design". These comments are of course for long-term maintenance purposes, but they also benefit team learning. Class, method and variable naming are obviously important too. Our internal code reviewing mantra is that 'I want to be able to read your code like a story book -- when I get to the end, I at least want to be able to understand what happened'. Not always possible, but a good goal. Writing comments and choosing class/method/variable names in pursuit of that goal massively contributes to the learning of the team. During our code reviews, one of the most common requests by reviewers is for the author to add a comment explaining something that was very difficult (or impossible) for the reviewer to grasp on a first read.
This approach has worked very well for us. Everyone learns and our product quality improves.
In the 18 years since I graduated (I feel old), I have seen some people easily carry entire projects while demotivating everyone around them… and also colossal idiots who were just as confident and unwilling to listen.
I really hope I never end up unable to listen to critics.
For juniors this is even worse, they get to wait until PR time to validate their design. With trunk based development this means continually commiting unreachable code with back and forth with more senior staff via PRs, instead of sitting down for an in depth discussion where they'd actually learn how to do this job.
This isn't really aimed at the parent poster, just an observation. I've been working since 2006, GitHub brought in PRs and I think we lost something over night: code reviews where you get to sit with more senior staff and discuss your code.
Depending on the company, the design discussion you're talking about has happened:
1. In verbal discussions with other devs before fingers ever touch keyboards
2. In long-form writing (Text docs, then Google docs, then later Notion)
3. In per-project slack channels
4. Out loud, on a whiteboard.
Right now it's very much #4 because my company is 2 devs and a founder. But even here, I wouldn't expect to get anything non-trivial into pull request before figuring out the overall structure with the other dev verbally or in writing.
But yes, we generally break things down into the smallest meaningful chunk possible to deliver. If that chunk is too small to understand the larger work that it's part of (as is usually the case for non-trivial work), we can discuss the larger work in another forum (ad-hoc verbally, via design doc, via meeting, etc).
I thought it was a great process.
While there may be exceptions, I default to: if an app is so messy as to consider a more complex architecture, it probably has so much going on as to be difficult for the end user to use it.
https://blog.pwkf.org/2022/09/18/always-optimize-for-dummies...
> ...PRs relatively small (when possible)
> ...deadlines
Truth is if you are doing the kind of work that fits into code reviews, small PRs and neat deadlines, does any of it matter? You're describing a tech enabled agency, not a startup. Sure customers have alternatives, but in the same sense that we have choices when booking airline tickets: you are describing a development process for a product that is fundamentally fungible, so the main differentiator among producers is costs, not management strategy.
If I'm doing a big chunk of work, I still do it in small PRs. That first PR (or a design doc) might outline a strategy for the ones that follow, but still try to have small PRs. Or, worst case, I do a big chunk of work and break it out into small logical chunks for review.
And even startups can have deadlines.
To me, the definition of junior is someone who needs guidance. If you don't have a good process of defining tasks before they're worked on and real code review before things get merged, you are not set up to work with juniors, and hiring them is doing both yourself and them a huge disservice.
Junior job titles are nearly as much of a mess as interviewing them.
Particularly in recent hot topics like AI the reality is you want both experienced and less-experienced devs. Most AI teams I see actually lack AI experience and keep falling for the same issues (like quickly getting to 80% working and thinking just a bit more data to 99.9%)
In this case, nobody really kept an eye on how things were being built, and the person was actually remarkably productive. I really don't have a bad word to say about them: they were given vague tasks and came back, for most of them, with working implementations. We're only a handful of people and everybody was busy elsewhere, but what little guidance and review we could offer was always accepted with much gratitude. They lasted about 18 months before moving to somewhere that offered more support, and I can't blame them at all.
What happened is predictable: things that ought to be in one place end up distributed in little pieces, and existing features got invasively modified to add new features even when that wasn't necessary. Poor separation of concerns, design patterns applied wrong, all of the stuff that over time adds up to a codebase that's hard to work with.
I think a lot of the refactoring we do would make a good book, actually, if any of us were the type to write about programming.
...doesn't quite square with:
> I'm still cleaning up after the unsupervised junior two years later.
I can appreciate that misfactored code now helps "flatten the curve" and skirt under whatever deadlines you were respecting——even at the cost of a long tail of reactors——but its a shame that junior dev isn't around to learn from their mistakes, and also that they weren't paired with a more senior dev who could've coached them through those reactors at the time, enriching both the codebase and the human capital.
This has been immensely helpful in New Hampshire because talent is more sparse, and lots of good people would love to stay in NH if only there were jobs at graduation. It turns out plenty are willing to if they have an offer well ahead of time.
This won't work for companies trying to blitz-scale everything, but I bet it would work for a lot more than the amount trying it. And it would especially work for companies located outside major metros.
I wrote a bit about our process here: https://simonsarris.com/p/growing-software-developers
But the words you used in your comment are so bad! Communications is your job!
"Policy?" It's a recruiting strategy. Why on Earth did it occur to you to use the word "policy?" It's not a policy!
"Only?" Not true. You mean that you've observed something works for you. Then you've one-armed-bandited it, and it kept working. Which is great!
"Junior?" No dude, don't dump on your people. This is a talent development program. Nobody calls the Mickey Mouse Club "junior" actors.
"New Hampshire because talent is more sparse:" Don't dump on New Hampshire, you live there. Try, "New Hampshire is an underrated community."
"This won't work for companies trying to blitz-scale everything:" Nobody set up this straw man but you.
"...outside major metros." Don't dump on your community!
The miscommunication on "policy" alone got the high-drama people out of the woodwork and derailing an interesting comment thread.
Even people with university CS programming experience will in reality have only learned a fraction of what's involved in writing and maintaining production code for a business.
But it doesn't discriminate on a prohibited basis (the decision to only bring in developers as novice interns itself; if the way you are choosing interns does, sure, that's a problem, but its orthogonal to the issue), so that's not a problem.
Age discrimination is allowed within limits. It's even in the Constitution.
It is unconstitutional to have representation determined by land, not population. The structure of the US Senate would be unconstitutional were it not written into the Constitution as an exception.
This indicates that the settlement was based on legal costs associated with a fight the company would otherwise have won.
Notably they did not change their hiring practices after the lawsuit....
I don’t think all generalists are juniors nor are all juniors generalists.
Why lump them together here?
We need more experienced generalists in our industry.
Specialism vs generalism is very much a mindset of a person and not strictly dependent on their past experience. I suspect it has much more instead to do with their ability and willingness to build a mental abstraction behind the concrete implementation they have experience with.
To refine the conceit: A specialist will see only the tool, but a generalist will see the way the tool solves a specific problem and get an idea for how other tools can solve it.
I'm being a little hard on specialists here; a good specialist may often have a far more thorough understanding of how to wield their chosen tool and come up with a better solution using it... Assuming they aren't trying to hammer in a screw, of course.
A senior dev is a specialist in your company, a junior often has pretty broad skills that apply across companies.
So while they may also have the generic skills that could get them hired into an unspecialized role, they're likely not applying for those.
Not all generalists choose to, or even can specialize. They don't cease to exist once they've accrued enough experience. Nor does having a lot of experience mean you're specialized in any one thing.
You can be senior, have loads of experience, and still be a generalist.
At a certain point, you would be capable of fulfilling a specialist role in those tools, whether you choose to apply for one or not.
When people say specialists, what they mean is SMEs hired to do one specific, specialized role. You can be an SME in something and be hired into a generalist role, or a generalist hired into a specialist role. Whether you are a specialist or a generalist is down to your job role, not your skills. An SME in e.g. reverse engineering who quit IT and now runs a llama farm/ cafe (the dream) is not an RE specialist, they're a llama farmer.
Totally agree on the huge impact, et al. And for available jobs without a job posting, this remains as you say. But when a hiring manager goes to HR/recruiting and a job posting is generated, it is never for a generalist.
So, an experienced generalist has to skip over specific postings, simply look at who is hiring at all (or growing headcount as evidenced by other data points), and find a way in to pitch themselves.
I kid you not, it's a real junior-level position description a friend* had sent me just yesterday (was a screenshot, or I would've linked it).
[*] Shameless plug if someone's hiring: my friend is a Pythonista, looking for a junior-level job in the US (she's a green card holder): https://nvp85.net/
I don't agree with the dichotomies that the author lays out here, for example the idea that juniors are generalists and seniors are specialists or the claim that you need juniors on your team in order to have a culture of teaching and cross-training. But I do think that hiring juniors is important to the health of the industry and can be beneficial to many orgs.
It seems like everyone wants to hire a senior dev, but nobody wants to train the juniors into seniors.
In my experience, all hiring is a gamble. Hire a bad junior and you run the risk of them being dead weight, or worse, they fuck up your codebase and drain time and resources from your more useful devs. Hire a bad senior and they're about as bad, but you sunk a lot more money into their paychecks. Hire a good junior and you get awesome work for a discount, though you'll need to promote them before they learn their worth and move on. Hire a good senior and you'll have someone who can build whatever you need, diagnose any problem, lead a team, teach skills to their coworkers, and so on.
Also, it will always depend on your org and your team. Some big companies have new grad programs where they have programs to teach and onboard people so that they can effectively absorb huge cohorts of juniors. They've run the numbers and have determined it's worth the investment. On the other hand, some companies simply don't need juniors at all. Think early stage startup or a lean stable small to mid-sized company; at places like that you can really do everything with 10-20 good seniors.
The further you go beyond senior engineer, the wider the audience, but you start developing the skills at the 1-1 level.
Or it can be near impossible. Large orgs can have dedicated onboarding programs for junior developers, this can work quite well. Small or medium orgs can have one or a few senior developers who are passionate about mentoring. This can also work well, but is unusual.
What is much more common is for new hires to encounter a nearly impenetrable wall of “figure it out, don’t bother me”. I have experienced both, and I’m sad to relate I’ve been a wall at times. I found I could only explain a stack trace n times to the same person before I personally noped out of training juniors.
It made me really start to learn on my own and figure out how go from 0 on many different skills. So personally I really think it’s about the junior and how much they’ve figured out their learning style, and being “a wall” like this can sometimes force them to learn by reading through all of your old code. Inadvertently leading by example is still really good
In short don’t sweat it
I want to be part of the solution to this industry-wide problem; it pains me to see people I'm mentoring struggle to break into the industry now after I got a new lease on life from a few key folks deciding to give me an opportunity as an unproven dev. The ladder is being pulled up, but I don't know how to help push it back down without career changing into leadership.
Agencies and consultancies the best places to learn as a junior IC. Reviews, process, and management are built in and there's a ton of variety. You also get opportunities to try a bunch of different hats before deciding where to specialize.
However, I would not encourage learning at an agency or consulting service. The best place to learn by far is at a large corporate company, where you have the time to learn good programming practices, and people to teach you how to do it well. The problem with consulting is that you're always working on a short-term issue, and never learn the value of writing good code for long-term support.
I think the best path for someone starting out is a year or two in a big corporate, then move to something small where you get to do everything. Of course, this seems like a bad thing for big corporates, so they should probably work out how to give devs a better path through their own companies.
There are plenty of recent grads out there who already know how to build software, will work for cheap, and will grow faster than the business increases their salary. That has historically been the selling point for "junior" devs.
The opposite is true of hiring senior devs. Many of them will not have learned enough to justify the premium that they demand in the market. They entered the workforce sooner, but that's about it.
Like "value investing" this is "value hiring", go long on people who are undervalued by the market, go short on people who are overvalued by the market. This is what the best hiring managers do.
Sure, you can't take someone who's never programmed anything before and train them on the job in a startup... but you can't do that in a large company either.
But every company has small tasks and spikes that they can hand to junior employees. If not, the startup is probably not breaking down the work very efficiently.
My first job as an engineer, I joined a mid-sized startup with around 150 people. My team had 8 people including me. I was very much a junior engineer (if not entry-level for that role) at that time, but I was given tasks that fit my experience level, as well as leeway to branch out into more challenging projects. Moved from junior role to mid-level, and then on to senior (7+ years later, of course).
That company had very low turnover, because people saw the company investing in their growth (and I don't mean paying for training, I mean actively nurturing their skills in their work).
Companies who want to hire only mid-level workers or up will likely find the mid-levels bogged down with all the little tasks that junior workers could be handling for them.
That makes the mid-levels less productive, which is the worse thing for a startup to be.
Senior dev is about skill mot time in industry
I would say this is true if you define "plenty" to mean "very few."
Plus you may learn something. A couple of bright Junior Developers showed me some nice tricks I was uaware of.
Then we’re going about it all wrong, and shouldn’t have “senior” devs hiring “junior” devs but “teacher” devs hiring “student” devs. And when I say “student” I mean someone who is willing to go through the pain of not knowing, who will keep an open mind and give new things a try. And when I say “teacher” I mean someone who will study teaching to the same level that they study tech, who will be patient and empathetic.
But this is not how most companies operate, nor is it how most people want to work. Consider promotions for example: Juniors are highly incentivized to work independently to become seniors. And seniors compete with each other to have their solutions adopted, rather than agree to explore a new approach and reevaluate if necessary.
I fully agree with the author’s sentiment.
Many companies see junior engineers as burdens who’ll suck up valuable time and resources of the company and their senior colleagues, and completely miss the point that junior engineers bring some invaluable but intangible benefits to a team.
Sometimes, it’s the junior eyes who’ll notice something those of us who can be a bit stuck in our ways wouldn’t immediately notice. This youthful energy is the same reason why a lot of startups can enter markets already dominated by huge, experienced, and well-resourced players, and start eating their lunch.
The best and most underrated value I think a team gets from junior engineers—which the author highlights—is learning how to break down and explain things. The ability to collaborate and teach is something many folks may underestimate until you end up in an environment that sucks at both.
That said, it’s probably not ideal to bring junior engineers into an environment that’s not prepared to deal with them. You need to be prepared to really invest in them and their success to see the true value they can bring to your team.
So hire generalist seniors? They exist.
Sounds like the author wants to patch a broken hiring system (only specialists get hired as seniors) by throwing juniors at it. Throwing juniors is a time-honored solution to many problems but while it tends to be somewhat viable and quick to implement it's also a sub-optimal solution.
When I started out, entry level was called "Staff" and then "Senior" was above that. Above Senior you had at least one foot in management, titles were maybe "Lead" or various manager/director titles.
Soft skills is more important than developer skills in my eyes, but not the only requirement. For Juniors, its probably the highest, followed by an ability to learn and adapt to new technology.
Surely a junior typically want to learn, so he/she explore the world, without much prejudices, but hardly have "the big picture" in mind especially current junior devs out of a schooling system who forge at best useful idiots[1] not fresh and curious people.
Personally my take is that company need a different architecture with NO MANAGEMENT AT THE TOP, meaning companies must be driven by entrepreneurs not beancounters, and technicians must be at the same level of managers because anyone have only a partial vision and the entrepreneur do the synthesis.
[1] https://www.theatlantic.com/ideas/archive/2020/08/i-was-usef...
LLMs are good aide for developers of all skill levels, capable of giving them ready answers to near-textbook questions (which juniors may not know and more senior folks may be just lazy to type).
If you’re writing usual CRUD-type applications, that is.
Anything more complex, and these LLMs will make something up that looks very close to what you want, but will have subtle bugs in it that’ll take a lot of time to figure out.
Some time ago what I was working on was a “textbook” question (as you say) involving binary tree and sets as part of a firewall management script I was writing; and I eagerly accepting that code completion that seemingly looked right caused a lot of traffic to be unintentionally blocked.
For sure, LLMs aren't good at designing things, so accepting large pieces of code is not just risky of having subtle bugs but more likely that it's not going to work at all.
But anything complex is made of simple bits, and LLM helps with those small building blocks, realizing the patterns you're following and saving time typing. Figuratively speaking, a LLM won't write you a working DOOM engine, but it can spot when you're going for that fast inverse square root trick.
> I eagerly accepting that code completion that seemingly looked right
And of course one must proofread, and do it carefully. However, reading is faster than typing - especially when one already knows what they wanted to type, and got a code snippet autocompleted that looks precisely or very closely to it.
And, yes, If a snippet looks even slightly different from your vision - it's really important to double-check it (and maybe write a test) and make sure it does the right thing. Subtle bugs are possible (I also had one story like that, when LLM put a wrong variable in one place and I glanced over it without noticing), but they're not that frequent and they're also possible in 100% handcrafted code.
LLMs are for the boilerplate.
My experience is: at high skill levels it's harmful, so I'd disagree with 'all skill levels'.
I treat LLMs just as a fancier keyboard for near-boilerplate. When I give a prompt I know what I want them to output, cycle completions until I get a snippet that looks close enough to my liking, then edit it to fit. Super helpful.
Another use case was learning a language and SDKs I've never even dabbled with before (Swift and WatchKit). It generated awful architecture (that I think even a junior developer would realize as stinky) and it had limited knowledge about recent Swift language features (async), but gave me just-good-enough samples to get me started - better than a book could have. Can't say I learned Swift that way (didn't need to) but I made a tiny WatchOS app for personal use over in a single evening because LLM gave me a good boost.
And then, LLMs can be just a better autocompleters - it feels nice when you get all arguments correctly listed before you even type the first letter, because LLM had guessed it right from the names (it doesn't always happen, of course).
I can imagine that being too lazy and just blindly accepting LLM completions without thinking or double-checking can be a bad habit, but that sounds more like a risk for a junior than a senior.