5 ms·
This write-up is too light to provide any real insight. In particular, how do you assess simplicity? From an example I'm currently working through on a hobby p
by addaon 4y ago
This write-up is too light to provide any real insight. In particular, how do you assess simplicity?
From an example I'm currently working through on a hobby project... do I use a RS-485 transceiver with a custom line code, or do I use a 10base-T1 PHY? Ethernet, especially one pair ethernet, is undoubtedly more /complex/, with echo cancellation, a complicated line code, etc; but if I use the PHY, then /I own/ that complexity.
(For pure software folks, the equivalent question is internal implementation vs external dependencies. Do you implement a 1D barcode yourself, or do you import a third-party dependency for QR code reading?)
The problem is that answering this depends not on some objective notion of simplicity, but on a realistic assessment of /where time will go/ during the development process. If development time dominates, then exporting complexity is a win. But if testing time dominates, and since exported complexity still needs to be fully understood during testing, then in-house simplicity wins.
And which of these cases dominates is very much a project-by-project and team-by-team decision.
- hattmall 4y agoDoes simplicity equal time? In my mind it doesn't. As for your example I'm a software person and bringing external dependencies feels like adding layers of complexity. Simplicity is minimalist, if I need an external dependency I generally try to extract the actual part I need and understand it and have it my own code to streamline what I need. From my view external dependencies are the epitome of complexity.
- deleted 4y ago[deleted]
- csdvrx 4y agoFor me, the simplest thing would be using a serial interface instead!
- addaon 4y agoRS-485 is a serial interface, at the physical layer. 8N1 as a line code introduces all sorts of other issues, assuming you're passing messages instead of byte streams over it. In particular, how do you do packetization? How do you synchronize? So many "serial interfaces" have implicit timers (corresponding to interpacket gap for ethernet) used for sync'ing, or play horrible games with embedded CRCs… there's a huge amount of hidden complexity here, especially if you do it implicitly without understanding the dependencies. By the time you've solved reliable packetization over 8N1, you're going to have something that looks a lot more like an Ethernet-level-complexity line code.
- icedchai 4y agoWhy reinvent the wheel? Just look at some older protocol, like SLIP.
- addaon 4y agoSLIP uses byte stuffing to reserve its end-of-frame sequence, which leads to data-dependent packet transmission times, which is not acceptable in my application.
- madars 4y agoIs this a big deal? Say, if character 0 is reserved you can encode everything in base255 and transmit encoded bytes shifted by 1. (Or, for simpler encoding, transfer an appropriately encoded bitmask of which characters are 0, then a copy of that data where 0 is replaced by anything else.) Edit: this HN comment by KMag suggests a much simpler encoding https://news.ycombinator.com/item?id=12550584 https://news.ycombinator.com/item?id=12550584 (you'd need to process your packets in 254 byte chunks) > replace first null with 255. Every later null, replace with the index of the previous null. Make the final byte the index of the last null (or 255 if no nulls were replaced). In this way, you've replaced the nulls with a linked list of the locations where nulls used to be. To invert the transformation, just start at the final byte and walk the linked list backward until you hit a 255. Looks like this is https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing?useskin=monobook https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuff...
- addaon 4y agoYeah, COBS works. In my case, I can even go simpler, since messages are fixed size. But: 1) This is now part of the line code. And "uart + slip but modified" starts losing some of the "simplest thing" charm of "just do what everyone else does." 2) Looking at this without reference to previous work, it sure seems unlikely to be the simplest thing. Magic numbers everywhere -- 8N1 uses 8 bit bytes to support ~5% clock skew, which isn't reflective of the application; COBS forces sub-packets at 255-ish byte intervals, which doesn't match any inherent concept, etc. It can work, but does it make sense in isolation?
- hinkley 4y agoObligatory Simple Made Easy link: https://www.youtube.com/watch?v=SxdOUGdseq4 https://www.youtube.com/watch?v=SxdOUGdseq4 Simple is a matter of intuition, and that can't be transmitted to others easily, or with a single class or book. At one particular job we got punished by the business for calling things 'easy' when what we mean is that we understand the problem and all of the steps are (mostly) known. Our boss coached the hell out of us to say 'straightforward' when we meant 'understood', instead of using 'easy' as an antonym for 'quagmire' or 'scary'.
- addaon 4y agoAgreed. But I also think that "simple to implement," "simple to debug," and "simple to test" are different metrics -- and that one has to choose which one to optimize for. This is independent from assessment of "simple" varying with intuition -- "simple" alone isn't a coherent concept.
- shagie 4y agoThat's part of the section in Programming Perl that sticks in my memory. From my copy... > Efficiency > ... > Note that optimizing for time may sometimes cost you in space or programmer efficiency (indicated by conflicting hints below). Them’s the breaks. If program- ming was easy, they wouldn’t need something as complicated as a human being to do it, now would they? > ... > Programmer Efficiency > The half-perfect program that you can run today is better than the fully perfect and pure program that you can run next month. Deal with some temporary ug- liness.1 Some of these are the antithesis of our advice so far. • Use defaults. • Use funky shortcut command-line switches like –a, –n, –p, –s, and –i. • Use for to mean foreach. • Run system commands with backticks. ... • Use whatever you think of first. • Get someone else to do the work for you by programming half an implementation and putting it on Github. > Maintainer Efficiency > Code that you (or your friends) are going to use and work on for a long time into the future deserves more attention. Substitute some short-term gains for much better long-term benefits. • Don’t use defaults. • Use foreach to mean foreach. ...
- 4y ago
- majkinetor 4y agoSimple is something that either can't be reduced further without changing the output (ideal, simplest), or it is very hard to do so (real world).
- addaon 4y agoBut this ignores, as in my example, who pays for the complexity. I want a bagel. Is it simplest for me to start tilling the land and looking for wild wheat relatives to breed, or to drive my incredibly complex car built in centuries of industrialization to the corner store and buy (using money, one of the most complex concepts we've developed!) a bagel, bring it home in a plastic (!!!) bag, and stick it in the toaster? If I should, during my lifetime, succeed in completing a bagel with the former, I have reasonable confidence it can't be reduced further without changing the output. But I disagree that it's the simplest way /for me/ to get breakfast.
- Zetice 4y agoI don't think the person you're replying to would consider "till the land" as fitting what they're describing as "simple".
- addaon 4y agoIt's a requirement for making a bagel… the question is whether I do it, or someone else. Part of the irreducible complexity of bagelness is the production process of wheat.
- majkinetor 4y agoYou are not producing a bagel. You are obtaining it. There is a big difference. Once nobody produces a bagel, your method is meaningless.
- Zetice 4y agoI'm not sure how you arrived at "every single step involved must be considered" from "can't be reduced further". If a step available to you is "buy a bagel", that's all you have to consider.
- xiphias2 4y agoActually Rick Hickey's talk (https://www.youtube.com/watch?v=LKtk3HCgTa8 https://www.youtube.com/watch?v=LKtk3HCgTa8) is amazing because he talks about your case by going back to the original meaining of words: ,,Complex comes from the Latin complecti, which means “to entwine around, to embrace'' Simplicity requires layering, so in your examples the main requirement for simplicity is about how intertwined your hobby project is with the transciever code or ethernet code. As long as the abstraction layer works well for you without getting too much into the details of the implementation, it's a simple solution. Of course it's not a clear answer whether you should do things yourself or use a third-party, but if the third-party works perfectly for use case without significant tradeoff in your system, of course it's better to use it.
- addaon 4y ago> As long as the abstraction layer works well for you without getting too much into the details of the implementation, it's a simple solution. But this is where the engineering intuition has to come in. "As long as you will not end up spending more time debugging the system than implementing it" is an equivalent statement -- and that requires prediction of the future. If I'm going to spend hours staring at signals on a 'scope to debug the system, I'd way rather they be RS-485 than 10base-T1, for reasons of simplicity -- but I don't know, today, if I will or not. Layering works /great/ during implementation. Layering is a strong impediment to understanding during testing and debugging. Debugging a system efficiently requires being able to bridge between layers of the system and see where your assumptions break down. And once you're going between those layers, you're exposed to the complexity within them. So: simplicity in implementation, or simplicity in debugging?
- xiphias2 4y agoFrom my experience most of the complexity doesn't come from adding stuff (where intuition is the only thing you have, and this rule doesn't help), but when removing/refactoring stuff, or the lack of doing it. A recent known example is Elon Musk removing a lot of services in Twitter that were built over the years. Every addition probably improved the system's functionality, but the more complex a codebase gets, the harder it is to change separate pieces (by definition of complex). I believe it was a big business mistake of him buying Twitter (especially as Tesla is getting competitors, like BYD growing by 100% a year), but removing services in itself probably makes the code more manageble by a smaller team.
- moremetadata 4y ago> the equivalent question is internal implementation vs external dependencies. Liabilities. Take the Windows EULA, its a contract that states MS is not liable for anything, standard software contracts state the same, so if boils down to being able to prove negligence, which can be sued for. For example, do you trust the suppliers? IF they are in a different country, what's the chance of legal recourse if negligence can be proved, knowing about political interference if the entity is valuable enough? So yes I agree, how do you assess simplicity, and as Billy Gates would say... it 's complicated!
- dfxm12 4y agoThe problem is that answering this depends not on some objective notion of simplicity, but on a realistic assessment of /where time will go/ during the development process. I don't think anyone mentions time as a proxy for simplicity. At least, the article certainly doesn't. You're right that the author doesn't objectively define simplicity, but I don't think anyone can. What is simple tends to be different to different people/teams, based on skills, tools, etc., available. I know what's simple to me. I know it may not be simple to you. I know what's simple for a team in my org and I know it may not be simple for another team in another org. But, I do know what skills someone in my position and in my org is expected to have, and I know what tools are available to us, so I can make some real assertions here about what is "simple". Get worried beyond that, and you get bogged down on unknown unknowns.
- BurningFrog 4y agoSounds like you have an answer to your question, so I don't see the problem. Yeah, it'll be a project-by-project and team-by-team decision, and that's as it should be.
- kokanee 4y agoI agree, the article is entirely focused on semantics. In the real world, outside of research and education, no one ever attempts to make something more complicated than it needs to be. A software project consists of thousands of different problems with solutions that must be mutually compatible through a web of compromises. You have known hard requirements, known soft requirements, known future requirements, unknown future requirements, and you're searching for the simplest possible solutions for each of them that result in something like a "minimum net complexity." The problem of "over-engineering" comes when a solution that optimized the simplicity for one concern becomes incompatible with another concern. It's inevitable in any system where requirements are subject to change over time.
- EGreg 4y agoIt’s too light to generate real insight because he took his own advice lol
- OJFord 4y agoI like to distinguish complexity from complication: the former requires cleverness to understand more of; the latter time and effort. In the simple case of a solo project, as much complexity as you understand is fine; in a team you obviously need some idea of a threshold, not that you could quantitatively define it. Complexity isn't necessary, though isn't a problem - complication on the other hand is always bad, it's just making things hard to reason about, but may be necessary if the only alternative is adding unacceptable complexity. The problem with discussing 'simplicity' is that it's an antonym for both complexity and complicatedness.
- hyperthesis 4y agoComparative simplicity requires you to accurately imagine the entire lifecycle of each alternative. This is a lot of work. And your prediction can end up wrong anyway (by your mistake or by the world changing). How are we then to make choices? Perhaps just, if one solution seems clearly simpler (to you), then choose that. If one looks unnecessarily complex, don't choose that. Simpl-est derails us perfectionist programmers. So maybe "Do the simpler thing that can possibly work" "You don't need to know a man's weight to know that he's fat" - Benjamin Graham. EDIT "Could possibly work" also implies a lack of foreknowledge as to its actual simplicity, or whether it will function correctly... or at all.
- GoblinSlayer 4y agoThat said, can't barcode be replaced with something easy to generate and read like braille?