No one wants simplicity
lukeplant.me.uk
lukeplant.me.uk
-- E.W. Djikstra
If you want simplicity you have to do hard work. It doesn't come by simply removing libraries. Some of that may be incidental complexity and you will get better performance from it. However the core problems themselves, the essential complexity of the problem: to make a solution that solves it in a simple way requires thinking. And if there's one thing I've learned in my career: people hate thinking.
Businesses tend to prefer quick solutions and will pay whatever cost to have it now rather than later. Elegant, simple solutions require time and thought. That is expensive and slow. Since businesses pay our salaries we do what we can and we slap on a library or use a framework and move on.
I'll also add that simplicity also comes from a lot of experience, since the most dangerous developers now seem to be the ones with minimal skill, that don't have the track record to understand that they can't predict what the future will hold, and should better just solve what's required while keeping their options open.
* Just Doesn't Work
* Your simplicity becomes my complexity (fussy compatibility, batching creates latency, etc)
* "One-button" interfaces where you have to learn a morse-code dialect and timing to access the necessary features
* Bonus points: the software is laggy and the one button is mechanically unreliable, compounding the difficulty of getting the timing correct
* Useless error messages that make simple problems complex
* Similar: Necessary complexity (e.g. radio reception, authentication, updates) hidden behind a featureless spinning wheel for maximum time wasting when you can't tell what the holdup is
Forth is simple. (It is not that hard to write a simple Forth system that implements the language in a workable fashion.)
Python is simple. (It is a good choice for a first programming language, and plenty of people use it to rough out ideas because it allows them to ignore some kinds of resource management details and comes with a large standard library.)
Equivocating on 'simple' is a neat trick if you can pull it off.
Look at the Common Lisp FORMAT function and say that again.
To get any work done with it, though, you need to write your own Python.
[1]: https://conservatory.scheme.org/schemers/Documents/Standards...
Pedantically, Common Lisp being a Lisp-2 vs a Lisp-1 arguably makes it a duplex vs a simplex…
Batching should solve a specific problem, it's not really complicated to implement but without a need adds unnecessary complexity to the system. Simplicity in this case would be no batching and just handling the inputs as they come.
One-button interfaces while minimalist are not simple, you've already covered why they're complicated. They can be simple though, if used correctly, but you're intentionally over-complicating to make a point. Even no button interfaces with gestures can be simple an generally intuitive.
But you're correct that my simplicity may be your nightmare. I use DWM because I don't need or want the complexity of a full desktop environment. Most of what I do use the same vim keybindings, and runs in the terminal. The settings for all of those are in a git repository and I install a new machine or VM with a single line that I've memorized at this point.
To you that may seem like a brittle hell, to me it's the simplest most stable system I can design.
Flashlight enthusiasts, I'm looking at you. Doubly so when there isn't a way to know the current state without already knowing the current state.
I mean, it's a hard problem - for many reasons you only have one button, with no way to display information. And you have to cram possibly many functions into that one button.
It's a really interesting exercise in UI, and there are benefits to different approaches. I actually like comparing the different ways manufacturers have chosen to solve this.
BLE mesh means you could link them in groups for lighting large areas that don't have power yet.
You'd never have a mode you didn't like, just turn of the dang flash mode or map it to a long press. The dim mode could be as dim as you wanted it, down to sub milliamp for when you're working in a dark theater and need to read your notes.
You could set it to turn on when unplugged for an emergency light, glow all the time faintly to find it....
I wonder if there's a market for boutique handmade one off lights... Making a few a year might be fun but I sure wouldn't want to start my own production scale anything.
Although these would really be at their best if they were mass produced and cheap enough to have several.
Olight does make these "bulbs" that have Bluetooth support, you can configure color settings there through an app.
As far a market, there probably is if you're good. There are a bunch of people who collect all manner of flashlights, and boutique one-off things are usually a great thing.
Actually seems like something Pine64 would do really well.
(I could also be talking out my ass here though, I know nothing about business, and Bluetooth anything might attract technophobia and make some people actually less interested).
Yes, there is a way to display information: put a screen on the device. My bicycle headlight has this: https://www.niterider.com/products/6780-lumina-oled-1200-boo...
Of course, this costs more. The OLED screen version of this headlight costs significantly more than the plain one-button version.
Yes!
The article claims people think they want simplicity, but aren't willing to sacrifice anything to get it. But the reality is much worse.
People, at least business people (people making decisions, not end users), hate and loathe simplicity, and love complexity. Or, if not complexity per se, all the benefits it brings. Esp. bragging rights.
You have to be able to boast the number of engineers working on the project, the millions spent... and even the bad performance!
Bad performance is proof of the difficulty of the problem. If something actually works, it means it wasn't that hard to begin with.
I live CNN lite: https://lite.cnn.com
I guess I am weird but the way websites are designed confuses the crap out of my brain.
Such a refreshing site to see. It is like early 2000s internet before the introduction of the dynamic web.
https://www.w3schools.com/asp/asp_ajax_intro.asp#:~:text=AJA....
Every news outlet and blog should have something like this. Seems relatively quick and easy to put together compared to their main sites, and I'm sure tons of people will use & appreciate it.
This one affects a huge proportion of modern software developers too, and has two close relatives where we wildly over reward those that fix things heroically at 3am while under appreciating those that prevented it breaking at all, or my favourite "what I do is hard, important and valuable, what you do is trivial, so why don't you just give it away?"
Making things that appear to work first time has been one of the defining repeated errors of my career.
Said he learned from a locksmith that people hate it when he makes it look easy.
For some reason people value effort over expertise.
Also if someone particularly wants a piece of software for their role they may try sell it to the rest of the business with ideas of what it can do more generally. This is why kitchen sink products sometimes do well (but ultimately make no one happy as they don't do anything perfectly while trying to do everything well enough to claim it is supported).
Never seems to shake out that it's the ones at the top.
Did it make sense for Microsoft Word back in the day to have a Fax option? Of course not. Unless you had a fax machine and needed to do a lot of faxing, then it was super convenient that your word processor knew exactly how to do that.
Faxing isn't a great example, since from the perspective of most other features, it's probably just a special case of printing, but you can imagine it made it harder to build a web-based version of Word (what number are you faxing from? How does the computer in the MS data center contact or emulate it?)
It's almost always a better bet to add more complexity to your product to capture more market than to make it as simple as possible.
My first principle in building software is:
Avoid Writing Code.
Code takes time to run. Code is habitat for bugs. Avoid it. Do everything possible before writing it to minimize it — think, plan, select better algorithms, data structures, process models, etc. Write and test toy versions to select the most streamlined. Of course some code must eventually be written, but doing the work to avoid it pays off.
Car analogy lesson; my coach in sportscar racing once asked me what things I do as a driver that slow me down on the track. I started to say something about "when I initiate the turn too harshly it generates more scrub and....". "No, No, I mean the big simple things...". "Well, that would be braking, turning, lifting off the throttle?". "Yes, so always avoid braking, turning, and lifting.". Obviously, doing all three becomes necessary at the end of the first straight going into Turn 1, but the point is that there hundreds of times where we'll do those things without thinking, and eliminating the unnecessary things that slow us down is one of the primary keys to fast lap times. The fastest drivers make FEWER moves and are much calmer in the cockpit. That simplicity takes a LOT of dedicated work.
Similarly, eliminating unnecessary code takes a lot of dedicated work, but it is critical to software that performs.
Spend the effort; it's worth it.
Avoid Writing (and including) Code.
Second thought: 'Wait, we have metrics on execution time, time-to-load/display, time to download, file size, etc, and can even count clock cycles required.'....
And, it's kind of like auto road racing, where the times only matter in comparison to other times of that particular car class, at that specific track, in the configuration for that race, on that day's weather conditions, etc. Software is similarly comparable only to software of the same type/class, and how well the earlier versions of that software performed.
It's almost like we can gather more performance data about software than we can about sportscars...?
Which is better, software that used the twice has a time to first paint of 3 seconds, 3 seconds or 4.5 seconds, 1 second? The second obviously benefits from caching.
There, it's no longer obvious because there are competing goals.
The goal the article, GP and I mentioned were simplicity and reducing amounts of code, and the comment was about how we have the ability to measure our code 's performance.
Yes, immediate fetch every time vs caching is a question of competing goals. The default approach would be to avoid adding the code and complexity of caching. BUT, and that is a big "BUT", if the context of the software's use requires it (e.g., cached uses are far more numerous than fresh and using cached values will not screw up the results), then add it, and be efficient about it.
What's the big deal, what am I missing?
Like the best race car races the race the fastest, the best company makes the most money over the time period you care about. The best software could be optimized to load for new users fastest to reduce new customer bounce rates or to work best for returning loyal users to reduce churn or several other metrics. It's a legitimate question of what you want to optimize for
That still seems orthogonal to, or at least a separate consideration from, the question of minimizing the code.
Of course what to optimize for should be as carefully considered as any other factor. It is kind of the core point of a design effort.
The developer or team should figure out what to optimize for, then figure out how to implement that with the least possible code. Of course, some optimizations will require more code than others, and that should be one consideration (e.g., "yes, feature XYZ is cool, but is it worth the amount of code — slowness & bug habitat — that it will require?") in deciding whether or not to implement it.
So, I'm still not seeing how your point is an argument for writing more code, or invalidating the principles in TFA or the above posts? It just seems an offtopic distraction?
What's your thoughts on no code platforms, such as:
-bubble.io
-airtable
-power apps
-nintex/appian/etc.
I find myself looking at these platforms because the client server model we all have been been doing, still has a lot of boilerplate that needs to be setup.
At least with these, the selling point is we can focus on the logic and look, which is all the paying clients really care about.
You're plumbing a pipe of tangible meaning through networks of functions as implemented in electronic signaling devices.
Creating and propagating that significance takes work. Embrace the boilerplate. Also acknowledge that every no-code tool has about a gazillion engineer hours lying in wait because what you want to do is hidden and sieved through somebody else's abstractions.
For real r2.0+ production versions on projects/products that matter, I'd be suspicious that there are huge layers of libraries that get included, lots of code to run slow and provide bug habitat. But, it could also be that the developers have some optimization passes that strip out unnecessary code. It's something to check out carefully before committing. Of course, using one for a first throw-away version and examining it in detail can provide much info.
Sure, in the general case people are way above that line, but we also see the reverse (e.g. claiming that systemd is “bloated”, when much of that complexity is required for that problem space).
"You just aren't intelligent/smart enough yo understand/appreciate the elegance of my design" is the cope of many a fragile engineer in the face of a real world bashing their head against something rendered unnecesarily complicated for reasons completely tangential/unrelated to intended use.
That still will not convince some that cannot be bothered to track where their bits are.
I bring up the point because I've whipped up a system specifically intended for shipping a declaratively defined DB state, to a particular user specifiable environment, whilst limiting thr actual implementation of said data as close as humanly possible to forms that were already being written.
There are just some times when the needed solution will not be accepted until people have rammed up against the problem they don't even know they have. Thus is the curse of the implementer that prevents rather than remedies.
Make a problem impossible to occur and people think you over engineered it. Sit on the answer til everything is on fire, and the migration cost is maximized, and you're looked on as a visitation from on High.
It...really...sucks.
Sometimes people mix up simple with familiar, easy, or shallow. They expect that they won’t have to learn anything or that understanding should come without effort. Unfortunately this is not the case.
I often use the word sufficient in place of simple when trying to convert this to an audience that isn’t familiar with the subject matter. It’s as simple as one can make it without waving our hands about the essential complexity of the problem itself.
The proof of Cantor’s theorem is conceptually simple but there are plenty of people who cannot appreciate it because they understand little enough maths. And yet the theorem serves as a basis for more interesting theorems and practical applications.
I also try to avoid the use of the term, over-engineering. I find it is often thrown around too easily and used derogatorily.
Take for instance washing machines. They aren't conceptually complicated from user perspective. More or less, they have well-defined configuration parameters. You don't need a complex model of a washing machine in order to successfully operate it by any stretch of imagination.
That is, unless you buy a modern washing machine... where instead of having separate controls for water temperature and time you get a single knob. In most cases it doesn't even have a line on it to show which direction it points. It's just a round knob you can rotate endlessly. When you rotate it, in seemingly random order the lights near cryptic icons go on and off. Even if you can sort-of guess what a particular icon might mean, you will have very hard time finding a combination of the desired temperature and time.
And this is not unique to washing machines. Try toaster-oven, or water boiler, vacuum cleaner, air conditioner... modern day household electronics have the most idiotic design in their entire history. And they aren't conceptually hard to use. People who came up with the interface made it unnecessary complex and convoluted. And it's not a one-of event. This keeps happening all across the board, different brands, different kinds of equipment...
My explanation to this is not that it sells better: I'd absolutely buy a washing machine with text labels instead of icons. It's some kind of bizarre trend where manufacturers think it's more "stylish" this way.
Hell, take modern furniture or bathroom equipment for example. There's a bizarre trend to avoid showing the screw caps. It makes installing stuff much harder and the final installation more fragile and suspect to accidental damage... and yet it's nigh impossible to find simple(r) alternatives which would be durable and easy to assemble.
Making up novel hieroglyphics and letting the user memorize them is just cheaper.
No one sells the same washing machines in Japan and Germany. In Japan, the washing machines are made only for the Japanese market, not for export (some are imported from China, but these too are specifically made for the Japanese market, and are very different from machines sold elsewhere).
The cheaper machines have all text labels, and a lot of buttons, all in Japanese. The fancy machines like mine have touchscreens, with an enormous number of different settings and functions, and again it's all in Japanese with no ability to change languages, there there are also some icons along with the text, but not enough to use the machine without reading Japanese.
The problem is that it's not even close...
Also, I worked in printing, specifically flexo / silk / tampo, i.e. the stuff that gets printed on all sorts of curved surfaces, stickers, souvenirs, mugs etc. Yeah, it adds a bit of complexity... but compared to the price of equipment, at least the printing part is nothing. It might have to do with packaging and managing inventory for different languages... but then again they also need other localized stuff... so who knows.
Yeah -- it's not a localization problem, it's a supply chain problem. By removing the need to localize, they can manufacture and deliver a single SKU to any location. It's the same reason manuals are printed in 12 languages.
Maybe washing machines are different in your market to in mine? In my region washing machines [1] have a dial, labelled in english, listing programs like 'cotton' and clearly labelled push buttons for temperature and spin speed.
I could only see one that doesn't have such an interface [2] and it comes at a substantial premium.
The UI situation with washing machines is much better than for things like smart TVs.
[1] https://www.johnlewis.com/browse/electricals/washing-machine... [2] https://www.johnlewis.com/miele-wer865wps-freestanding-washi...
Also, I really don't want programs like "cotton" either. This just doesn't mean anything really. It's just noise. I want two dials, for time and temperature.
For me a washing machine without a wool setting and where I cannot control the spin cycle is an instant no. On the other hand I have no use for time dial, as I would expect the washing machine to work that out for me. Which is the problem manufacturers have, your must have feature is useless to me and my must have feature is useless to you. So either they have to make two different models of washers or they have to try to combine all the features into one machine.
You select the desired program with the knob based on what you loaded, then adjust temperature and spin speed with the touch inputs (some programs will block out some options, e.g. wool won't let you do more than 40°C or 800 rpm), you can add some options like more water, and based on that the machine does its thing, running a program specialized to achieve the desired outcome. It tells you how much time it needs, but it's not something you have manual control over.
And of course everything is labeled ... printing different text on a $200-$2000 machine doesn't break the bank for non-american manufacturers.
1: https://media.miele.com/images/2000018/200001856/20000185612...
Absolutely true. Machines in Japan don't resemble his description at all. My machine has a touchscreen with a ridiculous number of options and settings, all printed in Japanese, along with 4 physical buttons (on, off, start/pause, and back). The cheaper machines don't have a touchscreen, but instead a bunch of buttons that basically do what yours does. Knobs don't seem to be a thing here (on washing machines; they are on the fancier microwave ovens though, strangely).
Last air conditioner I bought (and returned) had Alexa built in but not the ability to keep the fan running all night.
That it, it makes the physics harder but produces a payoff.
People choose the complexity of a bottom freezer, but in this case the complexity of the choice isn’t even apparent to them. It’s unlikely to keep running as long as a top freezer fridge from the 80s or 90s, but they don’t know that when buying.
Modern fridge/freezer combos want to control the ratio of cooling. This is often done as simply as controlling a fan that moves cold air between the compartments.
Conversely, the fastest way to turn around a failing company is to search through company e-mail archives, find everyone who has ever used the phrase "add value", and purge them from the company.
but you'd purge the entire c-suite if you did that!
I've made many decisions in my career that boiled down to: we're not going to do what the users want in this case because the complexity of maintaining that feature is not worth the value it provides. And many times, that's true. Sometimes, it's not true.
At Netflix, it's common for engineers, especially new engineers, to say, "Who even uses dubs? Just use subtitles." The answer turns out to be "at least 50% of people when watching content not in their native language."
There is a floor on app complexity that naturally results from trying to build something that many people want to use. HN User #82983 may not see the point in a web-based note taking app because he just puts all his notes in a `notes.json` file. But, that app has many users who love it, and the developer doesn't want to tell them to kick rocks just because it would corrupt their precious codebase.
The Netflix subtitles and dubbing for foreign media are both so bad, we just don't watch any of it. My friends and family are not the only ones. I'm pretty sure we're a dark demographic.
I'd say the more common use case is people in the many countries that are used to dubs, culturally, vs. using subtitles. I've found it to be very much a cultural thing.
Also, kids. Kids movies/shows are probably a not insignificant fraction of Netflix watch time, and below a certain age subtitles are unhelpful to them.
"Simple" and "intuitive" are rather orthogonal concepts.
See eg Lisp: an objectively simple language which many find unintuitive. WordPress I guess might be considered intuitive, but is not simple in any way.
I’ve learned that I don’t get as much real world value from the extras and they cost me more up front and are an under appreciated burden for the duration I own it.
As it relates to this article, the last 3 web applications I’ve built have used PHP, are not SPAs and store data in flat json files (I.e https://fiers.co - I don’t think you’d be able to tell). There’s some stuff that are hard to do and those things don’t get done because I don’t want the complexity.
Only half-joking btw. I thought the article was way more about "cut scope ruthlessly so you can use simpler tools" than it was about "use the simplest tool for the job".
> what are you willing to sacrifice to achieve simplicity?
I'm willing to sacrifice a website that tries to keep state up to date without requiring a page refresh so that I can avoid all the complexity and bugs which come from it.
That's simplicity!
Essential complexity is that of the problem you are solving itself. How complex the use case itself is.
Accidental complexity is how more complicated your implementation of it make things. This is the one people want to keep away, and favor simplicity.
If you remove scope, you're removing essential complexity by making the problem itself simpler.
To remove accidental complexity you have to find a solution to the same problem that adds little more complexity over it.
People want to be able to deliver essentially complex use cases, while adding as little accidental complexity over it. But doing so is hard, hard things are hard to achieve, and so most of the time we end up with a lot of accidental complexity added, because it's easier that way. Not because people don't want simplicity.
The prime example is short-term technical debt taken on to speed the release of something new. It's not accidental, the team intentionally chose to (temporarily, hopefully) take on the added complexity.
If it helps, think of "accidental" as "incidental". It's not referring to any actor's intent or lack thereof.
Frankly, you're introducing accidental complexity by trying to refer to it as "non-essential complexity" ;)
"Incidental" is correct here, but not ideal for communication because of the eggcorn with "accidental". The word "accidental" is wrong no matter how you slice it.
It is impossible in practice to persuade people to pay the same amount for a simple, reliable product that they would pay for a complex, unreliable one with more features. Reliability is a promise, and they have to trust. Features can be demonstrated now, so less trust is involved (or so it appears).
And then the features stop working.
However Samsung and LG wouldn't make as much money from those models, and the potential customers for them will probably suck it up and buy a smart TV anyway. So why would they bother?
The post isn't observing a lack of desire for simplicity, they're observing a very common case where people evaluate "simple" relative to their own familiarity with tools or techniques rather than a comparison of perceiver-independent properties of the tools and techniques vs their alternatives.
EDIT. I forgot with the Right to Repair issue, there is a third person, the neighborhood general mechanic. With physical controls, the mechanic is more likely to be able to repair the broken switch/electrical relay. With the tablet, the mechanic cannot.
https://github.com/search?q=%22simple+yet+powerful%22&type=C...
This is a pattern I see again and again. I constantly get downvoted here when I suggest that new devs should be able to get up and running within a couple of hours and that should be one of the priorities (at least on the "core" project that they will be working on). And yes, I "get it" - the company I work for just acquired a bunch of other companies with various stacks, on various clouds. But at the end of the day, people are way more worried about introducing a 1000 new libraries and writing ABSOLUTELY useless unit tests where everything is mocked than actually creating one source of truth for the data.
As you can see, I am a bit bitter about all of this.
1) spend an indeterminate amount of time reading documentation until I actually understand what I'm doing, and have nothing to show for the time I spent gaining a deep (or at least decent) understanding.
2) Just jump in and start coding, bugging people to look at error messages for me, google when that doesn't work, skim the documentation when that doesn't work, cut and paste examples when that doesn't work, but have something to "show" at the end of the day which is far more complex, slow and unpredictable than a well-thought-out solution would be.
Every year of my 30 year software development career has been spent under software management fads that insist on the second approach because it provides an illusion of productivity and predictability. I actually had some hope when XP came out in the late 90's that the tide was turning here, but XP became Agile, which was "meet the new boss, same as the old boss".
On a 10 month project, this translates to reading docs and putting down foundation stuff, and delivering no features, for the first two months.
Attempts to abrogate The Critical Twenty are what causes the majority of problems later on in most software projects.
it will be only a little bit slower than 2 on its own and it will be written better because it's not just accumulated debris from your learning
At least until the deadline passes and he still doesn't have it working, then you have to do the something else you moved on to _and_ productionize the POC that was already overdue last week.
I'm always thinking about relay-like and continuous improvement (team processes and mastery, not CI/CD) between team members to promote curiosity, high drive, creativity and friendly competition.
If there is nothing deep to understand, the only thing you can gain from the docs is encyclopedic knowledge of all the toggles and switches. So, there's no reason to ever study them instead of just start using.
Tough to explain to management or colleagues sometimes. (On the other hand everyone seems to "know" it's the right approach because even today just looking up something on SO is not seen as the highest standard)
Fred Brooks.
Edit: Now I'm sad, I hadn't noticed that he died last year.
And then I remembered that I wasn't the actual user of these sites; no, I was the one being used. The reason all of this JavaScript is necessary is to load tracking pixels, analytics agents, and advertising networks onto the page to generate revenue and data ("the new oil!") for the site's operators.
Don't get me started on web developers' penchant for pursuing whatever front-end framework is in fashion these days. I get it, I've written my own monstrosities in highly tortured, purely functional TypeScript with fp-ts with ADTs and monads and Tasks; sometimes it's too difficult to resist from scratching that intellectual itch. But after a few years of bouncing from prototypeJS to jQuery to backbone to angular to react to vue to svelte - goddamn, does it ever end? Is anything really gained from this never-ending, ever-accelerating treadmill of newer and newer frameworks which seem to pop up faster than they can be replaced in extant codebases?
All of this at the expense of the end-used, er, end-user.
Having spent a little while exploring the metamath site [0] and its associated program, I am stunned at how snappy, simple, and _long-lasting_ the whole thing is. There are theorems here dating from fucking _1994,_ and the site is still being actively updated. There is no framework, only one binary that generates static HTML documents, which are then served to your browser, no need for client-side rendering or XHR or advertising or cookie popups, or hell, even JavaScript entirely.
But I am just shaking fists at a sky that will never fall, thanks to the shoulders of the distributed Atlas of hordes of developers keeping this digital house of cards standing.
It slowed noticeably after React took over the market. Svelte and SolidJS are the first entries since 2013 that offer something new.
Meanwhile large organisations often use Angular and have been since its introduction.
But to answer the question: yes. Svelte in my view is one example of how complexity is slowly but surely dialing down thanks to the lessons that were learned along the way - for the first time in almost a decade you're getting a legible stack trace and this is a huge, unexpected boon associated with the approach used there.
And these progressive monstrosities came from somebody's attempt to "simplify" things down to where somebody who didn't actually understand what they were doing could produce something that was usable.
> resist from scratching that intellectual itch...prototypeJS to jQuery
See, I don't think that in most cases this comes from developers, but rather from non-technical (or worse, formerly technical) managers who read somewhere that "this new jQuery thing makes app development get done really fast". At the end of the day, the only thing that ever matters, the only thing anybody ever measures, and the only thing anybody ever remembers is "meeting the date".
however it's not all wasted so don't worry, be happy and remember, the best times as a developer are when you ride your bike or take a walk or swim in the lake, preferably in summer time :)
I don't even think the article tried to argue that it was wrong to want those other things over simplicity, just that most people out there only claim to want simplicity but then make another statement entirely with their actions.
Someone could build a simple tool to do what I want. Someone could build a simple tool to do what you want. They would be different tools, though. Nobody wants to create different tools for me and you. So they create one tool, and it has to be more complex.
As the article says, the same thing happens with business units. Every VP wants something that does what they need (or think they do). And it might be simple to do any one of those. It's not simple to do all of them put together, though. (In fact, I wonder if it doesn't happen more because of different VPs than it does different customers.)
Strange the article doesn't address this tension between all the various stakeholders and tension among their priorities. I want the simplest thing that satisfies my need and want, yet no simpler. If others are using it then it'll already be more complex or one or both of us must compromise.
I thought it did:
> Of course we all claim to hate complexity, but it’s actually just complexity added by other people that we hate — our own bugbears are always exempted, and for things we understand we quickly become unable to even see there is a potential problem for other people.
This whole point kind of invalidates the conclusion that no one wants simplicity despite their claims. They really do want simplicity, despite struggling to understand both the depths of what's needed to satisfy their less visible constraints and the needs and priorities of everyone else using the thing.
Subconsciously or consciously folks may have a sense of the tradeoffs, which is why they keep choosing more complex solutions. Not because they're being dishonest or are hopelessly ignorant.
"If I'm doing my job right, you'll see me come up with solutions so obvious and clear, you'll wonder why they took so long." It is hard to come up with really good answers to questions. To make sure that the obvious, is really correct, etc.
I've given code reviews where I've told people to remove 100's of lines of code and use a module we already use.
My way is not the easy way today. My way is the easy way over the years.
The people who want simplicity don't need experienced professionals to do those simple things. So we don't tend to hear about them, and we don't get to do them.
I've been asked to do things so simple I don't even want to go to the trouble of negotiating a contract, I just recommend an off the shelf solution.
I've been asked to do complicated things that should be simple, so I've recommended doing the simple thing. They just ask someone else to do the complicated thing instead.
If someone reading HN is involved, so is complexity. The best thing we can hope to do is wrangle it into isolated and manageable little chunks.
Say a client asks for features A, B, C, D which reach the bar of complexity where someone from HN has to get involved. Now two things can happen, and in both cases the same feature set is delivered:
1. All of those features are implemented as a server side web app, with little to no JS a simple CSS stylesheet, and each page is under 100K and loads almost instantly. There is also a simple caching strategy (but not necessarily an obvious one) that speeds the application up further, and allows it scale. The DB design is good, proper indexes have been added, the queries have been thoughtfully planned, etc.
2. The features are implemented as a SPA, and a large framework has been pulled in. Many UI components also pull in other large dependencies. A CSS framework has also been added even though only 1% of it is used, and no attempt to tree shake the CSS or JS has been made. The page size is over 3MB. No DB optimizations or caching has been added, etc.
Note this is far from a straw man. 2. is by far the most common approach, even among "professionals".
Option 1 can be done by one sensible person with intermediate PHP/Python knowledge, and maintained fairly easily and cheaply forever.
They're different jobs. You can take the interview for that option 2, and you can push for doing option 1 instead. What will end up happening is that they employ someone else.
(I speak as someone who spent a couple of months in the mid-2000s mostly writing a partial XPath implementation in Flash ActionScript, to be used in a single product to interface with one other 3rd-party system. It was a stupid idea from day 1 and definitely not mine, yet that was the job! The insanity is not new.)
This a vast underestimate of the amount of knowledge it takes to do 1. well, for a project of any complexity. Doing the simple thing well is hard. Indeed, one of the reasons that option 2 has skyrocketed in popularity is because a larger number of mediocre devs can "get the job done" using that method.
> They're different jobs. You can take the interview for that option 2
What you are saying is that there is a lot of non-technical pressure to do option 2. I couldn't agree more. It doesn't make it any less absurd.
I honestly think most people who are currently doing an option 2, and are capable of some restraint, would find it easier to do option 1. And if they were allowed, and if it paid as well or better than option 2, and if their career prospects were improved by doing it, they would.
Absurd is the right word, but that's just the world we live in. Why am I paid more than a doctor? Madness.
Using a big brush here, but webdev has a LOT of this “just throw tons of libs at it and hope for the best.” I ran away screaming once I got a taste of that. It is antithetical to what I want out of my career. And it seems to breed a lack of rigor, exemplified by how many people complain of “slow tests” but refuse to refactor in such a way to make them faster. IOW, you don’t want fast tests as much as you want to bitch on Twitter.
Plus, long-term I believe option 2 is somewhat dangerous: there’s a huge pool of applicants looking to employ the same approach. Why pay a premium for those skills? What’s your differentiator?
> Using a big brush here, but webdev has a LOT of this “just throw tons of libs at it and hope for the best.”
My experience matches this. And not only that, many of them will passionately argue in favor of this approach, under mantras like "I ship" and "it gets the job done", and dismiss attempts at corralling complexity as fussy and wasteful.
It almost feels like it is a bit gauche to actually talk about programming itself. Instead, you’re supposed to be talking about microservices vs monoliths, k8s, monorepos, or some other inanity. Though this is not exclusive to devs: guitarists write books on gear and then a few sentences on actual technique in most forums. Something about our platforms seems to actively resist deep content.
It’s been pretty alienating for me. I work with other technologists in R&D and that is great, but when I glance at industry, I see a ton of self-inflicted wounds paired with denial that there’s even a problem.
Bad developers write complex solutions for simple problems.
Good developers write complex solutions for complex problems.
Great developers write simple solutions for complex problems.
Points noted:
* "17 javascript trackers"
* "sacrificing complexity"
* "control how a checkbox animates when you check it"
* "adding an abstraction with thousands of lines of codes"
* "whether you are able to remove things you have added"
* "add even more stuff to fix it, or is it to remove and live with the loss?"
* "learning to say no"
It's not about simple solutions to complex problems. It's about avoiding complex problems and doing something simpler instead.
Controlling how a checkbox animates when you check it is also a solution, not a problem. Problems are things like: users don't know whether they've selected this value or not. Users think our application is boring. Users are completing their tasks too quickly and we need to find ways to annoy them and destroy their productivity. All of those are the possible problems that micromanaging a checkbox's animation might solve. There are almost certainly simpler ways to solve those problems.
Adding an abstraction with thousands of lines of code is, obviously, not a problem, it's a (probably poor) solution. I don't understand why I need to explain this one.
The rest of it is suggestions on how to let go of your overly complicated solutions and find more simple ones.
The article, and most commenters, are basically assuming a fixed, relatively complex problem. Your point seems to be that experienced professionals should not work on simple problems. Okay? And you should wear your seatbelt while in a car. That has nothing to do with finding simple solutions to a fixed problem.
A "simple solution to the problem" could be to abstract away the tracking code into a system of well documented and typed generic internal events with a plugin architecture. Rather than scatter hundreds of tracking calls everywhere you just need one in each place. Then write a plugin for each of the damn trackers to translate those internal events into whatever is required for each tracker.
Getting rid of all the trackers is avoiding the problem entirely. I agree, that's what we should do! But it's not a valid answer when your boss comes to you and says "now we're adding 17 javascript trackers, and yes we do have to do it".
The checkbox animation is your problem, as the developer, because the designer has decided that's what should be done and has already sold the concept to the customer. The designer is an idiot, but an elegant technical solution to the task of animating the damn checkbox is not "I've decided not to do that becuase you guys are idiots". Not doing it is just doing something simpler instead.
In practice, most software solutions I see that emphasize "simplicity" are really putting the complexity elsewhere, typically on the user. More complex solutions have more features because the user needs to get stuff done. The simple solution doesn't have those features, so the user now needs to either do more manual work or rely on additional tools. The simpler tool has made the user's life more complex.
My pet theory (that I just made up) is that what you really want to do is start with something ugly that gets at the real shape of the solution, and then simplify it over time. So "simplicity" is a refinement process like moving from the rough cut of a sculpture to the finished version. But I'm skeptical of simplicity as an up-front design requirement. If you value simplicity so highly that you're never willing to have ugly complexity, then you miss so much of the design search space that you're unlikely to find a good local maximum.
The web tech stack is brimming with accidental complexity.
> The complexity of software is in essential property, not an accidental one. Hence descriptions of a software entity that abstract away its complexity often abstract away its essence.
This is pretty close to what I was saying.
There are, of course, more standard notions like Kolmogorov complexity. You could argue that the essential complexity of something is its Kolmogorov complexity. But I don't think anyone means that when they talk about essential complexity.
Simplicity is great, how can we combine it with the 17 other frameworks we saw on HN this week and have to use?
This just seems like a hopeless thing to discuss because everyone says that they want simplicity (or at least: not complexity) but then nobody will admit to being the root cause of some specific kind of complexity; if someone has made something “complex” then it was because they needed something to work with something else that was complex (pragmatism).
If buildings were built the same way modern software gets built, we would never have the Burj Khalifa, the Shanghai Tower or the Tokyo Skytree. We'd probably still be living in holes in the ground, because that's the only fucking 'buildings' we'd be able to build.
More often than not I think it boils down to this. Saying no to growth, basically. Which might even be the right choice sometimes. And sure, sometimes people just over-engineer things completely unnecessarily. But that's not why there is an enduring problem of choosing complexity over simplicity.
For example, yesterday I was learning about VPNs in more detail and got WireGuard installed on Debian. It took 3 hours to get it working with no knowledge of WireGuard or how VPNs really work beforehand. Then I came across PiVPN which is a user friendly front-end for WireGuard (or OpenVPN) which works with or without a Raspberry Pi and I got that working in literally 5 minutes.
I'm happy I took the 3 hours to better understand how all of the pieces come together but I'm way happier using PiVPN in the end because the interface to use it almost can't be easier given how much complexity it's hiding away.
This is an example where all of the complexity is caused by rigid adherence to the most popular architectural patterns of about 10 years ago.
https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...
It looks completely ridiculous to modern eyes, but during peak OOP it was just how you should do it.
If you like simplicity then your fizz buzz implementation would be a few lines.
Reading my original post i probably shouldn’t have said it’s how you should do it. I mean that lots of engineers created loads of pointless complexity with OOP
Or perhaps that's the joke?
I chose to make my own native app (that uses HTTP too) and I can now see these same complexities mount.
The trick is to say no and stop features.
This is a double edged sword. Removing is generally dangerous and can cause things to break, while adding is generally safer… which might explain growing complexity in most software systems
I suppose engineers need to be brave and ruthless to remove code and fight growing complexity…
>[...] software engineering has accepted as its charter 'How to program if you cannot.'" [0] (1988)
The context is that CS has to tackle two "radical novelties" which aren't reflected accordingly in real world applications and education:
(1) Deep conceptual hierarchies:
>From a bit to a few hundred megabytes, from a microsecond to half an hour of computing confronts us with the completely baffling ration of 10^9! The programmer is in the unique position that his is the only discipline and profession in which such a gigantic ratio, which totally baffles our imagination, has to be bridged by a single technology. He has to be able to think in terms of conceptual hierarchies that are much deeper than a single mind ever needed to face before. Compared to that number of semantic levels, the average mathematical theory is almost flat. [EWD1036-7]
(2) Large-scale digital device:
>It is possible, and even tempting, to view a program as an abstract mechanism, as a device of some sort. To do so, however, is highly dangerous: the analogy is too shallow because a program is, as a mechanism, totally different from all the familiar analogue devices we grew up with. Like all digital encoded information, it has unavoidably the uncomfortable property that the smallest possible pertubations - i.e. changes of a single bit - can have the most drastic consequences. [For the sake of completeness I add that the picture is not essentially changed by the introduction of redundancy or error correction.] In the discrete world of computing, there is no meaningful metric in which "small" changes and "small" effects go hand in hand, and there never will be. [EWD1036-9]
[0]https://www.cs.utexas.edu/users/EWD/ewd10xx/EWD1036.PDF [EWD1036-10]
To be fair, this sort of complexity usually results from "UX" requirements. Just think about what it takes to materialize those damn figma designs. Google's Material Design is not a simple "skin".
When it comes to business applications (forms, reports, requirements strongly influenced by end-users and evolving in ways hard to predict), my most successful experiences consisted of multi-page apps + vanilla js for validation.
My last project in this field failed though. The client was infected by the figma virus and I failed to compatibilize this methodology with the UI fluff they so fiercely demanded.
Reliability: I don't want a single host EC2, I want a multi-AZ Kubernetes cluster.
Security: I don't want a EC2 behind a firewall, I want a zero trust architecture.
Performance: For a auth service, I don't want a boring Spring Boot app, I want a performant Rust server.
Today's web technology is perfectly capable of doing very dynamic and complex things without being slow. The reason for slowness, while entangled with complexity, is almost always founded upon poor decision making; such poor decisions are usually the result of bad leadership, inexperience, laziness, programmer dogma, and of course the business putting too much pressure on developers to rush things out. What you get out of these conditions is an app that "delights" the user, but takes several seconds to merely load because someone thought it was a great idea to load all the user's records on the frontend at once, and is laggy because a crapload of elements are being inserted even when they aren't visible. As far as the dynamics of the web app, lagginess or weird behavior is often caused by the developer not actually understanding the runloop or the process that leads to painting things on the screen (ex. how merely observing a property of the DOM or changing something seemingly innocuous can cause a redraw).
> Of course we all claim to hate complexity, but it’s actually just complexity added by other people that we hate
Yes and no.
Of course we prefer complexity we intimately understand to complexity we don't understand that well.
That doesn't mean all complexity we don't like is just a matter of "RTFM, bro" or "hit the ground running, bro." For example, I've come to believe that most OOP principles lead to unnecessary complexity most of the time. When I see complexity caused by OOP, it's not that I don't understand it because someone else wrote it, but because it's a pattern that I believe adds more complexity than is necessary. I know this because I've gone back to code I've written using OOP and immediately became confused, whereas my more functional code is usually easier to follow and has fewer gotchas. It's a matter of taste, as many people prefer OOP, but it doesn't just boil down to someone else having written the code.
Same for API, the worse is better debate, an OS which retries automatically in case of interrupts is simpler for the users? For most users yes, for those who care about low latency no!
To keep your job secure and well paid, the better strategies are by introducing tons of complexities into the system which look good to those who's not maintaining it.
Given two different implementations of software, that gives users the exact same features, you will often find that one implementation is simpler than the other. Using less libraries, a simpler build system, less code etc. That’s the kind of simplicity we should strive for. Not software with less features.
Some Java code bases are borderline patronising in their apparent simplicity but are actually built on many layers of complexity which is then hidden.
So when you say you want "simplicity" I have to ask what you mean by that. Where do you want simplicity and where can what you think of as simplicity arise as complexity elsewhere? I think there are more nuanced trade-offs than unqualified notions of "simplicity" and "complexity" don't capture very well.
Everyone else does, including the people who never entered the field because it is now incomprehensible.
On the one hand, beautiful, recursive composability of small, universal tools.
On the other hand, the tool we're introspecting is 'ls'. If we truly valued simplicity, ls would have no flags - you would pass its output to awk to extract the data you want.
A more thoughtful writeup: https://danluu.com/cli-complexity/
I can understand that the article seems to be focused on “unnecessary complexity” introduced by large frameworks for creating seemingly simple websites… but, this sounds a lot like folks complaining that Java code is less efficient and/or larger than assembly. Like, of course you can write “simple” code for your project, but there are many concerns that engineers hold in high regard beyond simplicity: correctness, reproducibility, maintenance, to name a few. And, we cannot be calling ourselves engineers if we don’t adhere to the most basic engineering principles of “standards”. That last one especially rings for me, if ever problem requires a scientific exploration than we’re not doing engineering work, we’re doing research. So, the use of frameworks, even “bloated” ones, brings us much closer to standardization than one-off boutique, yet (possibly) simple, solutions. —— Anyway, back to complexity: A perfectly fine website may require a 30-second load time… try walking to a store and finding the good you want and standing in the checkout line and missing your bus and having to carry the thing all the way back home and opening the box to find out that it’s broken and hauling it back to the store and then they tell you that that was the only one and then having to wait 4-8 weeks for a new one to be ordered and delivered and repeat the process all over again. Perspective is important on what “complexity” even is.
It can take 5x longer to make a product 20% simpler and 30% faster. But that might result in your product becoming 10x more popular. Power law dynamics are very counter-intuitive that way.
Do businesses ever consider the cost of maintaining and serving huge, dynamic web pages, when simpler ones would do? What savings in hardware (or cloud services) and staff time would be possible?
Tangential, but I've repeatedly found this to be a very useful and generalizable insight.
If you want to know what's really important to someone (including yourself!), ignore what they say and focus on what they actually do (or don't do).
https://www.thedrive.com/car-reviews/2023-ineos-grenadier-pr...
Do people want straight axles, reliable engines, and big physical knobs and dials?
As someone in software security, I tell people I'm the fourth or fifth priority for any product. Function, Speed, and Simplicity are all ahead of me on the priority totem. I get it, but it's frustrating.
No, you can't remove all that code. Think of all the person-months we sunk into it!
There's almost nothing harder, organizationally, than taking something out once it's in.
1. It's a very naive idea that our actions can always be construed as evidence of what we want. The fact is, humans aren't purely rational beings, and we don't always do things that lead to what we want. Particularly, short-term dopamine-rush type desires can override our more fundamental wants and even needs. The person who wants to lose weight gives in to a short-term craving for a cookie, the guy who wants a relationship gives in to a short-term fear of rejection and doesn't approach the girl, the person who wants to save money buys the cigarettes to deal with their stress. The idea that anyone is immune to this is arrogance, and it's uncompassionate to not allow for this in our understanding of others.
2. Simplicity is defined in a lot of ways, many of which don't make much sense. For example:
> A lot of developers want simplicity in the same way that a lot of clients claim they want a fast website. You respond “OK, so we can remove some of these 17 Javascript trackers and other bloat that’s making your website horribly slow?” – no, apparently those are all critical business functionality.
This is assuming simple == fast, but that's not in evidence. One might plausibly improve speed here by loading the 17 Javascript trackers asynchronously after the visible parts of the page have loaded, thereby creating the visual impression that the site is faster, which is likely what the client means when they "claim they want a fast website". By any reasonable definition this is more complex, but it's faster by the definition the client is likely using.
In optimization this is super common: quicksort is faster but more complex than bubblesort, hash tables are faster but more complex than lists of key/value pairs, etc. "Fast" is a really poor approximation of "simple" in this context.
Really this is an example of really poor listening on the part of the author. They're not taking the time to understand what the client wants to be faster, and are instead incorrectly telling the client that they need to remove core business functionality in order to do that[1].
[1] As a side note, I've managed my entire career to avoid working for companies that have 17 Javascript trackers installed, and in all likelihood you can too. If you don't like working on sites that have trackers installed, then I think it's more mature to be honest about that with both yourself and your clients, rather than setting up artificial roadblocks like "this can't be fast because of trackers" which is passive-aggressive if you're saying it just because you don't like the trackers.
Sounds like Richard P. Gabriel never really figured out an "ideal strategy" after decades of trying..
Simplicity may be the kind of thing that feels close but is ultimately impossible due to varying tastes, interests/priorities. You can get far within little bubbles of coherent taste/interest, but then as the bubble expands, entropy (aka some value diversity metric) breaks things on you.. Like a kibbutz vs. capitalism. You're always tempted to think you can have just a little bigger tent/bubble if only...
Projects become cluttered with various "dot-files" with various configuration formats, and because those tools need to cooperate somehow, you also see bits of configuration for one tool embedded (while escaped) in configuration for another tool, and sometimes even multiple layers of escaping.
There are usually straight-forward alternatives that simplify the process, make it more uniform. My explanation for why those alternatives aren't used is vanity. Users of projects with unwieldy configurations pride themselves on knowing and using a bunch of (unnecessary) tools, they like to appear savvy to their peers by discussing advantages of and new developments in these tools. And because the explanation is so simple and so unflattering, few will dare to acknowledge it.
It's also usually the case that one would need at least some years of experience to accumulate all the useless knowledge of development infrastructure tools, and so these "opinions" about tools will often come from more senior programmers in the group, often driving the junior programmers to unquestionably accept the unnecessary complexity of their environments as status quo and come up with all sorts of rationalizations for why it's normal to have this many cross-referencing configuration files and various infra tools.
I've lost count of arguments I've lost when suggesting a simpler automation solution which didn't use (an unnecessary) tool. Here's just one example:
A project aims to deploy a Python application with external dependencies (packages) in containers. Using pip to install stuff in containers was problematic because it took forever (due to solving dependency constraints, downloading from PyPI, installing a bunch of stuff irrelevant to the target application s.a. scripts for dependency packages, or tests etc. finally, poor network utilization). I suggested having a CI job which pulled vetted versions of packages on-demand, then have it strip those packages of unneeded cruft, put them in a tarball and use that for building containers.
You had to watch the guy who was a level above me in work hierarchy and was somehow responsible for CI get red in the face and start making saliva bubbles as he was getting ready to destroy and ridicule my "insane" idea... all because it didn't use pip.