Live data from Hacker News

A Theory of Software Architecture

danuker.go.ro

211–220 of 246 posts

Re: A Theory of Software Architecture

#211
Software architecture, as I understand it, applies to a particular software product/solution. Architecture is your opportunity to choose which problems will be easy and which problems will be hard. For example, a microservices architecture makes HA easy but global consistency and data locality/caching hard. A centralized database architecture is the mirror image.

The article discusses architecture in the abstract, which sounds more like a programming model or paradigm (OOP, functional, actor model, imperative), or maybe a pattern.

Wouldn't it be weird to discuss building architecture in the abstract, without a notion of the site to build on or the purpose of the building?

Re: A Theory of Software Architecture

#212

Earlier quoted context omitted.

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?

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

#213
post #183
post #166

Earlier quoted context omitted.

> 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.

We use mocks a lot on my team, and I don't think we've ever seen what you describe. Maybe you're using mocks incorrectly?

You might also want to consider the possibilities that you have problems but haven't noticed them yet or that your experience is not a global truth applicable to all projects.

If you think about the problem more, ask yourself how it's possible to mock a remote HTTP call without the risk of this problem? I've seen people write frameworks which periodically save and cache responses but unless you regularly perform some kind of validation there's no way to avoid that problem.

Re: A Theory of Software Architecture

#214

Earlier quoted context omitted.

> Use mostly functions, try to make most of them pure. This reminds me of: > Eat food, not too much, mostly plants > > -- Michael Pollan My new mantra: Write software, not too much, mostly functions.

"Not too much" is interesting. If I understand you correctly, you can write "too much software". I can think of at least three ways - bad architecture, too little abstraction forcing repetition, and just bad writing. Did you have something else in mind here?

I have been net negative lines of code for the month more than once, while productively adding more features and fixing bugs. There is a lot of code out there that need not exist at all.

Re: A Theory of Software Architecture

#215

Earlier quoted context omitted.

It's not a problem if you're using a proper IDE. Rider and IDEA will take you right to the implementation (or will display a list if there are multiple implementations) on Ctrl+Alt+B. This works on any of the parent classes/interfaces, or any inherited field or method.

> It's not a problem if you're using a proper IDE. From another POV it's IDE vendor lock-in: make the basic programming exercise so challenging that the users have to buy your special tool to even attempt it.

We just did a major reorg, and everyone who promoted that locked in tool got let go. There were other reasons for the reorg, but take this as a warning, if the tool you promote isn't productive you lose your job.

Re: A Theory of Software Architecture

#216

Earlier quoted context omitted.

> Use mostly functions, try to make most of them pure. This reminds me of: > Eat food, not too much, mostly plants > > -- Michael Pollan My new mantra: Write software, not too much, mostly functions.

"Not too much" is interesting. If I understand you correctly, you can write "too much software". I can think of at least three ways - bad architecture, too little abstraction forcing repetition, and just bad writing. Did you have something else in mind here?

NIH or Resume-Driven Development might be another way.

From personal experience, I worked with a team years ago where product owners wanted a datetime picker or parser for an app we had built. Senior dev on team decided it would be cool if it included some lite NLP. When product owners heard from him how easy it would be to add, they were on board.

He started with a popular existing Python library. But there was a bug with one corner case that was causing problems. So he took the initiative to spend a few extra days on the story to write his own simple NLP date parser.

A couple months later, early on Jan 1st, the new feature wished our ops team Happy New Year by taking down our application.

I happened to open an issue for the library's bug on Github after learning about it from the other dev. The owner there promptly responded to share a simple workaround for the issue. But by that time we already had too much software on our hands.

Re: A Theory of Software Architecture

#218

Earlier quoted context omitted.

> It's not a problem if you're using a proper IDE. From another POV it's IDE vendor lock-in: make the basic programming exercise so challenging that the users have to buy your special tool to even attempt it.

We just did a major reorg, and everyone who promoted that locked in tool got let go. There were other reasons for the reorg, but take this as a warning, if the tool you promote isn't productive you lose your job.

Without additional context, that seems a bit extreme. People often promote tools because they have some experience and have not (yet) had a poor experience with them.

Re: A Theory of Software Architecture

#219

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…

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.

Re: A Theory of Software Architecture

#220
post #118

Earlier quoted context omitted.

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.

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 unstructur…

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.
Post reply on HN