1) Typed languages are worse, and you want people with high levels of competence.
2) Java actually IS terrible. You win very little by designing for incompetent coworkers. Plan for competence, and hire appropriately. Small elite teams beat large incompetent teams every time. See #1.
3) Thinking through scalability upfront matters in many systems. Not all systems. Many systems.
4) SOLID is one way to do things, and not always the right one. OO isn't always the right one either.
5) YAGNI is more complex... you shouldn't build what you don't need yet, but you should architect for reasonable changes to requirements. Scope out all possible features early in the system design, create an architecture that supports them, and then implement the minimum viable system which can be easily incrementally refactored into that architecture.
6) There are ways to interview well. When you figure them out, you'll notice they give you a competitive advantage (while sharing them doesn't make the industry more efficient as a whole, and makes them less effective, so if you're smart, you'll keep them to yourself).
Hard agree with 4 and 5. Soft agree with 6, I think there's nothing's wrong with sharing specially since many of the important teachings are incompatible with the kind of people for whom these lessons are not obvious after a couple of years of experience.
But points 1 to 3 give me a visceral negative reaction. I'll go into detail:
1) If you're writing anything that's not a script with a few lines, and you care about your software not being terrible to maintain and change for other people in real production settings, typed languages wipe the floor with dynamic languages (excluding ecosystem moats, just judging the languages).
Good types act as documentation, a higher form of tests, and a form a development paradigm to make it easier to iterate through code new or old by building/modifying stacks of machine-checkable assertions that you can pass around.
Not enough devs are taught how to think with types and extract the most out of them, but any half-decent dev can be taught how to do it in a few days and the difference is night and day to anyone who has experienced it first-hand.
2) Java is terrible, but it's not as unworkable as some other mainstream languages given its extensibility and ecosystem. Java was sold to managers as "prevents cheap workers from making mistakes", but it was never about that and it's mostly terrible at it.
3) I would say that's a deceitful take, for only the absolute minority of systems have to care about scaling beyond a single server with failover (and a separate database if going with managed DB). For those systems that absolutely do care about horizontal scalability the answers should be absolutely obvious to any senior dev from the moment the requirements are stated. And for those cases where someone feels there may be a need for a complex scalability solution but there's not an obvious case for it yet, development will most of the time be better off starting with the simple solution and selectively optimizing as needed, just don't make it impossible to switch later down the road.
> 1) If you're writing anything that's not a script with a few lines, and you care about your software not being terrible to maintain and change for other people in real production settings, typed languages wipe the floor with dynamic languages (excluding ecosystem moats, just judging the languages).
I really hope the typed-vs-not-typed debate is over... types > no types. However... I used to believe that types were essential. I now believe that they are more like a luxury. Good tools are a luxury, not fundamental—it’s way more important to have good software design, and the core of good software design is really tool-independent. It requires deep understanding of whatever problem you’re trying to solve, not a deep understanding of software tools—-unless you’re unlucky enough to be building some horrible middleware.
I also like to dabble in photography, where you see a similar phenomenon. When I take a really great photo, people sometimes remark, “wow, you must have a really great camera!” No, actually, that’s the least important part of the equation. There’s a reason why Canon’s top-of-the line lenses are the “L” series—the L is for luxury. They make the job a little easier, but they’re not really essential.
> 1) If you're writing anything that's not a script with a few lines, and you care about your software not being terrible to maintain and change for other people in real production settings, typed languages wipe the floor with dynamic languages (excluding ecosystem moats, just judging the languages).
It's sort of the other way around. Typed languages result in most code being better, but completely prevent some design patterns. I have yet to run into piece of Java code -- beyond the completely standard use-case of a database-backed e-commerce / employee / inventory web site -- which doesn't go through one or two architectural contortions somewhere due to being forced into a specific paradigm.
The wins throughout the code from static take a back seat to the architectural contortions from not being able to express what you want.
Now, with incompetent developers, perhaps you want to prevent some design patterns, but those are workplaces I avoid like the plague.
> Java was sold to managers as "prevents cheap workers from making mistakes", but it was never about that and it's mostly terrible at it.
What do you think it's about?
I think that's a fair sale. If you're making a generic business system (you have things -- employees, inventory, customers, etc. you want to manage, which map 1:1 to objects, and which are exposed through a UX), it's nearly perfect, and you'll never hire qualified devs to work on those sorts of systems.
> 3) I would say that's a deceitful take, for only the absolute minority of systems have to care about scaling beyond a single server with failover (and a separate database if going with managed DB). For those systems that absolutely do care about horizontal scalability the answers should be absolutely obvious to any senior dev from the moment the requirements are stated. And for those cases where someone feels there may be a need for a complex scalability solution but there's not an obvious case for it yet, development will most of the time be better off starting with the simple solution and selectively optimizing as needed, just don't make it impossible to switch later down the road.
My experience -- having done a few successful startups and one or two failures -- is that it's critical to plan for success down the road. A major mode of failure is that decisions made early prevent success down the line. The system doesn't need to be scalable on day 1, but it absolutely positively needs to be designed for scale. The world is unpredictable, and you don't know the moment you'll hit exponential viral growth. At that point, you need to be able to refactor the system to hit scale virtually overnight. It doesn't always happen, but if you don't plan for it, it will never happen. It's the successes that define your career (and your bottom line).
The way I tend to design systems, they tend to run on 1-3 servers on a random cloud provider (depending on level of failover), but they use abstractions mapping onto scalable architectures (e.g. generic key-value stores and similar). If I do need to scale, it's a refactor away. A system I'm working on right now has an especially complex data pipeline. Thinking through scalability cost a few months time since it is complex, but without that, if we do hit scale, we'd hit a glass ceiling. As is, for now, we're sitting on top of a non-scalable managed RDBMS. If we do hit scale, I can migrate seamlessly to a horizontally scalable setup. At that point, we'd need to grow the team several-fold (esp. dev ops), but if you're scaling, that's okay; it's a fine problem to have.
I've advised startups, and ones which don't think through the long-term (and not just scalability; total addressable market, monetization, architecture to target adjacent markets, etc.) almost always fail, and if they succeed, it's by sheer, dumb luck.
Many would desire elite teams. On the other hand, such capable programmers are not the norm. Most are stuck with what they get and have to make it work.
There is a self-reinforcing network of assumptions in that statement:
- Good architecture beats good code.
- There are things I can express in dynamic languages which are hard to express in static languages.
- If you're not expressing those things, typed static languages win.
- When you're contorting your architecture to fit into static languages, dynamic ones win.
- Of course, if you don't have experience with dynamic programming, you won't think to express certain things or structure code certain ways.
There are, of course, academic languages which do both well (including optional static type systems for Lisp), but I'm not aware of any in widespread industry use (with an ecoystem of libraries, documentation, etc.).
Good enough code that works, at the right time, beats good architecture. Too many examples in computer science history.
Simple, clean code that works is the best way to express logical intent.
Eventually, everything compiles down to byte code. You can do it the easy way or the hard way.
Industry will use the most effective tool. Academics can experiment with high level concepts, but if it doesn't scale out, it won't be popular in the industry.
1) Typed languages are worse, and you want people with high levels of competence.
2) Java actually IS terrible. You win very little by designing for incompetent coworkers. Plan for competence, and hire appropriately. Small elite teams beat large incompetent teams every time. See #1.
3) Thinking through scalability upfront matters in many systems. Not all systems. Many systems.
4) SOLID is one way to do things, and not always the right one. OO isn't always the right one either.
5) YAGNI is more complex... you shouldn't build what you don't need yet, but you should architect for reasonable changes to requirements. Scope out all possible features early in the system design, create an architecture that supports them, and then implement the minimum viable system which can be easily incrementally refactored into that architecture.
6) There are ways to interview well. When you figure them out, you'll notice they give you a competitive advantage (while sharing them doesn't make the industry more efficient as a whole, and makes them less effective, so if you're smart, you'll keep them to yourself).