[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)