Live data from Hacker News

A Theory of Software Architecture

danuker.go.ro

231–240 of 246 posts

Re: A Theory of Software Architecture

#231
post #15

Earlier quoted context omitted.

Generally, to those of us who apply the functional approach everywhere, it comes naturally whatever the problem. There are idiomatic ways to program in particular languages (even in Python or JavaScript) which are strictly against the functional approach, even though nothing in those languages prohibits it. It gets trickier with external dependencies which are "forced" on you too. Do you have a concrete "domain" exam…

Multithreaded embedded systems. Yes, the functional people are absolutely correct that shared mutable state is evil. If that's the world you live in, though, you need to deal with it effectively. You need to have thread 1 able to respond to an external event by changing shared state that thread 2 sees, but in a controlled way so that thread 2 never sees an inconsistent state. Now, there is a place for pure functions…

"Multithreaded embedded systems" is not saying much.

My initial hunch is that you've got a lot of existing code that passes and mutates big global state objects around. Still, even your description clearly highlights an issue that is there regardless of whether you want to push for a "functional core": "decisions based on state ... run so thoroughly through the code" _will_ come back and bite you.

It also highlights an easy way to decouple those into simpler functional parts: identify which part of the state is really needed in each part, and only pass that in, and have it return an updated state: basically, the only change you are making is turning the implicit parameters into explicit function arguments and return values. Turning the entire codebase around will be tricky, of course. But perhaps you can switch over chunks of it as the units are readied as you go along.

Of course, if you've got a lot of data that would be expensive to copy around, you might want to keep some of the logic for mutating that non-functional, but you could still decouple that thus making it have a functional core too.

Re: A Theory of Software Architecture

#232
post #135

I spend a lot of time thinking about these sorts of topics (actually, I just taught a 4 hour session yesterday that used most of the terms in this article), working with newer, less experienced developers, and trying to figure how to distill the essence of "architecture" down to something simple that everyone can start with. This is what I’ve started telling people: Use mostly functions, try to make most of them pure…

Interesting. It aligns with my line of thinking. With OOP, the most interesting objects are always stateless and the only "state" present is used for dependency injection.

It seems like in the industry the cost of having state has always been overlooked.

Funny enough, in frontend software this pain surfaced a lot, but in the backend it keeps being unnoticed, at least in the world I live in (Ruby, Javascript).

Re: A Theory of Software Architecture

#233

Earlier quoted context omitted.

Multithreaded embedded systems. Yes, the functional people are absolutely correct that shared mutable state is evil. If that's the world you live in, though, you need to deal with it effectively. You need to have thread 1 able to respond to an external event by changing shared state that thread 2 sees, but in a controlled way so that thread 2 never sees an inconsistent state. Now, there is a place for pure functions…

"Multithreaded embedded systems" is not saying much. My initial hunch is that you've got a lot of existing code that passes and mutates big global state objects around. Still, even your description clearly highlights an issue that is there regardless of whether you want to push for a "functional core": "decisions based on state ... run so thoroughly through the code" _will_ come back and bite you. It also highlights…

Here's a router for television signals. It's got 100 different video sources, 80 different destinations, and "layers" (you can route audio differently from video, though you usually route them together).

You have 6 or so different sources of control (different panel systems, automation systems that use serial interfaces, other automation that uses Ethernet). Each of those is a different thread.

All those different sources of control need to see the same image of what's connected to what. So when one thread makes a change, it has to change for all the threads.

You could think about separating that state into parts, but does that really gain you anything? If you've got 80 variables that behave identically instead of one 80-element array, are you really ahead?

Re: A Theory of Software Architecture

#234
post #78

Earlier quoted context omitted.

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

Very insightful. Can I read more John Carmack's letters somewhere?

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

#235
post #19

Earlier quoted context omitted.

Agree on the functional bit. Naming things: I try to not think about it for more than 10 seconds, and go with the best I've got by then. I find myself renaming things sometimes, and I'm eager to do this when a better name comes to me.

Yes this. Naming is an intuitive thing, you can't force it, and it will get in the way, moreover, it's fluid and won't matter until later, things could change. Just name it whatever and come back to it when it starts to matter more and you've probably thought of something better by then.

Renaming things is a luxury only enjoyed by people who don't have other people using their code downstream. Once people have used it, renaming things becomes a breaking change others in your organization will oppose.

Re: A Theory of Software Architecture

#236
post #126

Earlier quoted context omitted.

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

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…

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

#237
post #135

I spend a lot of time thinking about these sorts of topics (actually, I just taught a 4 hour session yesterday that used most of the terms in this article), working with newer, less experienced developers, and trying to figure how to distill the essence of "architecture" down to something simple that everyone can start with. This is what I’ve started telling people: Use mostly functions, try to make most of them pure…

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

In a similar vein, I look forward to adding less lines and removing more in my git commits.

Re: A Theory of Software Architecture

#238
post #29

Earlier quoted context omitted.

I think the commenter generally views things as code acting on entities. If so, that code is suited to being called an xxxManager, or xxxService, or xxxCoordinator, or xxxController. Of course we have returned to a place in history by doing so, of creating big balls of mud as complexity increases. Peter Coad advocated against this in favor of modeling the problem domain under consideration using an object oriented ap…

>modeling the problem domain under consideration using an object oriented approach Really curious. Do you have any material that explains this way of design? I work on mostly web apps. End of the day, it's really about moving data and transforming data. So most of my programs have no choice but to deal with data, and so, my whole design process revolves around gathering, storing, operating upon and transferring data.

Peter Coad did write a number of books, which are pretty old and likely out of print. How to actually model a complex system into an object oriented domain model, is something I have long thought to teach. However, sadly there seems little appetite in a world currently dominated by procedural code acting on data, modeled using functional decomposition or through a relational data model. Of course our industry will eventually relearn the forgotten lessons and methods of the past, rename them as something new, and adopt them as the new silver bullet for software development.

Re: A Theory of Software Architecture

#239
post #87

When I see a subroutine with a verb in its name I think of side-effects. In my book a pure function should be named after the result it returns, so in this case I would use the name `definition' instead of `find_definition' and `definition_url' instead of `build_url'. For predicates I try to avoid an "is" prefix when a simple adjective is sufficient.

Too bad you're heavily downvoted. Principle "function name is a noun if it returns something, and verb if it doesn't" is super useful - just by looking at its name you know immediately if it has side-effects. Since I learned it I apply it all the time in programs I write alone, but almost always I see pushback in a team because people are unfortunately used to see `getX`, `fetchY` etc. as method names.

I guess a verb phrase comes up naturally when you are eager to implement a new function and think of all the steps required to calculate the result. However, a noun phrase is a more proper abstraction since the implementation may change to simply return a cached value. (see also the Uniform Access Principle).

Anyway, here is my naming strategy:

1. Boolean pure function

Use an adjective phrase where the adjective is the last word, for instance UrlValid or DefinitionFound.

2. Non-boolean pure function

Use a noun phrase where the noun is the last word, for instance CurrentDefinition or DefinitionUrl.

3. Non-pure "function"

Use a verb phrase where the verb is the first word, for instance PrintError or ReadInput.

Re: A Theory of Software Architecture

#240
post #34

Frankly, find_definition should be additionally modified to take a function that consumes a url and returns json data. This way it's easily unit-testable.

That would be dependency injection. It is a valid way to design around side-effects.

Another (equivalent) way to test it is to mock out requests.get and response.json using a mocking library: instead of performing real requests, do what the test wants (return correct data, return unexpected date, or throw an exception).

Post reply on HN