4 ms·
I came across an article a few weeks ago [1] that distils the idea of this architecture into a very simple pattern, stratified design, or the “Integration Opera
by adamkl 7y ago
I came across an article a few weeks ago [1] that distils the idea of this architecture into a very simple pattern, stratified design, or the “Integration Operation Segregation Principal”:
“A function either integrates or operates, it either only calls other functions or it does not call other functions but contains only logic.”
Basically, you have code that interacts with the outside world, and you have logic (read: conditionals and branching). Don’t mix the two.
It’s such a simple concept that it seems obvious in hind-sight (so maybe that’s why nobody ever talks about it, because it is obvious), but I don’t see code written this way all that often.
If there’s one thing I could teach every new developer it would be this. It’s such a little thing, but it would make a lot of code much easier to work with.
[1] https://medium.com/clean-code-development/stratified-design-over-layered-design-125727c7e15 https://medium.com/clean-code-development/stratified-design-...
- chris_st 7y agoWow, thanks, that's a fantastic article, particularly because it shows actual code that illustrates the idea, instead of being overly abstract.
- veeralpatel979 7y agoFunctional core, imperative shell is how this is commonly described! https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell https://www.destroyallsoftware.com/screencasts/catalog/funct... https://news.ycombinator.com/item?id=18043058 https://news.ycombinator.com/item?id=18043058
- eternalban 7y agoThe article begins with a misunderstanding. The semantic symmetry of the OSI layers is clearly an 'interaction': there is a computer talking to another computer. The stack diagram is obviously only considering a single object, a system. Would not be surprising that should we introduce the 'user' as the peer to the system that we can in fact derive a similar symmetry in layers. Yes, the user side of the layers would be mostly logical 'organizational' concerns.
- edw 7y agoI disagree. The author's point is that if you have a network connection, you can view it as: * A medium with a series of photons or EM waves propagating in one or both directions. * An exchange of packets between two boxes. * … * A conversation between two applications. It's the all the same thing, but it's an increasingly holistic or reductive view of that one thing as you take the thing in from the perspective from increasing or decreasing layers of the OSI stack.
- tsimionescu 7y agoTo me this article looks a lot like the kind of principle that looks very nice in articles but immediately breaks down in practice with even slight complexity. First of all, the difference between operations and integrations makes no sense, even in his examples. All of his functions are calling other functions. All of his integrations are doing some logic (passing results between functions in particular ways). There is no fundamental difference between 'if a then b else c' and 'other_function(a, quote(b), quote(c))'. Second of all, this idea that you don't have dependencies between Presentation and Business only looks like that because he's passing very simplistic data between them. But in real code you have complex data structures and complex interactions and complex invariants and they almost unavoidably introduce dependencies between 'strata'. Even if you force yourself to use maps and strings and lists so you don't have explicit type dependencies, you still get implicit structure dependencies.
- adamkl 7y agoThe premise is not that there are no dependencies of any sort, or that you aren't allowed to pass complex structures from one to the other. Its more about splitting logic (and by logic, he is referring to code with multiple, branching paths) from side-effects. When you mix effectful code (rendering to the UI, accessing a database) with conditional logic, you need to resort to mocking (potentially complex) objects just to perform basic unit testing. He's simply stating that if you split those out into different functions (operations in his case) and use a simple function to integrate them together, it will make life easier, and I agree. Its a very functional approach; get data, perform calculation, return data. Like I said, I thought article did a good job of distilling an important idea into a simple pattern. It doesn't have to be an overarching architectural design; even just using it locally in a larger code base can make life easier. *As an aside, I'd say there is a fundamental difference between: 'if a then b else c' and 'other_function(a, quote(b), quote(c))` The first, when tested inside the scope of its parent function needs multiple unit tests for full coverage, the second only needs one.
- tsimionescu 7y agoI think the last point is the most important - if there really is a difference between those two pieces of code, then the article does make some sense. If there isn't, the the article's pout is weakened. The reason why I think they are equivalent is that other_function may well be really reusable and have many different use cases, of which only one is right in my current use case. For example, it could be the 'if' special form in Lisp. That means, I can know for sure that other_function is itself perfectly correct, but still be calling it badly, so I still need to test whether my function does the right thing for any possible value of a, b and c.
- jfengel 7y agoI don't understand what the article means by "logic". "Ask_for_text() and Display_word_count() contain only logic" but "Count_words{} does not contain any logic". The requirement to remove stop words is accomplished by a piece of "logic". If that requirement were removed, a test would change, and the place you'd go to fix that test would be Count_words. If "logic" means "stateful" or "I/O", then OK, I get it, even if I find the terminology unfamiliar. But in familiar terms it looks a lot like MVC.