News for hackers. Stuff that matters.
Re:A Theory of Software Architecture by speedgoose on Wednesday October 28, 2020 @03:06AM (#24916063)
I understand that the point of his example is to introduce the reader to a variant of the very classic multitier architecture with layers.

https://en.wikipedia.org/wiki/Multitier_architecture

But I prefer the first version of the example, because while it's named "complex code" I think it's the simplest version. I think that there is no need to decouple this simple and straightforward function in three functions that cannot be reused independently. Splitting a function in smaller functions make sense where the code is complex, but I think it's important to not overly do it.

Re:A Theory of Software Architecture by hyko on Wednesday October 28, 2020 @04:41AM (#24916589)
I don't think this is a very good example of clean architecture; this is just a refactoring that extracts three methods. There's no dependency inversion used here, which is one of the key tools you would use to create a clean architecture. The use case itself depends directly on the functionality in requests, which means the business logic is coupled to the concrete details of the requests API.

Clean architecture also differs from n-tier in that–although there are layers, they don't have to be physically distinct and the APIs between them are not typically heavyweight gateways designed to work across network boundaries etc. The key design activity in CA is reducing the coupling between abstract business logic and the concrete code that executes it. It's actually quite a simple approach to describe, but more difficult in practice.

There's nothing particularly wrong with the first function; functions certainly don't only have to "do one thing" in clean architecture.

Re:A Theory of Software Architecture by cies on Wednesday October 28, 2020 @03:51AM (#24916298)
I find the Multitier Arch (MA) has much better names.

The arch proposed by the article has "Application Business Rules" (ABRs) and "Enterprise Business Rules" (EBRs). Now in a small start-up, what are the "enterprise rules", is "enterprise" not merely a buzzword in this context? And how ABRs and EBRs differ is not well explained.

In MA this is much clearer: the Data Access Layer (DAL) contains DAOs (the persistence side of the model in MVC), Business Layer (BL) contains the business/domain logic (the other side of the M in MVC and/or the business logic that may end up in the C of MVC; aka services in Rails), the Application Layer (AL) contains what would be typical "controller logic" (authorization/redirection/data gathering for the presentation) in MVC and the Presentation Layer (PL) contains the V from MVC.

> [...] I think it's important to not overly do it.

Yups. So maybe one can do without a BL at first, and put the business logic in the DAL at first and dont mind to have a litttttle bit of it creaping into the AL (controller).

Re:A Theory of Software Architecture by yokto on Wednesday October 28, 2020 @05:24PM (#24924296)
I've always been confused by the Clean Architecture and even somewhat dismissive, because the terms used are so "not Clean" (from my perspective biased towards startup/indie/freelance). Multitier Arch is already 10 times more appealing just by using more appropriate words.
Re:A Theory of Software Architecture by ravenstine on Wednesday October 28, 2020 @04:49AM (#24916644)
This reminds me of Brian Will's "Object-orientation is Bad" where he makes the case that most decoupling tends to be more confusing than long-form code that's got sufficient comments.

https://youtu.be/QM1iUe6IofM?t=2235

Re:A Theory of Software Architecture by rvense on Wednesday October 28, 2020 @06:34AM (#24917222)
I think that

    fn x() {
        doStuff();
        moreStuff();
        forgotSomething();
    }
is pretty bad code, but that's probably because I consider procedures with no arguments and no return value a sign that something is poorly factored. However,

    fn x(y) {
       foo = doStuff(y);
       bar = moreStuff(foo);
       if (isSomething(bar)) {
           return theRest(bar)
       } else {
           return theBest(bar);
       }
    }
can be a good way to separate the why from the how and clearly communicate what's going on, especially with conditionals in the mix.

It's important, however, that these helper functions are not haphazardly strewn around the code base and accessible to things that don't need them. Depending on the language/context, I'd reach for nested function definitions or public/private keywords (or a combination), because definitely, it can be very hard to approach a big file with a bunch of (often poorly-named) functions that are defined at the same hierarchical level but not meant to be used at the same level.

Re:A Theory of Software Architecture by toomanybeersies on Wednesday October 28, 2020 @07:10AM (#24917426)
Haven't you just described functional vs procedural programming?
Re:A Theory of Software Architecture by dathinab on Wednesday October 28, 2020 @08:08AM (#24917788)
No he described implicit arguments and mutation vs. explicit arguments and mutation.

It's independent of OOP vs. functional, through it's easier to have implicit arguments and mutation in OOP so you see it more often there, especially if people somehow ended up believing that programming OOP means you need to create a class for everything and make all states a object member instead of e.g. a variable in the stack.

Re:A Theory of Software Architecture by rvense on Wednesday October 28, 2020 @08:50AM (#24918113)
Yes! I often see code that where a method sets an instance variable, then calls another method that does some work based on that instance variable, which is then not used until the next time that first caller is used. The instance variable is redundant, and the control flow is obfuscated. I think the principle is just to only expose something when you really have to (harhar), and that the 70's suspicion of unstructured use of global scope should be equally directed to class scope.
Re:A Theory of Software Architecture by amw-zero on Wednesday October 28, 2020 @03:36PM (#24923198)
That's called temporal coupling, where some code only works if some previous code set some variable earlier in time. And it's a sign that you're building an implicit state machine.
Re:A Theory of Software Architecture by valenterry on Wednesday October 28, 2020 @12:00PM (#24920333)
It's not explicitly expressed (the functions could still execute sideeffects and e.g. mutate things), but yes, that is pretty much the style that pure functional programming enforces!.
Re:A Theory of Software Architecture by peterwwillis on Wednesday October 28, 2020 @06:56AM (#24917346)
The former example was much easier for me to understand than the latter, even if it wasn't factored well. But I'm assuming that the functions aren't mucking about with global state or something equally distasteful.
Re:A Theory of Software Architecture by rvense on Wednesday October 28, 2020 @09:15AM (#24918335)
Well, if we assume that both are doing the same work, then the explicitly named variables y, foo, and bar of my second example would, in the first example, have to be global variables, or at least things that are defined in the scope of the definition/call of x.

Given that, I have to say that I, err, and I'm sorry if this sounds a little arrogant, but I don't really believe you when you say that it's easier to understand. It might be easier on the eyes, sure, but to really understand how the first one works, you'd have to look into all the defined helper functions, and see which outer-scope variables they touch (global/module/class scope), and also, probably, have some knowledge of where x is called. In a style closer to the second example, there are less outside dependencies.

Of course, this is all very abstract. I'm not saying there aren't cases where a few variables in global (or class) scope that get mutated by bare functions can't work at all, but as a rule I don't consider it a good style.

Re:A Theory of Software Architecture by peterwwillis on Wednesday October 28, 2020 @08:36PM (#24925819)
I don't really fully understand how the kernel scheduler works, but I know in general how it works, and so I can write software using it. In this sense, a simple implicit abstraction is easier for me to understand than one where I'm peeking under the covers, so to speak.

Even just seeing a few variables or objects passed around, I still don't know exactly what it's doing, or hiding. I can more quickly understand the high level idea with the former example without the details potentially confusing me.

Re:A Theory of Software Architecture by rvense on Thursday October 29, 2020 @02:55AM (#24927978)
I see what you mean.

I think it depends on the type of code and how you interact with it. A library that requires its consumer to keep track of a bunch of data and pass it in and out at the right times when it could just as well handle internally is not a very good library. But if we say that all the code the above example is from an application, where a normal change might involve touching all of the mentioned functions, making it explicit where some variable is used.

Re:A Theory of Software Architecture by shock on Wednesday October 28, 2020 @08:15AM (#24917830)
> But I'm assuming that the functions aren't mucking about with global state or something equally distasteful.

There's not much else for them to do, since they don't take arguments, but to muck about with global state and/or have side effects.

Re:A Theory of Software Architecture by skinkestek on Wednesday October 28, 2020 @07:38AM (#24917588)
> But I'm assuming that the functions aren't mucking about with global state or something equally distasteful.

It seems fairly obvious to me that either the former example is waaaay simpler or it is doing something really distasteful.

Re:A Theory of Software Architecture by peterwwillis on Wednesday October 28, 2020 @08:42PM (#24925853)
Some designs don't require your own code to pass around state between functions, because each function can handle state in its own way without dependence on other functions. I've written a lot of such simple scripts where I just need to execute a series of tasks that aren't necessarily related to one another, but do follow each other.
Re:A Theory of Software Architecture by ZephyrBlu on Wednesday October 28, 2020 @05:11AM (#24916760)
I hate unnecessary functions with a passion and it's refreshing to hear his opinion.

Sometimes a big, fat block of code is just easier to understand.

Re:A Theory of Software Architecture by wsc981 on Wednesday October 28, 2020 @05:21AM (#24916811)
> Sometimes a big, fat block of code is just easier to understand.

John Carmack made once the same comment: http://number-none.com/blow/blog/programming/2014/09/26/carm...

Re:A Theory of Software Architecture by tarruda on Wednesday October 28, 2020 @08:05AM (#24917764)
> I don’t think that purely functional programming writ large is a pragmatic development plan, because it makes for very obscure code

As a functional programming enthusiast, I agree with this.

Recently I worked on rewriting a relatively large backbone web application in React/Redux (For those that don't know, Redux is a framework for writing JS in a more functional style).

While moving all app logic to functional style makes it safer and easily testable, it is definitely not friendly to most programmers that maintain it. We've had lots of bugs caused by new people coming in, not understanding the functional style and making bad changes such:

- Doing side effects from functions that are assumed to be pure.

- Writing a lot of logic into functions that are directly doing side effects, instead of refactoring the decision making into reducers.

While I still love mostly pure functional code, I would only recommend it for smaller projects, where one or few developers with strong grasp of the style would strictly review every new PR to ensure new people don't mess up.

Re:A Theory of Software Architecture by ratww on Wednesday October 28, 2020 @09:42AM (#24918621)
You're not wrong, but I don't really think this is the fault of FP.

I had the exact same experience with people not understanding new paradigms with Procedural (programmers experienced with Assembly using GOTO for everything), OOP (programmers used to procedural using only static methods), MVC (by putting everything in the controllers and ignoring views/modules/helpers), MVVM (by modifying state by themselves instead of using the MVVM mechanism).

All those things were always "obscure" for newcomers since it was different from what they learned in college, but after a while they became second nature.

I think the answer is not to avoid those paradigms because they're hard, but rather to teach people how to work with them. It's expensive but it's only way forward IMO.

Re:A Theory of Software Architecture by marcosdumay on Wednesday October 28, 2020 @09:19AM (#24918373)
> Doing side effects from functions that are assumed to be pure.

That completely goes away as soon as your language has purity declared at the type system.

It's just not available for Javascript development, like most nice FP features.

Re:A Theory of Software Architecture by nendroid on Wednesday October 28, 2020 @01:32PM (#24921658)
That's because JS is not a functional language. You are enforcing a functional style by discipline. Additionally a huge portion of benefits of the functional style are lost on untyped languages. If you're not using typescript you're dealing with a lot of unnecessary bugs.

If you guys moved to a fully functional paradigm where the language enforces the functional style you will see greater benefits.

Unfortunately for the front end the ecosystem for functional languages outside of TS/JS is not that great. But an easy one to try out to actually see the benefits I recommend writing a little app with ELM. With something like ELM, the functional style is enforced by the compiler. You will see that 90% of the bugs you typically deal with in JS/TS will disappear. One type of bug that will disappear is runtime errors. Runtime errors are not possible in ELM.

I find a lot of JS programmers haven't fully grokked the functional style. Example: You'll find JS programmers who talk about how much they like functional programming but don't understand why for loops don't exist in functional programming.

Re:A Theory of Software Architecture by UK-Al05 on Wednesday October 28, 2020 @08:07AM (#24917774)
I haven't read that in awhile. But the argument was around optimisation rather how easy it is to understand.
Re:A Theory of Software Architecture by wsc981 on Wednesday October 28, 2020 @08:24AM (#24917889)
The way I read the article, I believe his main point was to make reasoning about state easier, even at a small cost to performance, making code easier to test and debug.
Re:A Theory of Software Architecture by ratww on Wednesday October 28, 2020 @09:47AM (#24918666)
Not really, Carmack explicitly states that this is not a performance optimisation in the article:

> In no way, shape, or form am I making a case that avoiding function calls alone directly helps performance.

Rather, he argues that (among other things) this is a way to make current bugs more visible and to avoid future bugs by disallowing calling functions that should be inlined.

Re:A Theory of Software Architecture by laegooose on Wednesday October 28, 2020 @07:13AM (#24917448)
Very insightful. Can I read more John Carmack's letters somewhere?
Re:A Theory of Software Architecture by wsc981 on Thursday October 29, 2020 @12:57AM (#24927380)
Took me a while to find something useful, but here you are:

https://fabiensanglard.net/fd_proxy/doom3/pdfs/

Re:A Theory of Software Architecture by laegooose on Sunday November 01, 2020 @04:02PM (#24962480)
Wow that's a lot of interviews and letters. Cheers
Re:A Theory of Software Architecture by anotherforsure on Wednesday October 28, 2020 @01:28PM (#24921594)
If you have a well documented system, OWNED by a software architect, then breaking it down is better.

If you don't have that, at least big fat blocks of code are self documenting...

Re:A Theory of Software Architecture by xorcist on Wednesday October 28, 2020 @06:32AM (#24917209)
Thank you for this.

It has been a strongly held opinion of mine for a very long time, but I haven't been able to state it as eloquently as that.

Re:A Theory of Software Architecture by zytek on Wednesday October 28, 2020 @04:51AM (#24916658)
I love his series. Eye opener for beginner coders.
Re:A Theory of Software Architecture by ratww on Wednesday October 28, 2020 @06:38AM (#24917242)
Agreed. IMO it's an eye opener for experienced coders too.
Re:A Theory of Software Architecture by valenterry on Wednesday October 28, 2020 @04:50AM (#24916652)
If that is a simple 10 line script, I agree. But if that is part of an application, you will not be able to properly test it - so you either have to do time consuming manual tests or time consuming integration tests. Splitting it into different parts allows to write unit tests and smaller integration tests. Then, when you only change the "pure" parts, you only have to verify the unit tests. That gives a HUGE productivity boost in bigger applications.
Re:A Theory of Software Architecture by MeteorMarc on Wednesday October 28, 2020 @05:39AM (#24916909)
You only want to test on public API, because else you cannot change the implementation without adapting your perfect unit test on implementation details. So, I prefer the first code example and do not mind some mocking (unless the extracted functions make sense on the public API).
Re:A Theory of Software Architecture by valenterry on Wednesday October 28, 2020 @11:54AM (#24920262)
If you take that idea/ideal to the very logical end, then you can only do system tests / acceptance tests (however you want to call it). Your tests must only be able to do what end-users do - everything else would be relying on implementation details. No unit tests at all!

...unless we take a more compositional approach and define our application to consist of many "parts" each of which has a public API and an implementation. Well, in that case I would argue that each function can be considered as such a part, having a public API (the definition of its inputs and outputs) and an implementation that can be changed while keeping the public API stable.

Over the time I came reached a conclusion: whenever I have to run some code to be sure it does what it should, I write a test instead. And every often that is a unit test. If I'm highly confident that the code will do what I expect, then I rely on very high level system tests, unless I fear that someone might break the code later by accident without the compiler (or other existing tests) being able to detect that.

Re:A Theory of Software Architecture by winkeltripel on Wednesday October 28, 2020 @06:26AM (#24917172)
A large application has lots of implementation leak to the API, doesn't it?
Re:A Theory of Software Architecture by Izkata on Wednesday October 28, 2020 @09:23AM (#24918427)
For this reason, when mocks are involved (that is, just about any external API), I think Listing 2 is the ideal - extract a small function designed around the desired interface, a facade that's easily mockable and won't change with the library implementation.
Re:A Theory of Software Architecture by ghosty141 on Wednesday October 28, 2020 @03:58AM (#24916331)
Lile the author wrote, the example is only an example, in the real world those functions are way bigger. Such a small function would be fine but most functions are far bigger and often call other functions that again do some IO.
Re:A Theory of Software Architecture by seer on Wednesday October 28, 2020 @08:00AM (#24917736)
I usually look at this in the form of “layers”. If you have a lot of duplicated logic, its a lot nicer to abstract those concerns into a “layer” of functions / classes.

Whats important is to not have leaky abstractions though. The moment you need to start reading into those functions is the moment you realize you would have been better off leaving the code as is.

Its very hard (at least for me) to come up with those layers and requires a ton of iteration. Thats why I also prefer the top example - you need to work with the lower level code first, and go through enough of it before you can start spotting patterns and creating layers, otherwise you’re bound to mess things quite a bit.

Re:A Theory of Software Architecture by koonsolo on Wednesday October 28, 2020 @07:02AM (#24917378)
As someone who's been coding for 25 years, I agree with you.

I want code to be "clean and simple". Thats how I judge my own code and everyone else's. And the first example is indeed cleaner and simpler.

In my theory, you are only allowed to introduce more complexity (functions, frameworks, etc), when it makes it overall simpler and cleaner than before.

Re:A Theory of Software Architecture by mac01021 on Wednesday October 28, 2020 @11:14AM (#24919689)
You don't think

    def find_definition(word):           # Listing 3
        url = build_url(word)
        data = requests.get(url).json()  # I/O
        return pluck_definition(data)
is more readable that the original code that inlines the definitions of both helper functions?
Re:A Theory of Software Architecture by koonsolo on Wednesday October 28, 2020 @02:12PM (#24922169)
The original code is 9 lines, and it's very clear what it does.

Now you have a 'build_url' method, which is a bad name to start with. It's actually a 'build_def_request_url' or something like that.

Imagine you add another method find_synonyms(word). My quick brain would think I can use that same build_url() method. Wrong, because one needs a build_def_request_url() and the other a build_synonyms_request_url().

Let's say I need to debug and need to see what url it's calling. In the original code it's right there, here I have to on a goose chase to find my answer. One thing that wasn't refactored is putting the hardcoded url into a constant. That one I would do.

Another complexity is adapting one of the helper functions. If I adapt it, which callers could I break? Who is using this function?

Another part is that I would rewrite the pluck_definition(data) to a more generic get_value(data, u'Definition'). That way my other potential find_synonyms() could also use it, and it basically adds no extra lines of code except for an extra parameter.

I know this is an easy example to explain things, but the original code needs to be way more complex to justify it splitting up into multiple functions, that in this case can serve nothing else but that original function.

Just my feeling towards this code.

Re:A Theory of Software Architecture by rsa25519 on Wednesday October 28, 2020 @03:34AM (#24916206)
Agreed. Abstractions are more mentally expensive than a single concrete idea but less expensive than many concrete ideas. When something doesn't need to be abstract, especially in a language where refactoring is easy, it should not be abstract.
Re:A Theory of Software Architecture by berkes on Wednesday October 28, 2020 @04:03AM (#24916372)
Or, how I would put it more pragmatic: the first example is a sure way towards seven slightly different mechanisms to call an Api. Per year. On a team with seven devs.
Re:A Theory of Software Architecture by mathw on Wednesday October 28, 2020 @04:09AM (#24916413)
Not doing the first example is a sure way towards either copying that function and changing it a bit because you need a slightly different call, or a function with a pile of branches in it because it needs to operate in several modes.

Both ways could go wrong. I don't care what your architectural choice is, you can still mess it up.

Re:A Theory of Software Architecture by Tempest1981 on Wednesday October 28, 2020 @04:33AM (#24916542)
If so, then please add 2 comment lines above each "chunk", for faster human reading, and everyone will be happy:

// build URL

// find "definition"

Re:A Theory of Software Architecture by UK-Al05 on Wednesday October 28, 2020 @08:03AM (#24917754)
Multi-tier is different compared to say hex or clean, in that depedencies for edges of the system depend on interfaces in the "Core".

Tradtional mulit-tier the UI depends on Business Logic, Buinsess Logic depends on persistence etc

The idea is protect the core, and persistence or UI concerns adapt to how the core wants to interact with the world.

Re:A Theory of Software Architecture by froman88 on Wednesday October 28, 2020 @09:23AM (#24918414)
I agree that it may be overkill for such a simple function, but the author (at least the original author, Brandon Rhodes) is drawing an analogy to more complex applications.

He uses such a simple example so that his idea that applies to much larger, more complex codebases can expressed in a presentation/article, not to argue that all such simple functions need this level of decoupling.

https://en.wikipedia.org/wiki/Straw_man#Steelmanning

Re:A Theory of Software Architecture by nahname on Wednesday October 28, 2020 @09:19AM (#24918367)
There are people who cannot use an abstraction unless they understand every line of code behind it. Abstractions are blockers, rather than aids. This lowers the value of abstraction for those individuals.

Others find it tiresome to read every line of code and develop intuition around abstractions instead. The "find_definition" function will be all that is parsed.

The funny thing is people shift between the two as the scope of the project increases.

Re:A Theory of Software Architecture by bluGill on Wednesday October 28, 2020 @09:37AM (#24918584)
In a real project - millions of lines of code - there is no chance to understand it all. You have to trust the abstraction does what it says without caring how it works. You only break the abstraction and understand when you have reason to suspect that it somehow isn't obeying your quick mental model of what it does - normally this means you suspect the bug you are working on is down that abstraction, but sometimes it is just the name is bad and so you need to figure out what it is really doing.
Re:A Theory of Software Architecture by sidlls on Wednesday October 28, 2020 @03:36PM (#24923190)
Often this is done in the name of "testability" by the the "(unit) test everything" zealots. I've met some of them who haven't seen a function they wouldn'tsplit up to test different branches or what have you independently. The resulting code is frequently a nightmare of function aliases, mocks and other problematic artifices.