Live data from Hacker News

A Theory of Software Architecture

danuker.go.ro

161–170 of 246 posts

Re: A Theory of Software Architecture

#162

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…

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.

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

#163

But its all rules of thumb and common sense, largely. When are we going to get an axiomatic theory of software engineering/architecture which shall allow us to argue about and compare different architectures for a solution and arrive at an ideal one?

I don't think you'll be able to do that.

What you can is make is define a starting point app in the desired architecture. Then create a list of functional changes to go from starting point, to desired state.

Then you can use various stats for each architecture on how complex was the changes.

Make the functional starting point, the functional list of changes and stats a standard.

Re: A Theory of Software Architecture

#164
"Functional Core / Imperative Shell" is also why I love a combination postgresql/nodejs stack. The transactional sql or plpgsql surrounding the state makes dangerous operations much safer and clean. Then as you get farther from risky state changes, you get the productive flexibility of less strict javascript.

You also get the option of putting complex operations in plpgsql functions when you want them executed atomically without any side effects, corruption, or cleanup requirements when one of the step fails. Your default failure mode becomes "You got an error, everything was automatically reverted, you can safely tweak your request and try again".

Also operations being performed in a monolitic db means that the different pieces of data are much more likely to be loaded in adjacent memory caches and ready to be joined, combined and processed, providing significant efficiency and speed gains.

Re: A Theory of Software Architecture

#165

Earlier quoted context omitted.

But then despite that the class is getting a generated proxy that does basically nothing or is causing the problem and it is really hard to determine anything except tracing it at runtime to find out what actually is being run. People do some crazy things with Spring and interface injections in Java and it can get really Opaque quickly but also often it really is just 1 class implementing an interface and there are n…

For the one project I worked on that was Spring-based, my joke was that Spring was a really effective way to convert compile-time errors into run-time errors :)

> Spring was a really effective way to convert compile-time errors into run-time errors :)

This is not a joke. Spring invalidates refactoring tools and a lot of static analysis. It makes working on Java feel like you are working on Python or something. The traceability of errors is very low. You can limit yourself to a subset of Spring's functionality (eg no component scanning, wiring up the beans manually) but it will not be idiomatic.

Re: A Theory of Software Architecture

#166

I prefer the first example. It’s more straightforward and avoids accidentally creating dependencies (for example some other code calling pluck_definition) that will be make it harder to modify when you need to add features or the API changes. Testing pluck_definition by itself is completely pointless since it does nothing on its own. This is the “test public interfaces, not private implementation” principle. Similarl…

> I also dispute that it’s hard to unit test the first function—-you would simply mock the api response and then you have a great test.

How many times have you seen a test pass or fail when it shouldn’t have because the mocks didn’t match the actual code? It’s a useful technique but it has drawbacks which are not easily prevented.

Re: A Theory of Software Architecture

#167

[Meta] The introduction to the article relies on so much context and assumed knowledge that I almost didn't read past the third paragraph. Who are Uncle Bob, Gary Bernhardt, and Mr. Brandon Rhodes? I have no idea, and I don't need to know who they are to read the rest of the article. (Which itself is extremely well-written.) IMO: Have an introduction that doesn't rely on unneeded context. It's appropriate to credit p…

The author could stand to flip the sentences around a bit, but the introduction is basically trying to say "these three thoughtful guys collectively formulated some useful ideas about software architecture and in this post I will present those ideas".

It is important too attribute ideas to their originators (or at least the source from which one has learned them) and it is good that the OP is doing that.

I agree it could have been done a little more gracefully, though, with just a minor tweak to use phrasing that doesn't seem to assume the reader is familiar with those dudes.

Re: A Theory of Software Architecture

#168

Earlier quoted context omitted.

Perhaps you can explain this part from the post you linked which is perplexing me: > AppDomainAffine, therefore, would be a more appropriate name. Unusual perhaps, but that's because of the common drift toward the mechanics of things and away from concepts (because the mechanics are usually much easier to get for techies) how is 'AppDomainAffine' not a concept?

I read that as saying that AppDomainAffine is a concept, and that's why it's an unusual name, because a lot of naming these days focuses on mechanics instead of concepts (c.f. MarshalByRefObject)

ah okay that makes sense I was thinking it was opposite of that which made no sense

Re: A Theory of Software Architecture

#169
The only mantra about code organization I subscribe to is that it should be as simple as possible. Sometimes it means using several layers of abstraction like in this article. Usually it means just writing the damn thing in the most straightforward way because simple implementations are easy to adapt for future changes.

Re: A Theory of Software Architecture

#170

This is good advice and a good writeup, but I take exception to one (boldface!) line: Coupling kills software I hear this a lot but I think it’s highly overstated. The “clear” final version is still strongly coupled -- you can’t call find_definition without it directly calling the build_url helper! The key aspect isn’t the coupling, it’s that the high-level imperative function is calling a simple, low-level, testable…

This is a common misconception about "coupling". Decoupling is making something truly independent, not making the dependency injectable. Making it injectable is the last resort when you can't make it independent.

The real thing you should be thinking of is, look at those libraries and their documentation / READMEs (depending on library size, smaller actually preferred). Can I make my code modules more like that? Will the API boundaries I define make sense?

Post reply on HN