|
I'm a firm believer their decline started with the corporate charter.
Growth is only good when it's not cancer.
|
|
|
|
|
I was watching a commentary video (Scams In Software Engineering[^]) by Primeagen (funny youtuber who really understands dev and comments on development ideas).
While watching that video he mentions:
“The primary feature for easy maintenance is locality: Locality is that characteristic of source code that enables a programmer to understand that source by looking at only a small portion of it.”
The behaviour of a unit of code should be as obvious as possible by looking only at that unit of code
This is actually something I have been interested in for a long time and why I wrote a recent article here on CP: Is Dependency Injection the Missing Technique That's Holding Your Career Back? [^]
In that article I discuss how that DI causes a redirection of code (lack of Locality Of Behavior) so bad that DI can be quite terrible.
Two Issues
1) Seeing a call to a method DoThatThing() , only to discover that the implementation is in an injected class that is in another assembly and then you have to jump into that assembly to even see what it is doing, is a terrible part about DI.
2) Added on top of that, you have to know how all of the associated classes work to understand how the small piece of code works.
EDIT
Also, this idea of getting Locality of Behavior could be a naive one also. Meaning that only simple problems can have simple code and advanced coding for larger systems may require more obscurity in the code due to necessity of DI, patterns etc.
What do you think?
modified 9-Apr-24 10:17am.
|
|
|
|
|
Larger systems won't demonstrate locality of behavior because of frameworks that use polymorphism and inheritance to invoke application classes. That's not much of a problem because people working on the system will be familiar with its frameworks, so all they'll usually need to look at are application classes. If the frameworks are well designed, all the code for an individual application will be colocated, making it possible to understand that application even though its implementation is scattered among various colocated classes.
When the DoThatThing in your DI example resolves to a specific target without the use of polymorphism or inheritance, I never got the point. It seems like artificial complexity and needless boilerplate.
|
|
|
|
|
Greg Utas wrote: That's not much of a problem because people working on the system will be familiar with its frameworks
But this can be a "training issue" and even more so depending upon how many "company-specific" patterns are used.
This, in turn, means that you're always slower on maintenance and enhancements because "we always have to train new devs in our patterns so they can even fix one simple bug.
Greg Utas wrote: If the frameworks are well designed
Emphasis on if...
(Yes, I'm being a bit facetious.)
You make good points but man code is just so often terribly obfuscated -- and especially so when DI is involved. That was my point of DoThatThing : no you can't just see the implementation here, you have to jump into another class then another one that is in another assembly and
You have to have the Gestalt of the entire system in your head before you can do one simple thing.
|
|
|
|
|
The training issue can't be avoided with new devs. If you don't have frameworks, you'll have spaghetti, which will be even worse. Nested function traces are a great way to help new devs navigate the code.
|
|
|
|
|
That's why I don't necessarily agree with the idea that having it spread out across classes in the same solution is "just fine" not at all deserving of a tiny bit of a spaghetti moniker.
You get two levels of indirection with some patterns. These patterns deliver... things (CQRS/event sourcing), but imo, you should probably have a significant team size with many juniors to get ROI on it.
Lately, I don't think many want to hire junior/entry. They want to hire people for whom this sort of thing will just ultimately be ball and chain.
I think the thing with this is that it is mostly minor annoyance for more avg-to-senior devs but from the bottom to a bit above avg it is holding them back probably far more than it is protecting our codebases. Have reviews and teach people. This sadomasochistic forcing of pain by pattern in the name of quality that still won't be there is a bit nonsense.
Teach what makes quality if you want quality, don't teach that pain makes gain. It doesn't and it's impossible from the perspective of students' in this scenario to grok the difference. If they could, it would have less value to do it. To me, it feels a whole lot like slews of this stuff are thinly veiled gatekeeping aimed at increasing complexity to maintain superiority by tumbling trashcans as the elite flee the scene. But I might be a bit of a cynic.
|
|
|
|
|
Thanks for posting. So many great things in your post.
jochance wrote: not at all deserving of a tiny bit of a spaghetti moniker.
That's exactly right! Software "Engineers" are often ready to cast aspersions upon code that "isn't following an exact pattern" by saying it is spaghetti. I'm not talking about bad code with no structure at all. I'm talking about the fact that often patterns are over-wrought & forced into a solution with little to no benefit, except that they're considered "pretty" to software "egineers".
jochance wrote: They want to hire people for whom this sort of thing will just ultimately be ball and chain.
Very true.
jochance wrote: This sadomasochistic forcing of pain by pattern in the name of quality that still won't be there is a bit nonsense.
Exactly! MOst of the problems still exist -- they just exist at a different level.
You're still going to have issues doing maintenance and enhancements. (again, I'm not talking about completely unstructured code with globals everywhere, etc.)
jochance wrote: To me, it feels a whole lot like slews of this stuff are thinly veiled gatekeeping aimed at increasing complexity to maintain superiority by tumbling trashcans as the elite flee the scene.
I agree. It has a feel of making sure that Software Engineers can create a wall between them and the minions and almost is a form of virtue signaling in Software Design. "Oh, I use the Strategy pattern with a Decorator here." Ok. ok, software "engineer", you've hit me over the head with it.
And, yes I believe in patterns, DI, designing toward interfaces, etc. But I believe in it when it has a specific purpose.
|
|
|
|
|
I think you're taking "locality of behaviour" a little too literal.
It's not like all code has to be in a single method or something like that.
Quite the contrary.
Let's say we have a function that fetches an entity from some service, inserts that entity into the database and then returns the ID.
Now, if everything was "local" you'd create an HttpClient, do the fetching, then establish a database connection and do the insert while returning the ID.
You now have to look at one function to understand what it does and to change the behaviour (for example, add a property).
However, you've also coupled your service to your database.
One can't exist without the other.
I probably don't have to explain it would make a lot more sense to create a class that deals with the service and a class that deals with the database insert.
Your function could now look something like:
var something = service.Fetch();
return repository.Insert(something); That's a gross oversimplification, but you get the gist.
In this example, service and repository are probably injected.
Now you could argue that you don't understand what this code does anymore, but I'd say that's not true.
You still understand the code, it's just that its internals are hidden from you so you don't know how it does it.
Now, let's say a property is added to the service and you also need to store it in the database.
This is where the true locality comes into play.
Because both changes are local to their respective function.
So the service change is a different one from your database change because they're now isolated units of code.
They could be implemented by different teams, the service change could already be implemented while waiting for the database team to add a new column to a table.
And now other parts of the code can also use service.Fetch and repository.Insert in the same way.
Yes, you'll still need to figure out what type of service and repository is (probably some instance of IService and IRepository), but that should be easier than maintaining a long function that does multiple things.
Now how would this code not be "local"?
Let's say the implementation of service.Fetch would do something like "&type=CUST" and then in your repository.Insert you also do a check on "CUST", or some other check that has to do with the internals of service.Fetch .
You'll now always have to change two functions that seem isolated, but really aren't (and you have to know this or you'll break the code!).
Or when service.Fetch does the call to repository.Insert , because you'd think you can fetch, but it's now still coupled to a specific database action.
So in conclusion, don't think of "locality of code" as "code has to be local", but "code has to be as local as possible", which is not the same
The author mentions it too, saying it's often a trade-off
|
|
|
|
|
Sander Rossel wrote: I think you're taking "locality of behaviour" a little too literal.
Yes, I was thinking that all code should just be in one file. I think you were taking what I said too literal.
No, I'm just experiencing code where there are Interfaces for every class in the system.
Have you ever looked at code where there is literally an Interface for everything?
Sander Rossel wrote: don't think of "locality of code" as "code has to be local", but "code has to be as local as possible", which is not the same
The author mentions it too, saying it's often a trade-off
Yep, balance. That's what I'm looking for.
However, much code is often extreme one way or the other and I'd often heard of reasons to break code apart, use patterns, design to Interfaces,
but never heard Locality of Behavior mentioned.
Which seemed unbalanced.
modified 10-Apr-24 9:06am.
|
|
|
|
|
raddevus wrote: how that DI causes a redirection of code (lack of Locality Of Behavior) so bad that DI can be quite terrible.
But wait - then the code won't be cool!
|
|
|
|
|
Question: Why did you join the network?
Original in german: Quote: Weil ich nicht einverstanden bin, wie manche Sachen laufen und, für mich, die beste Art etwas zu verbessern ist, ärmeln hochzukrempeln und aktiv anzupacken
I would say:
Because I didn't like how things are being done and, for me, the best way to improve something is, to roll up one's sleeves and actively ...
tackle it // seize it // go for it // something else?
Improvements about the whole sentence are welcome.
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
..., die Ärmel hochzukrempeln und [Dinge] aktiv anzupacken
..., to roll up your sleeves and actively tackle [things]
|
|
|
|
|
Thanks
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
These sentences have the same gist.
1. I believe in taking a hands-on approach to improve things when I see they're not going in the right direction.
2. When things aren't going well, I prefer to dive in and make a difference.
|
|
|
|
|
Thank you
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
Some more ideas come to mind.
1. Getting my hands dirty (an idiom a native speaker might use)
2. Take charge.
|
|
|
|
|
#1 is something we say literally translated in spanish.
#2 is not exactly what I want to mean. Because I can't take charge of many things since it is a big company.
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
So relaxen und watchen das Blinkenlichten!
|
|
|
|
|
Almost...
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
Nelek wrote: something else
(for me to) take complete ownership.
|
|
|
|
|
Not exactly what I mean.
In own actions yeah. The context (I didn't explained it correctly before) is corporate. There is a network created by one of the chairmans about culture@work and professional change of mind.
I am part of it and I do what I can as a speaker, moderator of groups helping other departments to improve processes, showing there are other ways of doing things and things like that...
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
Then, the best word I feel is "Suggestion", as in
"I would like to suggest these enhancements in our ways of working (aimed at addressing these pain points). Let's try these for a couple of weeks/months, and evaluate after that period".
|
|
|
|
|
YAA (yet another attempt) :
Because I didn't like how things are being done and, for me, the best way to improve something is, to roll up one's sleeves and take action ...
|
|
|
|
|
If you want something done right, do it yourself...
Jeremy Falcon
|
|
|
|
|
Exactly. The short form.
I might add, "one man's meat is another man's poison" just to complicate things.
"A little time, a little trouble, your better day"
Badfinger
|
|
|
|
|