On the nature of computing science (1984)
cs.utexas.edu
cs.utexas.edu
People get emotional rewards from themselves from making something work that is at the limit of the complexity that they can handle. They often also get emotional rewards from others for making things that others can't understand. (They shouldn't, but they often do.)
Imagine a carpenter going: - "Yeah, so I wanted to test the limits of my abilities so I made the shed nuclear bomb proof, and yeah, that'll be $100k, now I gotta go to the reinforced concrete conference, and do you mind if I use this shed as a reference when applying to the nuclear shelter company that I actually want to work for?"
This carpenter would of course never be hired again. But our industry is overflowing with nuclear bomb proof sheds without much push back. It's incredibly unprofessional.
Yes. There were too many cases of overnight success to ignore that in our field, this works very well.
It may require thinking hard to get code that is simple (like with DRY, KISS principle should be followed in moderation. It is all about tradeoffs as usual).
I still think you could have multiple levels of skill across design and code implementation though
Our profession doesn’t really know what it is, and that makes us easily manipulated.
Most professionals have to wrestle with time constraints. Push hard enough and at some point the carpenter/doctor/civil engineer/whatever firmly says “no”.
What’s the difference in software that unbounded tech debt is permissible?
Clients regularly tell carpenters to “just do X” against the professional’s better judgement. The carpenter isn’t going to call the collapsing Jerry rigged staircase tech debt, instead they tell the client “no, I won’t do it”.
Our profession generally lacks sufficient apprenticeship. We could learn a thing or two from student doctors doing their rounds.
> Our profession generally lacks sufficient apprenticeship. We could learn a thing or two from student doctors doing their rounds.
I'm not sure how apprenticeship would solve this problem in software. To me, the difference seems to be that unlike carpenters, most people in software don't work on a contract basis for specific clients, but as an employee of a specific company. We don't have the authority to just refuse to do what we're told, and even in fairly good workplaces where you can voice technical disagreement without fear of repercussions, at the end of the day you'll often get overruled and have to go along with what you're told.
So they're only good in theory given infinite time, but not in the real world where someone's waiting to be able to use what they're working on?
When did people learn good design?
Is reducing 24 to 6 "good design?" The study controlled for the actual quality of jams.
Avoiding the hard challenges of design at any cost is certainly a factor. I've seen design demonized as waterfall, and replaced by seat-of-the-pants planning almost universally. "Design" is the opposite of "Agile" in some minds.
Time crunches and the "move fast and break things" mentality results in broken things (shocked!). Keeping a sub-optimal system running smoothly requires an investment in complex workarounds.
Customers will always bias towards new features, new buzzwords, and flashy aesthetics. They don't innately understand the benefits of simplicity - they assume more/new is better.
Software developers want to keep up with the rapid pace of technical change; they are intrinsically motivated to adopt newer technologies to avoid getting stuck on a dying career path. New technologies almost always layer on new abstractions and new dependencies - increased complexity is almost guaranteed.
Finally, we're advancing the state of the art of what computation can achieve. Pushing the boundaries of inherent complexity is effectively the stated goal.
All factors steer us towards ever-increasing technical complexity. It takes a force of nature (or really abnormally disciplined, principled engineers) to swim upstream against this current.
What happens is that features new features are added willi-nilli and these take priority over the quality of the overall product - see the triumph of MS Office in the 90s and many other situations of software companies competing.
And the companies have their priorities and their hiring and management reflects these priority even if it's just implicit in what's done. Especially, if you let older software engineers go and push the youger workforce constantly with constant fire-drills etc, and , no one will be "capable of good design" but why should they be?
OTOH, Vernon's DDDD book comes with caveats:
https://dev.to/yakovlev_alexey/do-not-read-ddd-distilled-by-...
Simplicity is a great virtue but it requires hard work to achieve it and education to appreciate it. And to make matters worse: complexity sells better.
Another good quote is;
To which we may add that, the less the new science is understood, the higher these expectations. We all know, how computing is now expected to cure all ills of the world and more, and how as far as these expectations are concerned, even the sky is no longer accepted as the limit.
The analogy raises, for instance, the questions which current computer-related research will later be identified as computing's alchemy, and whether this identification can be speeded up,
Describes the current ML/AI craze perfectly.
Sure, Lambda is fine for that small app, but I once inherited a 100k/month mess of SQS, Step Functions, API Gateway, Cognito, Lambda, ECS, AppSync, S3 and Kinesis that made me want to go into carpentry.
It wasn't simple, it was't quick to make, it wasn't cheap, it wasn't fast, and no: it did not scale (because we reached the limit of Step Functions).
The default limits are _very_ conservative in large regions
(Admittedly, by the time you've asked for those limit increases you should probably reconsider what you're doing, you're bleeding $$$ at this point)
Feeling like you’re getting a special deal overrides objective thought. There’s a bunch of this stuff in AWS and it all feels dirty and wrong.
Serverless monolith ftw
I wrote a bit on how to achieve this with .NET (but probably applicable to many other frameworks/runtimes): https://chrlschn.dev/blog/2024/01/a-practical-guide-to-modul...
(It's inspired by the Google paper, but obviously a much simpler implementation appropriate for most non-Google scale teams)
Theoretically, microservices allow for each team to deploy independently, thus the choice is made up front, before any part of the system is designed, because it looks like it reduces the effects of inter-team communication lag.
i.e. Docker lets you better push the org chart into production.
The biggest place I ever worked, I came to believe that their chaos worked because it was self organizing. They’d split a large project into parts, and the groups that didn’t work well would find the boundaries of their mandate constantly eroded by their more capable neighbors upstream and downstream from them. Eventually all the gaps would fill in, which is why the company worked. But it meant many orgs and applications did work that would have made more sense to be done at a different step in the process, if not for incompetence/bandwidth. Things would happen here or there not because of some waterfall design but because of where the task was in the development flow and who had more bandwidth at the time.
They kept a lot of old guys around not because they were effective but because they were historians. They knew where the bodies were buried, and who was the right person to ask (not just which team but who was helpful on that team). We had a greybeard who basically did nothing but was nice to be around and any time you had a problem he knew who to introduce you to.
This is absolutely a feature and this guy probably deserves his salary.
> Theoretically, microservices allow for each team to deploy independently
You can still do that with a monolithic codebase. A Google team published a related paper: https://dl.acm.org/doi/10.1145/3593856.3595909 > When writing a distributed application, conventional wisdom says to split your application into separate services that can be rolled out independently. This approach is well-intentioned, but a microservices-based architecture like this often backfires, introducing challenges that counteract the benefits the architecture tries to achieve. Fundamentally, this is because microservices conflate logical boundaries (how code is written) with physical boundaries (how code is deployed).At work the decision was made to rewrite it all in React because it was supposedly easier to find people who knew React, instead of any good product fit.
1. susceptibility to fads
2. path dependency,
or, to borrow a term from evolutionary biology, punctuated equilibrium.
A system that's made out of smaller single-purpose programs that are all made to be composable and talk to each over a standard interface, is not exactly an unproven idea.
1. There's some benefit to writing the different parts of the system in different languages (e.g. Go and Python for AI/ML)
2. The teams are big enough that process boundaries start to form.
3. The packaging of some specific code is expensive. For example, the Playwright Docker image is huge so it makes sense to package and deploy it separately.
Otherwise, agreed, it just adds latency and complexity.
Actually this happened to me once. We had two components that needed to talk to each other - one with an Erlang server and C client library that communicated over a socket with a proprietary protocol - and the other in node.js. The first attempt was to write a C translator that took requests over another socket with a different proprietary protocol, but this one was proprietary to us so we could use it directly from node.js. The second, much better attempt was to learn node's C++ module interface and write a C++ node module wrapper around the C client library.
This third-party Erlang component benefited from being an independently restartable process and therefore needing some RPC, but we also had a mess of C/C++ components inter-connecting over RPC that in reality probably didn't need to be separate processes, but for some reason we'd already decided that architecture before we started writing them.
If you have two languages that both are not C or C++ , and have more involved runtimes, how well does this work? I know for some cases you have things like JRuby or IronPython, but say mixing a JVM language and a CLR language?
With JVM and CLR you can use JNI and COM to generate SOs/DLLs, and both of them can use any SOs/DLLs via FFI. There is also IKVM and Jni4Net that allowed Java code to run in .NET (or at least used to be, I last used it 15 years ago). Results may vary.
For other languages it can be a bit more involved: if there's no such thing as exposing as a library, you must embed the interpreter, which typically involves using C++.
It's not fun. This is why people end up using network requests.
If you can have a text-only interface, or even involve files, you can also just invoke the other app as a process.
You had a relational database, designed to store and query a relationship between a user and their orders. Now, you have a user management service and an order service, each wrapping its own database. You had a query language. Now, you have two REST APIs. Instead of just dealing with relational problems, you now face external relation problems spread across your entire system. Suddenly, you introduce an event bus, opening the gates to chaos. All this resulting madness was originally sold to you with the words, "the services talk to each other."
Who ever claimed that REST services compose well? Because they can "talk to each other"? Really? Only completely disconnected architects could come up with such an idea. REST services don’t compose well at all. There aren’t even any formal composition rules. Instead, composing two REST services requires a ton of error-prone programming work. A REST service is the worst abstraction possible because it’s never abstract—it’s just an API to something extremely concrete. It doesn’t compose with anything.
Microservices aren’t micro. They’re hundreds of large factories, each containing just one small machine. Inputs need to be packaged and delivered between different factories in different locations, adding complexity every step of the way. This is what happens when enterprise architects "rediscover" programming—but from such a disconnected level that the smallest unit of composition becomes a REST API. Rather than solving problems, they create a far larger problem space in which they can "be useful," like debating whether a new microservice should be created for a given problem, and so on.
The same critique applies to "hexagonal architecture." In the end, with all of these patterns, you don’t get separation of concerns. The smallest unit of the architecture was supposed to be the isolation level where your typical problems could be addressed. But your problems are always distributed across many such units, making them harder to solve, not easier. It’s a scam. The truth is, separation of concerns is hard, and there’s no magical, one-size-fits-all tool to achieve it. It requires significant abstraction work on a specific, concrete problem to slice it into pieces that actually compose well in a useful and maintainable way.
Simplistic is often sadly seen as an effective replacement for the difficult achievement of simple.
Whoever it was, I think the same holds for software: creating simple software is harder than making complex software.
Quoting from https://quoteinvestigator.com/2012/04/28/shorter-letter/
"The French statement appeared in a letter in a collection called “Lettres Provinciales” in the year 1657:
"Je n’ai fait celle-ci plus longue que parce que je n’ai pas eu le loisir de la faire plus courte.
"Here is one possible modern day translation of Pascal’s statement. Note that the term “this” refers to the letter itself.
"I have made this longer than usual because I have not had time to make it shorter."
Certainly it is documented as appearing in Pascal's writing, and both Twain and Franklin postdate that.
Certainly if Cicero said it then that would be earlier, but while it is (later than Pascal) attributed to Cicero, there are no writings quoted by Cicero as containing the sentiment.
Again, all this is in the lunk page, so I'd be interested if you could provide an earlier reference.
Do you have a reference to Cicero's writings where he says this?
The parent I responded to gave the exact Pascal quote, but it has been given in many forms by many writers, all of whom had likely read quite a bit of Cicero.
Martin Luther also talked the same way about his sermons far earlier than Pascal.
The well-known Shakespeare quote, "Brevity is the soul of wit" is also another (loose) translation of a passage from On Oratory.
- Benjamin Franklin
On the foolishness of "natural language programming".
https://www.cs.utexas.edu/~EWD/transcriptions/EWD06xx/EWD667...
In back office / cloud / IT type stuff I wonder if complex things like Kubernetes win over simpler approaches precisely because they are more expensive and labor intensive. As a result of being labor intensive they pick up more users who after investing in climbing their learning curve become champions. Simpler or more “fire and forget” systems require less labor and so win fewer converts.
Then, universities include X in their curricula…
The result is a market where more grounded approaches to development are outcompeted by stacking abstractions on top of each other, leading to systems that are mediocre in the best case, and killing people in the worst.
But honestly two of them stand above the others: docker and kubernetes.
Docker is what your program is, and kubernetes is somewhere for it to live while it's running.
I'm pretty much the polar opposite of djikstra, all application almost no theory, but he was a real one...
Personally, I'd prefer if everything he represented was properly demarcated by 'mathematics', leaving its complex, material, physical realisation to 'computer science'. The failure to do this has indoctrinated a generation of people into a mysticism I'm not found of, to say the least.
Math and computer science at their core are more it less the same. Both are concerned with manipulating "digital" equipment that is assumed to respond predictably. Equipment is a prerequisite even for pure mathematics - it is interesting in this case because it is the mathematician themself, who agrees to act that way and respond predictably.
Physics is implicated in this in that it forms the basis of that agreement. Certainly it did historically. In the 20th century serious attempts were made to justify it on the basis of notions like consistency and completeness; the failure of that project is not yet fully absorbed. To be fair, the results are devastating because they can only really be understood by students after they have invested greatly in mathematics with the idea that all but a few "facts" derive from reason - when in fact almost none of them do.
Computer science is not constructive mathematics -- it is not mathematics at all, since `f(x)` means the spatio-temproral state `x` is operated upon by the IO/device action `f`
Honestly that sounds pretty nice.
More constraints can push us to find the better solutions. In our work. And in our life too. [0][1]
[0] https://en.wikipedia.org/wiki/Ikigai
[1] https://www.japan.go.jp/kizuna/_src/7994686/ikigai_japanese_...
The hard sciences seem to lead to more real-world applications quicker. Software science only seems to advance when used by tech companies to sell ads. But there's not that many applications for software to perform that function, so there's not really that many material improvements.
They keep coming up with new ways to advertise (who'd have imagined an interactive navigation map that advertises burgers?). But the computer technology that controls the lives of the common man has not progressed much past the 90s. The hardware has gotten denser, sure, but the software has bloated at the same pace, without providing a significantly improved or different user experience. It's still just clicking windows and paging through media, with basically the same software working the same way, just re-written 20 times over.
These new forms of generative AI certainly have the capability to sort out information more efficiently, and skip a lot of the more manual programming required to provide features. But AI was never necessary to take a prompt and turn it into an action, as all the car nav systems in the world have shown for years. Yet for some reason I can't quite fathom, only cars have audible user interfaces? And we traded tactile interfaces for glass screens... because it's prettier?
I don't care about simplicity or complexity, any more than I care about how antibiotics are produced. I care that I can take a pill and get better.
Similarly, it would be great if it were just a little bit easier to do simple things, like check my bank statement, without worrying about "cyber threats", or jumping through hoops when the next password replacement fails, or having to upgrade my app for the 3rd time this week before I'm allowed to check the bank statement, or having to click through offers for yet another credit card, or navigate a complex tree of "features" that varies from app to app, and month to month. I just want to read my god damn statement.
I don't know if the philosophy of producing this technology will ever be resolved. But I've stopped caring. The state of computer science today is, I've given up hoping for something advanced. I'll settle for something that isn't painful.
Please consider using the original title: is "On the nature of Computing Science."
The essay is about much more than simplicity versus complexity.
...and compare it to say, Paul Graham's 'the other road ahead' https://www.paulgraham.com/road.html (2001)