3 ms·
This has been obvious to me since I graduated with a BIT majoring in 'Software design.' I literally went to university with software design and software archite
by jongjong 5mo ago
This has been obvious to me since I graduated with a BIT majoring in 'Software design.' I literally went to university with software design and software architecture being my core interests.
When I graduated, I was shocked to learn that no company cared about any of the architectural concepts that I had learned. UML class diagrams, sequence diagrams, ER diagrams, etc... had been on the way out. At one point, as internet companies where scaling up, there was a brief resurgence of interest in sequence diagrams... Especially as a communication method when explaining complex bugs or complex message-passing scenarios. But it didn't really last. Nowadays most software is riddled with race conditions and deep exploitable architectural flaws. Cryptocurrencies have been victims to many such attacks. Billions of dollars have been lost to race conditions... And that's just the ones which were discovered. They are notoriously difficult to find post-implementation.
The programming primitives that we're using today aren't optimized to avoid race conditions or even try to encourage good concurrency patterns; quite the opposite; they encourage convenient but disorganized parallelization and they're optimized to put the focus on type safety which is a far less concerning issue. A lot of people who were rightly alarmed by gaps in schema validation (which is critical at API boundaries) became overly obsessed with type safety (which is a broader concern). I have built some async primitives for Node.js, nobody cared! NOBODY! Other developers have had the same experience with most other languages. I think only a few niche languages like Elixir actually treated it as important. But nobody even acknowledged that the problem could be remedied in existing languages. It's so bad that it seems as though some people wanted it to be that way.
The term 'concurrency safety' doesn't even exist! Some have a vague idea about thread-safety OK, that's very specific to one particular concurrency primitive... but what about the concurrency of asynchronous logic (much more common nowadays)? I have felt thoroughly suppressed in that regard in my career.
The only voice on the subject of architecture that got through to the 'mainstream' was Martin Fowler (one of the inventors of Agile software development). After that, there was Dan Abramov of Redux fame. Some notable opinionated architecture books were published but none really identified the underlying essential philosophy to good architecture.
The best, most succinct quote I ever read on the subject was from Alan Kay (inventor of OOP) who said "I'm sorry that I long ago coined the term 'objects' for this topic because it gets many people to focus on the lesser idea. The big idea is messaging."
I like that quote for many reasons; firstly because it shows wisdom, secondly, it tells you what the issue is, very simply and, thirdly, it hints at the importance of 'focus' in this discipline where we are saturated with thousands of complex overlapping and partially conflicting ideas.
I think the FP trend was somewhat of a red herring. Same with Type Safety. Yes, they were useful to some extent, there are some really good ideas in there, but people got so caught up in them that the most fundamental area of improvement was ignored entirely. To me, the core value proposition of FP can be reduced down to "pass by value is safer than pass by reference." Consider that in the context of Alan Kay's "The big idea is messaging." - Is an object reference a message? NO! A live instance is not a message! Precisely! His point supports pass-by-value, furthermore, it encourages succinct/minimal parameters.
Good architecture is rooted in 2 core concepts. 1. Loose coupling. 2. High cohesion and you achieve those by separating logic + structure from messaging. The biggest mistake people make it passing around structure and logic as parameters to other logic. You should avoid moving around logic and structure at runtime; only messages should move between objects; the simpler the messages, the better. And note that 'avoid' doesn't mean never but it means you have to be extremely careful when you do violate this principle and there should be a really good commercial reason to do so. I.e. You should exhaust other reasonable approaches first.
- kelsier_hathsin 5mo ago> only messages should move between objects Can you provide an example for this?
- burakemir 5mo agoSay you have a Car, Engine and Dashboard object. Let's not have dashboard access the temperature by doing `GetSurroundingCar().engine.temperature` If the dashboard needs to get the temperature from a sensor in the engine, it should be able to "talk" to the sensor, without going through car object. In ideal OOP, a "method call o.m(...)" is considered a message m being sent to o. In practice, field access, value and "data objects" etc are useful. OOP purism isn't necessarily helping if taken to the extreme. The pure OOP idea emphasizes that the structure of a program (how things are composed) should be based on interactions between "units of behavior".
- skydhash 5mo agoI had to learn OOP with common lisp (CLOS) and smalltalk to understand this. Now, I’m leaning towards C, because it’s easier to model a problem with struct and function and not have to deal with the flavor of OOP that some languages foster.
- igouy 5mo ago> Now, I’m leaning towards C Maybe there are other languages?
- bluGill 5mo ago> Say you have a Car, Engine and Dashboard object. Then you should burn the whole thing down and start over! I work on tractors not, cars, but I'm sure the abstractions are similar. Our engine objects are things like [service]AutomationEngine. Our dashboards objects are for a collection of things on secondary displays - meanwhile the thing you would point with your finger as the actual dashboard doesn't have or need a dashboard object. There is an object for things like RPM gauge, or check engine light - this later is a generic fault indicator with a icon field; it is connected to a different messages; and placed in different positions depending on the fault. The point of the above isn't how tractors are designed, it is how the objects you need to design a real OO system rarely have anything to do with that looks like objects. Nobody ever writes dog and cat objects derived from animal; nobody ever writes triangle objects derived from shape.