(no title)
exclipy | 6 months ago
Basically, you should aim to minimise complexity in software design, but importantly, complexity is defined as "how difficult is it to make changes to it". "How difficult" is largely determined by the amount of cognitive load necessary to understand it.
YZF|6 months ago
You can't win architecture arguments.
I like the article but the people who need it won't understand it and the people who don't need it already know this. As we say, it's not a technical problem, it's always a people and culture problem. Architecture just follows people and culture. If you have Rob Pike and Google you'll get Go. You can't read some book and make Go. (whether you like it or not is a different question).
safety1st|6 months ago
* Our coding standards require that functions have a fairly low cyclomatic complexity. The goal is to ensure that we never have a a function which is really hard to understand.
* We also require a properly descriptive header comment for each function and one of the main emphases in our code reviews is to evaluate the legibility and sensibility of each function signature very carefully. My thinking is the comment sort of describes "developer's intent" whereas the naming of everything in the signature should give you a strong indication of what the function really does.
Now is this going to buy you good architecture for free, of course not.
But what it does seem to do is keep the cognitive load manageable, pretty much all of the time these rules are followed. Understanding a particular bit of the codebase means reading one simple function, and perhaps 1-2 that are related to it.
Granted we are building websites and web applications which are at most medium fancy, not solving NASA problems, but I can say from working with certain parts of the codebase before and after these standards, it's like night and day.
One "sin" this set of rules encourages is that when the logic is unavoidably complex, people are forced to write a function which calls several other functions that are not used anywhere else; it's basically do_thing_a(); do_thing_b(); do_thing_c();. I actually find this to be great because it's easy to notice and tells us what parts of the code are sufficiently complex or awkward as to merit more careful review. Plus, I don't really care that people will say "that's not the right purpose for functions," the reality is that with proper signatures it reads like an easy "cliffs notes" in fairly plain English of exactly what's about to happen, making the code even easier to understand.
bogdanoff_2|6 months ago
That's not true. There's plenty of beginner programmers who will benefit from this.
braebo|6 months ago
ruraljuror|6 months ago
zakirullin|6 months ago
That's true. One doesn't change his mindset just after reading. Even after some mentorship the results are far from satisfying. Engineers can completely agree with you on the topic, only to go and do just the opposite.
It seems like the hardest thing to do is to build a feedback loop - "what decisions I made in past -> what it led to". Usually that loop takes a few years to complete, and most people forget that their architecture decisions led to a disaster. Or they just disassociate themselves.
bb88|6 months ago
Unless it's a rule prohibiting complexity by removing technologies. Here's a set of rules I have in my head.
1. No multithreading. (See Mozilla's "You must be this high" sign)
2. No visitor pattern. (See grug oriented development)
3. No observer pattern. (See django when signals need to run in a particular order)
4. No custom DSL's. (I need to add a new operator, damnit, and I can't parse your badly written LALR(1) schema).
5. No XML. (Fight me, I have battle scars.)
mnsc|6 months ago
I feel this in my soul. But I'm starting to understand this and accept it. Acceptance seem to lessen my frustration on discussing with architects that seemingly always take the opposite stance to me. There is no right or wrong, just always different trade offs depending on what rule or constraint you are prioritizing in your mind.
lokar|6 months ago
heresie-dabord|6 months ago
This is true. However, very few people can clearly explain all the rules.
If they can, they have understood the system and are qualified.
bsenftner|6 months ago
zahlman|6 months ago
martinpw|6 months ago
I think it's a pretty good compromise. I have tried in the past not to duplicate code at all, and it often ends up more pain than gain. Allow copy/paste if code is needed in two different places, but refactor if needed in three or more, is a pretty good rule of thumb.
cyberax|6 months ago
Example: you have a config defined as Java/Go classes/structures. You want to check that the config file has the correct syntax. Non-DRY strategy is to describe its structure in an XSD schema (ok, ok JSON schema) and then validate the config. So you end up with two sources of truth: the schema and Java/Go classes, they can drift apart and cause problems.
The DRY way is to generate the classes/structures that define the config from that schema.
hinkley|6 months ago
When you’re dealing with perennial plants, there’s only so much control you actually have, and there’s a list of things you know you have to do with them but you cannot do them all at once. There is what you need to do now, what you need to do next year, and a theory of what you’ll do over the next five years. And two years into any five year plan, the five year plan has completely changed. You’re hedging your bets.
Traditional Formal English and French gardens try to “master” the plants. Force them to behave to an exacting standard. It’s only possible with both a high degree of skill and a vast pool of labor. They aren’t really about nature, or food. They’re displays of opulence. They are conspicuous consumption. They are keeping up with the Joneses. Some people love that about them. More practical people see it as pretentious bullshit.
I think we all know a few companies that make a bad idea work by sheer force of will and overwhelming resources.
tialaramex|6 months ago
Deliberately going earlier makes sense if experience teaches you there will be 3+ of this eventually, but the point where I'm going to pick "Decline" and write that you need to fix this first is when I see you've repeated something 4-5 times, that's too many, we have machines to do repetition for us, have the machine do it.
An EnableEditor function? OK, meaningful name. EnablePublisher? Hmm, yes I understand the name scheme but I get a bad feeling. EnableCoAuthor? Approved with a stern note to reconsider, are we really never adding more of these, is there really some reason you can't factor this out? EnableAuditor. No. Stop, this function is named Enable and it takes a Role, do not copy-paste and change the names.
hinkley|6 months ago
I even tried calling the bookstore on his campus and they said try back at the beginning of a semester, they didn’t have any copies.
My local book store could not source me a copy, and neither IIRC could Powell’s.
tialaramex|6 months ago
ashurov|6 months ago
zakirullin|6 months ago
exclipy|6 months ago
swat535|6 months ago
Ultimately, context, industries and teams vary so greatly that it doesn't make sense to quantify it.
What I've settled on instead is aiming for a balance between "mess" and "beauty" in my design. The hardest thing for me personally to grasp was that businesses are indeterministic whereas software is not, thus requirements always shifts and fitting this into the rigidity of computer systems is _difficult_.
These days, I only attempt to refactor when I start to feel the pain when I'm about to change the code.. and even then, I perform the bare minimum to clean up the code. Eventually multiple refactoring shapes a new pattern which can be pulled into an abstraction.
epolanski|6 months ago
Also, people confuse familiar with simple, they tend to find things simple if they are familiar, even if they are complex (interwine a lot of different things).
ferguess_k|6 months ago
But I'm not experienced enough to tell, whether it is my inexperience that causes the difficulty, or it is indeed that the unnecessary complexity tha causes it.
lll-o-lll|6 months ago
Watch ‘Simple made Easy’ by Rich Hickey; a classic from our industry. The battle against complexity is ever ongoing. https://youtu.be/SxdOUGdseq4?feature=shared
brabel|6 months ago
With that said , get good at jumping into definitions, finding all implementations, then jumping back where you were. With a good IDE you can do that at the speed of thought (in IntelliJ that’s Cmb+b, Cmd+Alt+b, Cmd+[ on Mac). I only open more than one file at the same time when comparing them. Otherwise it’s much easier to jump around back and forth (you can even open another function inline if you just want to take a Quick Look, it’s Alt+Space). Don’t use the mouse to do that, things you do all the time can be made an order of magnitude faster via shortcuts. Too many developers I see struggle with that and are embarrassingly slow moving around the code base!
seadan83|6 months ago
tverbeure|6 months ago
RossBencina|6 months ago
I remember using TCL in the 90s for my own projects as an embeddable command language. The main selling point was that it was a relatively widely understood scripting language with an easily embeddable off-the-shelf open source code base, perhaps one of the first of its kind (ignoring lisps.) Of course the limitations soon became clear. Only a few years later I had high hopes that Python would become a successor, but it went in a different direction and became significantly more difficult to embed in other applications than was TCL -- it just wasn't a primary use case for the core Python project. The modern TCL-equivalent is Lua, definitely a step up from TCL, but I think if EDA tools used Lua there would be plenty of hand-wringing too.
Just guessing, but I imagine that at the time TCL was adopted within EDA tools there were few alternatives. And once TCL was established it was going to be very hard to replace. Even if you ignore inertia at the EDA vendors, I can't imagine hardware engineers (or anyone with a job to do) wanting to switch languages every two to five years like some developers seem happy to do. It's a hard sell all around.
I reckon the best you can do is blame the vendors for (a) not choosing a more fit-for purpose language at the outset, which probably means Scheme, or inventing their own, (b) or not ripping the bandaid off at some point and switching to a more fit-for-purpose language. Blaming (b) is tough though, even today selecting an embedded application language is vexed: you want something that has good affordances as a language, is widely used and documented, easily embedded, and long-term stable. Almost everything I can think of fails the long term stability test (Python, JavaScript, even Lua which does not maintain backward compatibility between releases).
Shorn|6 months ago
onlinehost|6 months ago
leke|6 months ago
wtbdbrrr|6 months ago
[deleted]