[HN Gopher] A Formal Theory of Spaghetti Code
___________________________________________________________________
A Formal Theory of Spaghetti Code
Author : nickdrozd
Score : 46 points
Date : 2022-03-12 16:56 UTC (6 hours ago)
(HTM) web link (nickdrozd.github.io)
(TXT) w3m dump (nickdrozd.github.io)
| pmichaud wrote:
| It's a fun crack at the problem. I'll say (very annoyingly) that
| I have a hunch that the formalization is fundamentally wrong
| somehow that I can't quite put my finger on, even though branch
| factor does seem like a really great candidate for the relevant
| measure.
| parksy wrote:
| One of the first principles I learned in programming was
| coupling and cohesion. This type of graph-based measurement of
| program complexity already existed some 60 years ago.
|
| I think your hunch is on point, I think because the author
| conflates running time of a busy beaver with benchmarks of
| programmatic coupling and cohesion.
|
| Busy beaver algorithms are single-purpose programs. An
| eCommerce website is layers upon layers of interrelated modules
| and functions.
|
| I get where they're going, reducing a problem space down to its
| simplest representation is ideal. I just don't on first pass
| understand how busy beaver accomplishes this.
| everyone wrote:
| [Discussing article title, not article]
|
| I have thought about spaghetti code.. spaghetti is..
|
| * Messy. * Disorganized. * Every part of it is connected to every
| other part.
|
| The third one is the actually really bad one. U tug on one thing
| and it affects another thing and so on.
|
| I call my code rice code, its like spaghetti code but its made of
| _tiny_ little modules and no part is connected to another. It
| also (like spaghetti) has no order / design patterns n stuff.
| Imo committing to a design pattern is kind of a mini-failure cus
| your project is now less flexible, you've committed to a certain
| pattern and everything in future has to follow it. Maybe the next
| feature does not fit well into this pattern. Ideally you can get
| to end of project without ever committing to one. (But sometimes
| u give in and use one to overcome a difficult problem)
| [deleted]
| bsedlm wrote:
| seems the author should be aware of the Big Ball Of Mud
| http://laputan.org/mud/
| neilk wrote:
| Theory-curious but mostly workaday programmer here. Does this
| have any application to detecting spaghetti code in conventional
| codebases, or is it specific to the Busy Beaver problem?
|
| "Cyclomatic complexity" is as old as the hills, but attempts to
| count the paths through the code from a begin state to and end
| state. According to Wikipedia it's similar to "circuit rank"
| which is the minimum number of edges to remove in order to break
| cycles. That smells like it's related to this graph reduction
| thing but I lack intuition into this problem.
| hackerfromthefu wrote:
| Low Cyclomatic Complexity is absolutely the result of careful
| management of interfaces in the system. The inverse is also
| true that high CC is a sign of poorly structure code, which
| tends towards spaghetti. Thus I agree it's related to the
| premise of detecting spaghetti code.
|
| There's nice CC visualizers that can show you at a glance areas
| that have higher complexity. Sometimes that complexity is
| related to the problem domain, but sometimes it comes from
| overhead of poor system architecture.
| ravi-delia wrote:
| I highly doubt it does, it's largely a fun puzzle with
| potential ramifications for limits of computability.
| atq2119 wrote:
| People are perfectly capable of writing spaghetti code in
| structured programming languages (without goto) and such
| programs are always reducible in the sense of this article.
|
| Actually, I have a hunch that every program that is reducible
| in the standard compiler sense is also reducible in the sense
| of the article, but the converse does not hold. 1 -> 2 -> 3 ->
| 4, 1 -> 3 -> 2 is irreducible in the compiler sense (there is a
| loop with two entries) but reducible in the sense of the
| article (first merge 2 and 3, then delete self loop, an acyclic
| graph remains which is trivially reducible).
| marcodiego wrote:
| Besides Spaghetti Code there is a development practice which is
| relatively common and yet people usually fall for it. I like to
| call it: flag oriented programming.
|
| People usually think it is a good idea to use flags. They create
| a flag to store states of entities and think the problem is
| solved. Actually it sometimes duplicates the number of possible
| new problems.
|
| I once tried to convince a friend not to use it. In a part of the
| code, I asked him: "Look, how can you guarantee that the states
| of the flags are consistent here?", he then added code just
| before the line to check for consistency of the flags. I then
| said that if the flags fell into an inconsistent state, then it
| should be fixed there, not when they are checked. He tried
| another fix: created "set methods" for each of the flags, each
| method called a function "checkFlags" which detected
| inconsistencies in the flags and automatically set them to a
| consistent state.
|
| I continued: "Look, every time you add a new flag you will have
| to check this function and infer, among possible combinations,
| which are valid and which are not. If you need states, use an
| enumeration with few states all of which are consistent."
|
| That is the problem with flag-oriented programming: each new
| flags doubles the number of possible states and it is very
| complicated to guarantee consistency between them considering all
| possible combinations and temptation to just add, set and check a
| new flag when writing code.
| bitwize wrote:
| Ah, I see you've met YandereDev.
| echelon wrote:
| I can relate to this. Flags are great, but you need to exercise
| discipline to not wind up with dangerous spaghetti.
|
| This problem is amplified further because flags can come in so
| many different shapes and sizes:
|
| - Rollout: binary on/off, percentage rollout, beta group
| rollout, single user rollout, etc.
|
| - Control plane: eg. emergency shut off valve for the caching
| layer, switch that controls routing, etc.
|
| - Multi-valued or numeric: ie. not just true/false, typically
| combined with A/B testing
|
| Conflating these can lead to extremely messy code. Each of
| these cases deserves its own special type of treatment.
|
| Rollout flags should have a self-destruct or mechanism that
| _strongly encourages_ engineers to remove them as soon as they
| 're no longer used.
|
| Control plane stuff shouldn't really be mixed with feature
| flagging at all. It would be dangerous to remove them, and
| regularly vetting the states should be a necessary requirement
| for any type of disaster recovery assurance testing.
|
| I really appreciate your call to represent these states as an
| enumeration. Capturing the flag states at the start of a
| request and then determining the proper bucket helps to make
| the problem more concrete. Engineers can then better reason
| about the explosion of states and the impact to control flow.
|
| Ultimately, I think flagging is one of those "hard problems"
| that comes with the job territory. You don't want to throw the
| technique out entirely along with the bath water, because it
| has plenty of justifiable benefits. There are best practices
| and proper hygienic steps we can take to make the use of flags
| easier on ourselves.
| sjf wrote:
| I think the OP is referring to the kind of thing you might
| find in frontend code, like maintaining state for things like
| isVisible, isExpanded, isSelected.
| wa1987 wrote:
| State charts / FSM's work wonders in these situations.
| jonhohle wrote:
| I often pushed for immutable objects specifically for this
| reason. At construction time you guarantee the state of the
| object once, otherwise, as you said, complexity doubles with
| each mutable property.
| joostdevries wrote:
| The need for flags in itself may be a sign of the wrong
| approach. You create a shared module. But for some cases the
| handling should be different. Let's pass in a flag or
| configuration. So somewhere in the shared component it will
| handle things differently. Oh wait, there's another case.
| Another flag. Which combinations of flags are meaningful and
| which aren't? The nearest improvement is to put all the cases
| in an enumeration. But wait it's not one 'dimension'. Let's
| have two enumerations. And the extreme end point is that your
| shared module has a full blown DSL for the parameters it
| receives. Or even an interpreter. The other solution that is
| often more understandable and debuggable in the long run is to
| not have the shared module call specific code for cases. But to
| have specific code pull in shared commonalities. No need for
| flags.
| LightHugger wrote:
| To boil it down:
|
| Flags work brilliantly when the states are independent and
| there is no such thing as an inconsistent state... the moment
| you have strange interdependence you lose all the benefits.
| gumby wrote:
| This is perfectly encapsulated by my favorite joke.
|
| A physicist is showing their friend the computer scientist a
| thermos.
|
| "This thing is so cool: you can pour something hot into it, and
| no matter how cold it is outside it stays hot". The friend is
| duly impressed.
|
| "But that isn't all: you can pour something _cold_ into it, and
| no matter how hot it is outside it stays cold "!
|
| Now the computer scientist is puzzled. "But how does it know?"
|
| Code like this is the bane of my existance.
| WinterMount223 wrote:
| I'm sorry I don't get it.
| kens wrote:
| You might want to glance at the article, which is about Turing
| machine busy beaver programs and has nothing to do with
| spaghetti code as a development practice.
| fshbbdssbbgdd wrote:
| What hacker news needs is a separate "discuss title" page.
| elijaht wrote:
| Giving you a heads up- I think you may have accidentally
| commented in the wrong thread. This isn't related to the main
| article
| pkrumins wrote:
| Theorem: Any spaghetti code that's pushed to production and
| solves a customer's problem is no longer spaghetti code.
| #deployordie
___________________________________________________________________
(page generated 2022-03-12 23:00 UTC)