Hacker News new | past | comments | ask | show | jobs | submit login

I don't like the mental image of layers. It's not wrong, but it's terribly inclusive of everything that is bad about bad abstractions. Even the worst abstractions will often look kind of nice from the layers angle.

I prefer the concept of orthogonality: you have an entire plane where your domain requirements can move in, but the way you make persistence reliable is completely orthogonal to that plane. It should be implemented in a way that does not change when, say, your customer account becomes a composite of of multiple identities. And neither should the way you organize UI components change, or your transportation tooling change. That entire transportation layer stack, from ethernet all the way up to your domain model generator of choice.

Did I say layers? Yeah, I did. You'll often see the orthogonal aspects themselves consisting of layers. But that's an implementation detail and those layers tend to be more pragmatic than dogmatic, as in the way TCP goes out of its way to avoid hiding any of the addressing of the underlying IP. TCP absolutely is a layer, but it has zero ambition to perhaps run on top of something other than IP, or hide differences between IPv4 and IPv6 from higher layers. It focuses on one thing, implementing streams on top of packets, again a problem nicely orthogonal to the problem of routing those packets (what IP does) or anything built on top of those streams.




To add on to your great comment, I've read a few papers that justify your remarks, but some have paywalls and I'll try to condense them anyways.

Parnas' criteria for when to split code into modules[0] is very compelling: modules should enforce information hiding, where the information of each module is how a key decision is implemented. Key decisions should be orthogonal: e.g., encryption shouldn't inform filesystem access and vice versa. This fits in nicely with practices for determining solutions for a given problem: nail down key decisions (or uncertainties around them) early on and encode them through modules and interfaces.

A logical application of Parnas' module criteria is, naturally, in network stacks. According to [1], although coarse program flow generally follows the OSI layers, the fine control flow may hop around quite a bit. For some time people tried to keep the OSI layers as inspiration and use hacks like upcalls to selectively violate layering, which is a sure sign that the layers are unhelpful. Instead, modules should reflect functionality like encryption, NIC interfacing, and routing. Aim for a flatter, horizontal architecture like a B-tree, not a contrived vertical tower with hacks to cross layers "incorrectly". There will be hierachies and layers, but they should be obviously necessary now. Layering is not the end or even the means but merely how things are.

A program's capability (functionality) is determined by the capabilities of its dependencies, and splitting up functionalities well is important. I use this language to relate it to capability-based security[2]. After all, "security" is basically just a stricter form of program "correctness", and just as a terminal emulator's input text handling capability shouldn't have much to do with its window event handling capability because malicious input shouldn't cause dangerous graphics bugs, there isn't much logical reason to have overlap regardless. They govern separate devices, protocols, and purposes. Capabilities along the lines of capability-based security reify the interfaces and provide strict enforcement.

Lastly, flexibility around protocols should be added or discard as given by the precise problem at hand. Don't preemptively choose some extreme, but instead be informed by what is actually desired. It will yield substantial implementation complexity and performance detriments[3] to over-generalize, and of course over-specializing is just inadequate.

  [0] https://prl.khoury.northeastern.edu/img/p-tr-1971.pdf
  [1] https://ieeexplore.ieee.org/document/662046
  [2] https://en.wikipedia.org/wiki/Capability-based_security
  [3] https://ieeexplore.ieee.org/document/208098




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

Search: