> I don’t know if structural engineering works like this, but I do know that software engineering doesn’t.
Structural Engineering (generally construction engineering) does work like that. Following the analogy, the engineers draw; they don't lay bricks. But, all the best engineers have probably been site supervisors at some point and have watched brick being layed, and spoken to the layers of bricks, etc. Construction methods change, but they don't change as quickly as software engineering methods. There is also a very material and applicable "reality" constraint. Most struct's knowledge/heuristics remains valid over long periods of time. The software engineers' body of knowledge can change 52 times in a year. To completely stretch the analogy - the site conditions for construction engineering are better known than the site conditions for a large software project. In the latter case the site itself can be adjusted more easily, and more materially, by the engineering itself i.e. the ground can move under your feet. Site conditioning on steroids!
Ultimately, that's why I agree fully with the piece. Generic advise may be helpful, but it always applies to some generic site conditions that are less relevant in practice.
My father mentored some engineering college students about 15 years ago. He came away from the experience a bit disappointed: they knew how to model a part, but not how to machine one. When he came up in the world of slide-rule-and-drafting-pencil mechanical engineering, every engineer knew, in principle at least, how to machine a part; such knowledge was necessary for good designs because a design was instructions to shop-floor personnel on how to make the part, including info like materials to be used, tolerances, tools, etc.
It sounds like you are making the argument that there is no established way to generate good software. If that's the case, then software isn't engineering, but rather art. The former requires established/best practices to be called a discipline, while the latter is a creative endeavour.
That's true. I do. I consider it a creative art, with some disciplinary adjacency to engineering. The creative sculptor has to know the material stone in order to make anything good with it. But, construction engineering is creative too; just different.
NASA is a bit of an outlier. In the 50's through the 70's any failure, particularly a failure involving the loss of a life, would have been a national catastrophe; a blow to national prestige. So, they were super careful that it didn't happen. The spent-cost was irrelevant compared to the reputational value at stake. Honestly, it was a wise investment given the operative quid pro quo in those days. Maybe they still do good software, I don't know, but I suspect that the value at risk today makes them more cost averse, and less sensitive to poor software.
"Business" runs the same calculations. I'd posit that, as a practical matter, most businesses don't want "good" software; they want "good enough" software.
A lot of this is because while a 'good' business is waiting for the 'good' software to be written, some crappy business has already written the crappy software and sold it to all the customers you were depending on. In general customers are very bad at knowing the difference between good and bad software and typically buy what looks flashy or the sales people bribe them the most for.
Reading that particular section made me think of the tree swing cartoon [1]. I agree that the best engineers have likely been on the ground making concrete changes at some point, watching bricks being laid as you said, but I have encountered quite a few supervisors who seemingly had no idea how things were being implemented on the ground. As the post says, people on the ground then sometimes have to figure out how to implement the plan even if it ignores sound design principles.
I don't view that as a failure of abstraction as a design principle as much as it is a pitfall of using the wrong abstraction. Using the right abstraction requires on the ground knowledge, and if nobody communicates that up the chain, well, you get the tree swing cartoon.
I agree with you. But, talk too long or too fulsomely about "abstractions" or "principles" and you'll lose the brick layers. They're paid by the course, generally. Trust them to make the site adjustments, but always verify that it's not a bad-bad-thing.
> Nah, those changes are only in the surface, at the most shallow level.
Very strongly disagree.
There are limitless methods of solving problems with software (due to very few physical constraints) and there are an enormous number of different measures of whether it's "good" or "bad".
Once again, that's only true at the surface level.
If you dig deeper you'll realize that it's possible to categorize techniques, tools, libraries, algorithms, recipes, whatever.
And if you dig even deeper, you'll realize that there is foundational knowledge that lets you understand a lot of things that people complain about being too new.
The biggest curse of software is people saying "no" to education and knowledge.
> Once again, that's only true at the surface level.
Can you provide concrete examples of the things that you think are foundational in software? I'm thinking beyond "be organized so it's easier for someone to understand", which applies to just about everything we do (e.g. modularity, naming, etc.)
For every different approach like OOP, functional, relation DB, object DB, enterprise service bus + canonical documents, microservices, cloud, on prem, etc. etc., they are just options with pros and cons.
With each approach the set of trade-offs is dependent on the context that the approach is applied into, it's not an absolute set of trade-offs, it's relative.
A critical skill that takes a long time to develop is to see the problem space and do a reasonably good job of identifying how the different approaches fit in with the systems and organizational context.
Here's a real example:
A project required a bunch of new configuration capabilities to be added to a couple systems using the normal configuration approach found in ERP systems (e.g. flags and codes attached to entities in the system controlling functional flow and data resolution, etc.). But for some of them a more flexible "if then" type capability made sense when analyzing the types of situations the business would encounter in these areas. For these areas, the naive/simple approach would have been possible but would have been fragile and difficult to explain to the business how to get the different configurations in different places to come together to produce the desired result.
There is no simple rule you can train someone on to spot when this is the right approach and when it is not. It's heavily dependent on the business context and takes experience.
> Can you provide concrete examples of the things that you think are foundational in software?
Are you really expecting an answer here? I'll answer anyway.
• A big chunk of the CompSci curriculum is foundational.
• Making wrong states unrepresentable either via type systems or via code itself, using invariants, pre/post-conditions, etc. This applies to pretty much every tool or every language you can use.
• Error handling is a topic that goes beyond tools and languages, and even beyond whether you use try/catch, algebraic objects or values. It seeps into logging and observability too.
• Reasoning about time/space and tradeoffs of algorithms and structures, knowing what can and can't be computed, parsed, or recognized at all. Knowing why some problems don’t scale and others do.
• Good modeling of change, including ordering: immutability vs mutation, idempotency, retry logic, concurrency. How to make implicit timing explicit. Knowing which choices are cheap to undo and which are expensive, and design for those.
• Clear ownership of responsibilities and data between parts of the system via design of APIs, interfaces and contracts. This applies to OOP, FP, micro-services, modules and classes, and even to how one deals with third party-services beyond the basic.
• Computer basics (some of which goes back to 60s/70s or even back): processes, threads, green memory, scheduling, cache, instructions, memory hierarchy, threads, but races, deadlock, and ordering.
• Information theory (a lot goes to Claude Shannon, and back): compression, entropy, noise. And logic, sets, relations, proofs.
I never said there is a "simple rule" only foundational topics, but I'll say again: The biggest curse of software is people saying "no" to education and knowledge.
> Are you really expecting an answer here? I'll answer anyway.
Yes, and thanks for the examples, it's now clear what you were referring to. I agree that most of those are generally good fundamentals (e.g. wrong states, error handling, time+space), but some are already in complex territory like mutability. Even though we can see the problem, we have a massive amount of OOP systems with state all over the place. So the application of a principle like that is very far from settled or easy to have a set of rules to guide SE's.
> The software engineers' body of knowledge can change 52 times in a year
Nah, those changes are only in the surface, at the most shallow level.
I think the types of items you listed above are the shallow layer. The body of knowledge about how to implement software systems above that (the patterns and approaches) is enormous and growing. It's a large collection of approaches each with some strengths and weaknesses but no clear cut rule for application other than significant experience.
> I think the types of items you listed above are the shallow layer
They are not, by definition. You provided proof for it yourself: you mention the "body of knowledge [...] above that", so they really aren't the topmost layer.
> is enormous and growing
That's why you learn the fundamentals. So you can understand the refinements and applications of them at first glance.
> They are not, by definition. You provided proof for it yourself: you mention the "body of knowledge [...] above that", so they really aren't the topmost layer
I said "shallow", not "topmost".
> That's why you learn the fundamentals. So you can understand the refinements and applications of them at first glance.
Can you explain when (if ever) a person should use an OOP approach and when (if ever) he/she should use a functional approach to implement a system?
I don't think those fundamentals listed above help answer questions like that and those questions are exactly what the industry has not really figured out yet. We can see both pros and cons to all of the different approaches but we don't have a body of knowledge that can point to concrete evidence that one approach is preferred over the many other approaches.
> I can, and have done several times, actually, for different systems.
The reason I asked that question isn't to be argumentative, it's because, IMO, the answer to those types of questions are exactly what does not exist in the software engineering world.
And talking through the details of our different opinions is how we can understand where each one is coming from and possibly, maybe, incorporate some new information or new way of looking at things into our mental models of the world.
So, if you do think you have an answer, I am truly interested in when you think OOP is appropriate and when functional is better suited (or neither).
If someone asked me that question, I would say "If we're in fantasy land and it's the first system ever built and there are no variables related to existing systems and supportability and resource knowledge, etc., then I really can't answer the question. I've never built a system that was significantly functional, I've only built procedural, OOP and mixtures of those two with sprinklings of functional. I know there are significant pros to functional, but without actually building a complete system at least once, I can't really compare"
You asked whether one should use OOP or FP to implement a system.
I can answer that, and did in the past, as I have done projects in both OOP and FP. But before I answer, I ask follow-up question about the system itself, and I will be giving lots of "it depends" and conditions.
There is no quick and dirty rule that will apply to any situation, and it's definitely not something I can teach in a message board.
Respectfully, I disagree. You're correct on the facts, but any "new techniques, materials and tools" need to be communicated to the brick layers. That takes time and effort i.e. it all needs to be actively managed. The brick layers have to be able to work with those new techniques and materials. I don't want some of them using method #1 over here, and method #2 over there, unless I'm wholly conversant with the methods, and fully confident that it'll all mesh eventually. The system i.e. the whole shebang has to work coherently to serve its purpose.
> Respectfully, I disagree. You're correct on the facts, but
I'm fine with the disagreement if you say I'm correct. ¯\_(ツ)_/¯
> any "new techniques, materials and tools" need to be communicated to the brick layers
Same for software.
> That takes time and effort i.e. it all needs to be actively managed. The brick layers have to be able to work with those new techniques and materials.
Same for software.
> I don't want some of them using method #1 over here, and method #2 over there, unless I'm wholly conversant with the methods, and fully confident that it'll all mesh eventually. The system i.e. the whole shebang has to work coherently to serve its purpose.
Same for software.
Virtually every profession has a body of knowledge that's constantly getting updated. Only software engineers seem to have this faulty assumption that they must apply it all immediately. Acknowledging it's a false assumption leads to a better life.
The challenge would be to control the pace of the evolution of the body of knowledge, but more importantly, its application, to a pace that's consistent with the pace of the system you're building.
> faulty assumption that they must apply it all immediately
No truer word was ever said. Everyone is attracted to shiny things.
Structural Engineering (generally construction engineering) does work like that. Following the analogy, the engineers draw; they don't lay bricks. But, all the best engineers have probably been site supervisors at some point and have watched brick being layed, and spoken to the layers of bricks, etc. Construction methods change, but they don't change as quickly as software engineering methods. There is also a very material and applicable "reality" constraint. Most struct's knowledge/heuristics remains valid over long periods of time. The software engineers' body of knowledge can change 52 times in a year. To completely stretch the analogy - the site conditions for construction engineering are better known than the site conditions for a large software project. In the latter case the site itself can be adjusted more easily, and more materially, by the engineering itself i.e. the ground can move under your feet. Site conditioning on steroids!
Ultimately, that's why I agree fully with the piece. Generic advise may be helpful, but it always applies to some generic site conditions that are less relevant in practice.