Hacker Newsnew | past | comments | ask | show | jobs | submit | zgniatacz's commentslogin

The Stanford Mathematics Problem Book: With Hints and Solutions (Dover Books on Mathematics)


thank you!


should be FUTHARK which should be the first letters of their alphabet. (just like alphabet are first few letters, alpha beta ...) https://en.wikipedia.org/wiki/Elder_Futhark





www.modwiggler.com/forum/ https://llllllll.co/


“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.” – Edsger W. Dijkstra


I think every talk on complexity is meaningless, without taking into account the difference between accidental and essential complexity.

There are problem domains where there is simply a minimal complexity required implicitly. You can’t write an insanely simple program that will render vector fonts, simply because the problem inherently has to have a fixed amount of complexity. Anything more (accidental complexity) is of course bad, and “clean” code or whatever should try to minimize its amount, but it is harmful in my view if we keep believing that it could be made simpler. One really bad example is this list: http://harmful.cat-v.org/software/


>> I think every talk on complexity is meaningless, without taking into account the difference between accidental and essential complexity.

Yeah. This is both true and pointless.

Nobody codes things too complex on-purpose, at least not normal people. So it's not the difference in types of complexity, it's the difference in our ability to understand accidental and essential complexity.

I find that I do a really poor job at this, and I'm the first to stand on the soapbox and rail against systems being too complex. Just like programmers naturally introduce bugs into code without realizing it, programmers naturally introduce complexity into code without realizing it.

We may theoretically be able to talk about the differences in type, or how to manage each, but our real problem begins in our conceptual models inside our brains or various types of problems, and this happens a long time before any code is ever written.

In my personal practice I've come up with a few gimmicks that help me refactor my preconceptions. It is very difficult, however, for people to adopt practices that continue to inform them that they make lots of mistakes. Everybody wants to code as if they're conquering the boss-level at the end of a game. We sell coding, tooling, frameworks, and practices to other coders under the assumption that they're going to have a blast, not that they're going to continuously be reminded that they're screwing things up.

So yes, I agree, but without moving past that statement into something more tractionable, it's more of a truism than a starting point.


I've worked with a lot of people who'd never thought about the difference between accidental and essential complexity.

This resulted in them coding things too complex unintentionally, so while not on-purpose, it was absolutely a useful conversation to have. It's a good starting point.

I don't have a good single rule for a "second step," though. It's going to depend on the details of your project, by and large, though I think some principles to try to strive for include composition, encapsulation of details, and so on - nothing new or startling, but just adding the "is this essential or accidental" lens to the decision-making process.


Yup. They don't think about it, but the mind is a funny thing. If you ask them why they've done something a certain way (without bringing up the topic of complexity), folks usually have some good reasons for the things they do.

However, if you bring up the topic, then take a look at some code or architecture? Then suddenly we're talking about all the ways we might have done it better/less-complex if things had been different.

Most every coder I know understands the topic, and most are even willing to go on at length about how important it is, including me! (grin). It's the actual application where things fall apart.

>> I don't have a good single rule for a "second step," though.

I do. It was bugging me so I spent a couple of years coming up with one. Seems to work great for me. YMMV. I do not believe it is as context-dependent as most in our industry seem to think. (It's very much problem dependent, though. It's just vastly more related to the business problem than the technical considerations. [Discussion goes here about tech-related problems not related to the solution foisted on the solutions team])


> Nobody codes things too complex on-purpose, at least not normal people. So it's not the difference in types of complexity, it's the difference in our ability to understand accidental and essential complexity.

It's not so simple — I've seen people create over-architected monsters because they thought everyone coded like some consultant's magazine article/talk/book claimed, because they were trying to be taken seriously and didn't think they could push back, because they had talked their way into a job they weren't qualified for and tossing around buzzwords was a way to obscure the fact that they had no idea what they were doing, because the client insisted that all real projects must run in the way the consultants in expensive suits assured them everyone serious runs them (ignoring massive differences in scope and resources or long term success), or because the institutional incentives made it easier to say their project would handle everything anyone had ever thought might be useful into one application rather than working with the actual users to build multiple smaller, simpler tools.

One way to think about that is that it's neither accidental nor essential complexity but environmental. Fixing that can be quite hard but it's often work the political capital if you have it because the alternatives might not be survivable.


> accidental and essential complexity

I feel like I am turning into a bot for posting the Out of the Tar Pit paper:

http://curtclifton.net/papers/MoseleyMarks06a.pdf

This changed my understanding of computer science and our product virtually overnight. We are using a hybrid model of Functional Relational Programming (see section 9 in the paper). This is in production right now and its clearly the right answer for managing complexity in our product.

If you think "eww i have to learn some FRP language" - No. You just need to tack SQLite onto whatever preferred language you use today and model all your business logic as SQL queries over properly-normalized tables. If you can achieve this with 6NF, you have an infinitely-extensible domain model. If you don't know where to start, 3NF is the safest place. Most humans tend to think in terms of 3NF when referring to the business entities.


The problem is that performance and normalization do not (always) go well together.

Let's say you have billions of rows of event data you want to perform summary counts for by a few different key columns.

Doing this up front as the events are ingested is going to allow for much more efficient querying on an already grouped table than having to group on your billions of events in each SELECT query.

I'm not saying don't normalize. But normalizing creates its own problems too you may need to think about.


> The problem is that performance and normalization do not go well together.

> Let's say you have billions of rows of event data you with to perform summary counts for by a few different key columns.

Guess what? 99% of people on here don't have billions of rows of event data they need to regularly aggregate. Problem solved.

Such a terrible tradition in our industry in focusing on outlier cases, or on what FB/Google/... might need when making technical decisions.


>Guess what? 99% of people on here don't have billions of rows of event data they need to regularly aggregate. Problem solved.

having built a real time analytics solution a few years ago because we wanted one we controlled for our startup, it doesn't take much to get to billions of rows of event data in the modern web.


At last $dayjob we were a speck compared to even the smallest "webscale" consumer B2C app and we gathered 800mil tracing events a week.


Yup. How many variations of analytics startups/companies exist out there? How many customers do they each have with how many events happening per customer?

Analytics on large-ish data is definitely a common challenge. And sure, CRUD is even more common. But knowing what your options are for each challenge makes sense.


this relates https://news.ycombinator.com/item?id=28047618 if the giants are generating exabytes per year it seems reasonable to expect that your smaller application can end up with a few terabytes in the same time.


OK well I'm telling you based on my experience and it wasn't at FB or Google. :) Do most people have these problems, no you're right. Should everyone ignore them and be unaware of options when they do have the problem? Probably not?


I had those problems several times within the last few years - having to aggregate and detect various signals from billions of data points - and keep the system flexible enough that different business people could “try out” various ideas and play with the results.

All sorts of different patterns and architectures have to be brought together to make sense of it.

But the technique described above still has its place within such a system. For example - you boil billions of data points down to a handful (several thousand) facts, such as events that occurred or anomalies. Then those several thousand facts can be analysed standalone (as described above) without going back to the source. Etc.


Sqlite has triggers, and Sqlite has indices, and Sqlite lets you write custom functions in your host language.

While I'm not necessarily arguing in favour of using Sqlite for this, it most certainly can do this up front during ingestion.

So yes, sometimes you do end up sacrificing normalisation, but often that means keeping a normalised form, and having code that can re-generate summary data from the normalised form.


The question to ask is whether building a cache of normalized data will be more efficient than addressing the complexities of non-normalized data, eg. duplication, renaming, integrity problems, etc.


I've seen the downside of this. And it's having to have an oncall staff of DBA's hand-grooming fragile databases and running deduplication processes that sometimes get so far behind that it's a mathematical impossibility to catch up with new data coming in. (never mind what happens to your maintenance schedule when you have entire teams focused on "fixing this problem" for weeks at a time).

If it were up to me (and it almost never is, because I'm not a DB expert), I would ALWAYS normalize as much as possible when designing a database. I really can't even wrap my brain around why large (and old) databases ever get into this state. But I've seen it at two different employers and it's very painful (and costly) to deal with. My take was that these databases were probably originally set up by people who had no idea what they were doing, and ended up locking the company into a shitty implementation that kept the company crippled 15 years later. But that's just me.


Totally. All I mean to say is that "everything should always be normalized" doesn't necessarily make sense. You need to consider your situation.


Premature optimization is the root of all evil. It’s unlikely normalizing data is going to be an actual problem you can’t solve via caching.


I hate how this quote has been perverted. “Premature optimization” was meant to apply to people making their programs an unreadable/unmaintainable mess to save a couple of CPU instructions. Figuring out how to organize your data is not premature optimization, it’s literally one of the first things you have to tackle when starting a project, because trying to change it down the line is going to be miserable, especially if you can’t afford any downtime.


Yes, and I think the parent was pointing out that denormalization is often a premature optimization that makes the data schema an unreadable/unmaintainable mess to save a few CPU instructions. The normalized schema is answering the question of "how to organize your data". Denormalizing that schema is an attempt at optimization.


> The problem is that performance and normalization do not (always) go well together.

Absolutely agree. That is why we use in-memory SQLite projections of business state that are scoped per-user-session so that row counts never exceed double digits in any given table.

For us, adding indexes to these special database instances would actually make things go slower.


Use a columnar database for this. Use materialized views. Don’t do this on the prod DB for the CRUD app. Simple :)


That sounds good!


I'm curious, can you recommend an open source example that implements these ideas? My first reaction when I read

> You just need to tack SQLite onto whatever preferred language you use today and model all your business logic as SQL queries over properly-normalized tables.

was to think "well that can't work for _all_ my business logic". But I'd like to see how this idea works in practice before I jump to that conclusion.


I want to second this.

My first thought was the same as yours (no way that works for everything).

It seems like a neat idea. But I can't imagine that anyone has ever done this for anything non-trivial. I want some sort of compelling argument that this works at all before I'm willing to accept this as anything else than a pipe dream.


I am curious what edge cases (i.e. "non-trivial" things) you have in mind that this would not work for.

For us, the more complex the business gets, the more justified this path becomes. Our business fails to scale if we have to write custom code for every customer. Writing custom SQL per customer (against a common schema) is far more tenable.

Are you thinking of some specific logical determination that would be infeasible in SQL vs in code? Or, is this more about webscale arguments?


It's the same sort of disbelief that I would have towards being introduced to a skyscraper made out of cardboard. At first I would think, "oh, this is just like concept art." ~No, we actually built it.~ "Err, so, like nobody can actually go in there." ~It supports people just fine.~ "Um, for what, 20 minutes." ~Well, Nick has lived in it for 20 years now.~

Finally, I'm not going to venture in (let alone actually live in it myself) without someone sitting me down and carefully explaining the structural integrity principles (and other logistics) that make the cardboard skyscraper possible.

Hearing business rules in sql works for some unknown entity doesn't really give any information about the viability for anything else. Maybe the initial modeling is really hard, but all your customers have near identical concerns, so you only pay that cost once. Maybe having multiple customers is actually the key because if one customer's needs violates some assumption that makes the whole thing work, you can tell them go to someplace else. Maybe your customers only have five business logic rules apiece that are all well spec'ed.

What's the domain? The industry? What problems are actually being solved? Can we have an example (even a contrived one)? Is there an open source example? How about a mathematical proof or even principle that argues for why this can be expected to always (or even nearly always) work? How about a youtube video with someone describing the approach?

EDIT: How about this. Show me a partial parser using this approach (grammar rules can be considered business logic, right). Just parse function declarations in C or something. I'll be able to project such an example onto what the full solution would look like to see if I believe it could actually work in general.


Your cardboard skyscraper analogy is fantastic. It does a good job capturing the tone of my disbelief.

I'm disappointed to see there wasn't a response because I was pretty willing to entertain the notion of business-logic-as-normalized-tables. But I needed, like, any evidence.


Going to high levels of normalization also makes the code harder to understand. It's very extensible, but every system that I have dealt with that had high levels of normalization was a huge pain to figure out.


I wrote a piece about that some time ago. The vast majority of the complexity in my professional career now is extra curricular complexity and that wasn't true a decade ago. It's build processes, it's CI, it's containers, it's a dozen arbitrarily different frameworks, microservices, dependency management, it's all of that stuff.

The trope I see all the time is enterprise tooling in small projects. Small teams basically moon-lighting as devops 50% of their time and reducing their capacity to solve the actual domain problems significantly.

The domain complexity is something you can't remove, but complexity you've chosen to introduce through tooling should be hard thought about, and the less time you spend thinking about stuff outside the problem you're actually trying to solve the better.


But I really enjoy painting bike sheds and shaving yaks!

YAGNI is so hard for people to really grok.

Get the revenue model right and suddenly every feature is cheap; get it wrong and every decision is infinitely expensive.


>without taking into account the difference between accidental and essential complexity.

This is acutely summarized by Larry Wall's "Waterbed Theory of Complexity" which is basically Einstein's "Make things simple as they have to be but not any simpler than that". i.e if complexity is like water -- not very compressible. If you compress that complexity (a part of the bed) -- it will manifest elsewhere in the bed as more awkward/expanded because it's all connected.

Many discussions on complexity do make this distinction.


"Essential" is always relative to requirements. If the requirements include interacting with a poorly-designed, buggy, complicated piece of other software, then yeah, you have essential complexity. Enlightenment is when you realize that you can keep zooming out and dumping what seem like essential requirements but are really just BS that follows from interacting with constantly-changing crapball software stacks.


Nah, that’s a cop out. There’s nothing enlightening about shrugging off complexity.

If a system is hard to interface with, the complexity is still accidental, it is just outside your own system and maybe out of your control.

Even if you’re a “middleware” company that connects multiple shitty systems together, you’re still adding zero value to anything but your own pocket. The complexity is still there.

We still have the right to call a spade a spade. In the past I had to say “no” to managers about interfacing with shitty systems. Sometimes you CAN make a difference.


Aren't we kind of agreeing, given your last two sentences?


I'd say "essential" refers to the value statement.

The translation of that into requirements is by itself one of the largest sources of accidental complexity.

And even the value statement sometimes is wrong and leads to unnecessary complexity too.


> The translation of that into requirements is by itself one of the largest sources of accidental complexity.

Good point!


Actually I think Djikstra's comment still applies. A lot of time the essential complexity is due to design. That design may have said essential complexity because the design is poor, when a different design would have less essential complexity. But as Djikstra says, the design with more essential complexity often sells better.


You can't say "more essential complexity" because that violates the definition. It's the complexity required by the task and that is constant and independent of the design.


That page is a joke right? That last alternative really makes it seem that way. If you want simplicity, why would you use sed to get the first lines of a file? Head is a much simpler program that has a single job while sed has its own text transformation language.


I totally agree, but I think today’s systems have more incidental than essential complexity.

The sentiment behind that list is okay but it does demonstrate a lot of ignorance The biggest joke is simple tables or file systems as a SQL alternative. If you do that for anything that needs more than just a map you will eventually end up with a badly implemented buggy slow relational database.


Truest comment I’ve read so far.

If simplicity is always the right solution, then why do so many programming languages have dedicated parsing libraries for .csv, which has to be the world’s most simplest data format ever?


CSV isn’t so much “simple” as “underspecified”. Sure, Comma separated values, but what happens when a value contains a comma? It emerges that people normally use quoted strings ‘"a,b"’ for that, but then what do you do when you need to include quote characters in your values? Etc. etc.

The basic rule for CSV is: Don’t. Or at least use a library which emits RFC 4180-compatible results. If you need to parse some co-called “CSV” non-RFC-compatible monstrosity, do whatever you need to parse it, but don’t have any illusions of it being in any way “standard”.


This is the problem with “artificial simplicity” – people make systems too simple, so the abstractions leak heavily, and by the time you want to get anything done you have a massive pile of leaked complexity to wade through.


> keep believing that it could be made simpler. One really bad example is this list: http://harmful.cat-v.org/software/

That's indeed a pretty bad example, regrettably of a website often shared in programming circles. The author simply listed his beliefs about stuff he doesn't like vs stuff he likes, and never bothered to justify them. In many places the list is obsolete, too.


I don't understand how they could classify CSV in the "less harmful" column -- its rules are insanely complex.

Also, UTF-32 seems way simpler conceptually than UTF-8, so I don't understand how UTF-8 ended up "less harmful" and UTF-32 ended up "harmful".


Would turning that font rendering into a web service an accidental complexity, or an essential one?


Accidental, of course. There is never a need to introduce latency in text delivery, simply a long line of unmitigated wants.


Thai reduces a number of companies, eg Slack, to an “accidental complexity” then.


Are you saying that you think Slack's primary challenge is font rendering?


No, it’s providing a web service to do something that would work (and used to work) much better without it.

Their primary challenge is making money, and that part probably is better as a web service, but it makes it worse from technical point of view. Just like with hypothetical FaaS - worse technically, but you can have adds.


I'll bite, what exactly worked much better than Slack without the web?


Pretty much anything, starting from IRC - it offered more functionality, from logging to scripting, but the general idea is the same.


essential complexity == simplicity. Make it as simple as it can be but not simpler.

To me it’s sort of implied that it’s unneeded complexity when we talk about it as something that should not be there and it’s making our life hard.


Most technical people don't get paid to solve problems, they get paid to work on problems. That paycheck is an hourly/weekly/monthly paycheck.


I remember one dev kept talking about simplicity, even made a session about it and then just lumped business logic, data access and transfer layer mapping into a single API file...


Whats the problem?


Only works for small projects, doesn't scale in terms of maintenance.

Same sort of issue makes people use microservices not because of their true advantages but simply to enforce boundaries between features because so many people lack discipline to make a well-structured (distributed) monolith.


Without knowing the problem it’s hard to say if they were right or wrong to do that.


I just know that "divide and conquer" works and impure functions with side effects don't.


I mean, your statement assumes a definition for "work". Reusability and maintainability are features, and for certain scopes, they may be overkill. I think this is where the really good software developers shine: You have to know the rules before you break them for sure, but pretending there isn't opportunity costs in software development is a big problem. Shipping anything gets you feedback, and that feedback can drastically change what you decide to build.

This is coupled with organizational dynamics where to get resources you have to prove value. Proving value is a lot harder than scaling/rewriting a software system, because if you need to scale a software system, you have rewards and money attached which are good business drivers. If you need to prove business value, no one cares (and you won't get resources) until you do.

It's a fine line to walk for sure.


I am a developer not a manager, getting resources is not my problem but maintaining bad code is. In the end of the day business does not understand technical debt, so it's my duty to manage it transparently and well in advance. Perhaps start-ups that need to capture market or something are a different story.


"complexity sells better" AWS sales team :)


He also have the quote: "Simplicity is prerequisite for reliability."


Dunno about that one. Our most reliable integrations have a lot of quite complex error handling in order to be highly reliable.


> And to make matters worse: complexity sells better

Well said Dijkstra. Some of the my favorite algorithms are beautifully simple, mostly in the way of being naturally recursive. My compiler course in university involved a lot of recursion, but everything just flowed. Sometimes I'd mindlessly write some code and just assume I'd recurse down the AST, and everything just worked.

Obviously simplicity isn't always achievable in large software, but hopefully there are many simple pieces involved that come together in a clean and concise way.


Similar quote from Steve Jobs (1998)

"That's been one of my mantras - focus and simplicity. Simple can be harder than complex: you have to work hard to get your thinking clean to make it simple. But it's worth it in the end because once you get there, you can move mountains."


> [...] and education to appreciate it.

Also true with personal finance:

* https://canadiancouchpotato.com/2016/01/25/why-simple-is-sti...


Seems like Dijkstra was seeking popularity too.



vcv rack


Civilisation: A Personal View by Kenneth Clark


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: