12 ms·
Zero one infinity rule
- antiquark 4y agoRIP the byte.
- layer8 4y agoIt’s just one octet.
- Kim_Bruning 4y agoAm I the only person who sometimes makes an exception for "two" ?
- jerf 4y agoNo. But I have the decency to feel bad and leave an apologetic comment.
- adhesive_wombat 4y agoA ping-pong buffer certainly seems like generalising to a ping-pong-pang-peng-pung-p(infinity)ng buffer would be overkill.
- hprotagonist 4y agoi fairly regularly want pairwise, yep.
- grensley 4y agoTwo is quite relevant for relationships
- ChickeNES 4y agoWell, if you ignore polyamory and polygamy...
- layer8 4y agoYou can have n-ary relationships. Relational databases are built on that.
- grensley 4y agoWhat are the columns in a relational table like that?
- layer8 4y agoNot sure what you mean. A table with N columns corresponds to an N-ary relation. The rows contained in the table are the tuples contained in the relation. Table = relation. That's why it's called a relational database. See also this example in Wikipedia of a ternary relation: https://en.wikipedia.org/wiki/Finitary_relation#Example https://en.wikipedia.org/wiki/Finitary_relation#Example Another example: If you have a table (SSN, Name, DateOfBirth), then that corresponds to the relation "person with SSN x has name y and date of birth z". In that case it's a relation between SSNs, names, and dates.
- grensley 4y agoVery fair, thanks for the example.
- ChainOfFools 4y agoI seem to recall that there are certain languages (human languages) that have cases specifically for talking about pairs of objects, situated semantically between singular and plural. I think one of these is an archaic form of Greek, maybe ancient or Hellenistic.
- tough 4y agoAsked ChatGPT Yes, you are correct! Ancient Greek has a dual number, which is used specifically for referring to two people or two objects. The dual is a distinct grammatical number, separate from singular and plural. In the ancient Greek language, nouns, pronouns, adjectives, and verbs all have different forms for singular, dual, and plural numbers. The dual number is used when referring to two things or two people, while the singular number is used for one thing or one person, and the plural number is used for three or more things or people. The dual number is no longer used in modern Greek, but it was an important feature of the ancient Greek language, which had a rich and complex system of inflectional morphology. Other languages that have a dual number include Old English, Old Norse, Lithuanian, and Slovenian, among others.
- guavaNinja 4y agoIn Arabic there is the mothanna مثنى (pair) case.
- playingalong 4y agoIt has always "bothered" me that AWS allowed for up to two API keys per IAM user.
- jdreaver 4y agoThat's probably so you can rotate your keys without downtime.
- alex_sf 4y agoThe argument against two would be: if you can do two, why can you not do three?
- GauntletWizard 4y agoWherever I need "Two" I usually find that what I actually need is a one and a many; there's not a master and a replica, there's one master and many replicas. There's not two places that the data is when doing a raid restripe, there's many places the data probably is and one place it should be.
- mmphosis 4y agoHow about a sign bit? https://en.wikipedia.org/wiki/Unum_(number_format) https://en.wikipedia.org/wiki/Unum_(number_format)
- teo_zero 4y agoI'd say that 2 is indeed quite common in Computer science. In graphs, for example, each edge has 2 ends. In an abstract syntax tree, a binary operator has 2 children. All raster images are based on 2 dimensions. A "for each" loop often involves 2 variables: the iterator object and an index. In all such cases it makes sense that a language/ construct/library special-cases 2 elements without generalizing for an arbitrary number of elements. By the way, 3 is much less common, except in some specific domains, like 3D vectors, UNIX permissions (user, group, other), etc.
- Kim_Bruning 4y agoOh, you're right, there are a few other exceptions for other numbers too!
- xigoi 4y agoUsually you wouldn't store these things in a collection, but as separate fields of a record type, so the rule doesn't apply.
- teo_zero 4y agoThe principle applies to all kinds of structures. For example a common way to implement a generic tree that respects this rule is to model each node with exactly one parent and any number of children. My statement instead is that you may have legitimate reasons to want exactly one parent and from zero to two children, but not more.
- hsjqllzlfkf 4y agoJohn Carmack argued the opposite. He said he would hardcore limits into his data structures. Limits that would never be hit under normal operating circumstances. He argued that when you design software you should have an idea under what circumstances it will run and optimize for those. The fact that people normally don't do this, is why software often lags - that algo you implemented worked worked just fine when it's hashmap has 1000 keys, but not when it has 1m keys. I haven't articulated his point very well, but I lost interest in this comment mid way thru.
- TazeTSchnitzel 4y agoYou can see this kind of design in action in the Source engine, perhaps inherited from Quake (which is partly Carmack's work of course). There are hard limits on things like how many objects can exist at once. Occasionally those get hit… usually due to a memory leak![0] So the artificial limit helps find real problems. That's also been my experience with PHP, which limits the amount of memory a request or script execution can consume by default. [0] https://www.youtube.com/watch?v=pw2X1yhrDdE https://www.youtube.com/watch?v=pw2X1yhrDdE — check out shounic's other videos too, there's lots of interesting content there about how complex game systems fail, including about these limits
- quelsolaar 4y agoIve come to agree with this. Say you have a struct that contains a name. If you limit the name size to say 64 bytes, then you can store it in the struct, otherwise you need to have a separate allocation and an indirection. This makes the code slower, more error prone and more complex to use. So think hard of when “infinite” is justified.
- AlotOfReading 4y agoYou should also be careful about incorrectly imposing limits on human input, as every "falsehoods programmers should know about x" repeatedly hits on. To continue the name example, there are people with legal names and titles that take far more than 64 bytes to store and truncation is not an appropriate solution. You should store the entire thing, even if that's a small bit more difficult technically. The other limit also applies. Some people don't have any characters in their legal names at all, like my mother (birth certificate name was blank).
- GauntletWizard 4y agoI learned this rule through, of all things, the children's series Animorphs. One book they encounter a colony of ants, who mention that "You are one, we are many" and count that way; any finite number is one, and infinite numbers are many.
- zeroonetwothree 4y agoWhile this has some theoretical merit, IME, limits are quite useful to catch bugs (or prevent degenerate cases). For example I was recently working on a permissions system wherein there can be members of groups. I set a reasonable limit on the size of a group based on a maximum of actual usage and what I could foresee being reasonable. A few days later, this limit was triggered, and I got a bug report. But it turned out there was some bad caller that had essentially an infinite loop that was adding more and more members to the group. Without the limit this probably would only have detected after it cascaded and caused other failures. As another example, Facebook famously had (maybe still has? I have no idea) a limit of 5,000 friends. This was based on the idea that you were supposed to be friends with people you actually kind of know at least a little bit, which would probably fit within 5,000 for most people. After some more popular users started hitting the limit, it led to the development of public profiles/pages as an alternative product to handle that use case. So in this case the limit allowed the company to identify a new market that they could better serve in an alternative way. BTW, the George Gamow book that the name comes from (One, Two, Three… Infinity) is a great read for anyone interested in popular descriptions of physics or math. He also lived a very interesting life, I would recommend his autobiography "My World Line".
- crazygringo 4y agoTotally agreed. I think it's absolutely a best practice to set limits. Code is generally designed to operate within certain "reasonable" performance boundaries, and when it goes outside those you need to think whether code should be rewritten to accomodate it. Just a tiny example, but I regularly deal with long (800+ page) PDF's on my iPad, reading parts of them in the stock Books app. When I select text to highlight, the context menu unfortunately puts "select all" directly next to "highlight". Of course, every so often I accidentally hit "select all", and then I have to force-close the app because otherwise it just freezes for 10 minutes as it extracts and selects the text on every single page. When really, it needs a limit to detect that, hey, if the PDF is over 20 pages long then just don't allow "select all" anymore, because this isn't the right tool for the job.
- psychphysic 4y ago
- deergomoo 4y agoI think this is something programmers intuitively learn pretty quickly (in fact I'm only just learning that there is actually a name for this idea), but it's an interesting principle to explain to non-developers. Back when I was doing agency work, on more than one occasion I had clients question why modifying some entity to permit multiple related entities instead of one would be more work than they were anticipating. The question was usually along the lines of "would it help if we were to limit related $foobars to three?". But of course, from a structural perspective supporting three related records is usually exactly the same amount of work as supporting arbitrary amounts. Yeah I could probably hack in some fixed amount of extra records, but that's just going to create an increasingly large mess when your business grows and you realise three...twelve...one hundred wasn't enough. Might as well do it properly from the start.
- dragontamer 4y agoThis is probably a rule I believed in as a beginner, and completely don't believe in anymore today. Lets take a look at an exceptionally well designed system: single-error correction double-error detection codes. Also known as "ECC RAM". The implementation of this only works for *exactly* 64 bits + 8-parity bits. Now sure, we can talk about how we can generalize SECED ECC to different numbers of bits or whatever. But I'll also point out that the only implementation in widespread use is ECC Memory, the 64-bits + 8-parity bits (72-bits total) implementation.
- alex_sf 4y agoI would argue your example is a special case of only allowing one.
- dragontamer 4y agoBut it detects two-bit errors. Which is nonzero, non-one, and non-infinity. -------- SEC without DED is the classic implementation of Hamming error correction codes. The double error detection (aka DED) but is grafted on top of the theory, because it's useful in practice.
- Nullabillity 4y agoIt is generalized, you can chain together infinitely many blocks.
- crazygringo 4y agoI've read the article but I'm having trouble understanding the context of what this was in response to. The article quotes: > I formulated it in the early 70s, when I was working on programming language design and annoyed by all the arbitrary numbers that appeared in some of the languages of the day. Was it just an issue with languages in the 70's then? Because I'm struggling to think of any "arbitrary number" limits in modern languages. Obviously we have numerical limits depending on if a variable is a signed 32-bit integer or whatever. But those aren't arbitrary. Like would older languages just arbitrarily say there couldn't be more than 100 elements in an array, or something?
- gdprrrr 4y agoEarly C compilers had a limit of 6 characters for an identifier
- layer8 4y agoLots of examples (e.g. maximum number of nesting levels), see for example: http://www.tendra.org/tdfc2-config/chapter2 http://www.tendra.org/tdfc2-config/chapter2 https://www.ibm.com/docs/en/epfz/5.3?topic=reference-limits https://www.ibm.com/docs/en/epfz/5.3?topic=reference-limits One aim of finite implementation limits is to define which programs are guaranteed to compile successfully, so that you don’t run into the situation that a program compiles on one implementation but not on another implementation, which would raise the question of whether it’s the program or the compiler that is nonconforming. If both are conforming, you want the program to compile 100% of the time. This isn’t possible if programs can have unlimited complexity. The mindset is similar to embedded programming, where you have limited memory and absolutely don’t want to run into the situation that there’s not enough memory left to perform the operation that needs to be performed.
- kevin_thibedeau 4y agoIn the embedded world you're always mindful of memory consumption. Static allocation of a fixed size array has advantages over the same data in a linked list by simple virtue of eliminating node pointers and bookkeeping overhead associated with dynamic objects. Regardless of concerns about algorithmic complexity. Sometimes you really do need to set fixed limits for the sake of economy. Minicomputers of the 70s and PCs of the 80s had computing resources comparable to what passes for embedded systems today (i.e. much less capable that an RPi). Those machines required tradeoffs with arbitrary limits to make realizable software and that is still a valid approach for a subset of modern programming where you can't just pretend you have an infinite store that will never be exhausted and if you do hit a limit you can't just throw more hardware at the problem.
- travisjungroth 4y agoA metarule for using rules like this: instead of thinking of it as a rule, think of it as an option you should usually consider. You get lot of the benefits and less of the costs if you just ask questions like "Would it be easier to solve for N than 3? Easier to use and maintain?". The answer will never always be yes or no, but you'll be more likely to get the right answer if you ask the question.
- xlii 4y agoI have a feeling that a lot of commenters mix up structure design with structure implementation. Rule talks about the design (and I find approach interesting) yet implementation can (and most likely should) be limited. E.g. we are designing a world. In this design we say children can have toys. It doesn’t make sense to design universe so that children are limited to 5 toys or any other arbitrary number. But no room can fit infinite number of toys so implementation is limited. For some it’s 500 toys but for some it’s 500.000 toys. Names or parents are good real world examples. Sure, most people have 2 parents pr at most 2 names but this rule argues that if there’s more than one it shouldn’t be limited at all (which also makes sense in real life even though IT system might limit names to 256 characters because hardware).
- eternalban 4y agoThen change the name of the rule :) Zero, One, or Many. I think that would satisfy all concerned.
- xlii 4y agoAbsolutely agree. However that’s for the rule creator. I think that infinity in this context sounds slightly poetic.
- heyzk 4y agoWhich, I assume, led to one of my favorite idioms: there are only three numbers in computing: 0, 1, and n.
- neilv 4y agoI first heard of "no arbitrary limits" in connection with GNU software. It was one of ways that GNU software not only had different licensing than alternatives, but was also usually technically superior. (At the time, there were a lot of different workstation computer vendors, each with their own flavor of Unix. But where GNU tools existed, they'd usually be better than all of the Unix workstation ones. One exception was that the premium vendor C and C++ compilers generated better code and/or were more trusted than GCC at the time. GCC didn't take over until Linux, initially on x86.)
- kloch 4y agoOne example I recently ran into with large image files, specifically a 24GB PNG file, which of couerse requires much more working memory when uncompressed: Gimp: Opens this image successfully without complaining. It takes a while and uses lots of swap space but it works. OSX Preview App: "The file <filename> could not be opened. It may be damaged or use a file format that Preview doesn't recognize. So not only does Preview fail to open the file, it also lies about what the specific issue is. Apparently nobody at Apple ever imagined opening such a large file. The early Internet flourished in large part because the protocol designers correctly recognized that they couldn't predict or even imagine all the ways people would use their work. "Be conservative in what you send but liberal in what you accept - John Postel" https://en.wikipedia.org/wiki/Robustness_principle https://en.wikipedia.org/wiki/Robustness_principle
- at_a_remove 4y agoI've had a different take on this that goes "Zero, One, Many." And that when you end up really using your software, the things that were "one" often become "many," and the unthinkable zeroes frequently became ones.
- readthenotes1 4y agoZero one infinity (many) is a good rubric for test driving, and for thinking how close to infinity your system can/should actually support
- furyofantares 4y ago> It argues that arbitrary limits on the number of instances of a particular type of data or structure should not be allowed. Either this is a misuse of "arbitrary" or it's not really arguing for no limits beyond 1. In the Carmack example from another comment, if you know your solution isn't going to scale well beyond 1000 items, that's not an arbitrary limit, and it's not 0 or 1 either. When we choose not to allow users to back up their hard drive in the username field of their account, that's not an arbitrary limit.
- xigoi 4y agoIt is arbitrary. Why can it handle 1000 items, but not 1001 items?
- deleted 4y ago[deleted]
- chazu 4y agoI'm consistently shocked by the number of people who have never heard of this principle. Introducing arbitrary numerical limits (emphasis on _arbitrary_, as performance limitations or other actual requirements obviously trump this rule) is a design decision that I find myself having to clean up after frequently. I see a lot of people here questioning the wisdom of the rule, however, like every other principle used in SWE, it shouldn't be applied blindly. Ask yourself "why am I specifying that a maximum of five wangervanes can be specified in the turboencabulator settings?" _IF_ you have a good reason, fine. Most of the time you will not.
- zarzavat 4y agoLimits are good. Limits mean that you can test your software under both min and max conditions. If there’s no hard limit, then the limit exists merely in the developer’s mind as what they consider sensible or not. Inevitably there will be some user who takes your software past what the developer considered sensible. And unknowingly and silently, this user becomes a tester in production. The real problem is not DRYing your limits. There should always be one central point of truth, one constant that determines what the limit is.
- sethammons 4y agoI've been working on high scale systems for over a decade. An early lesson was to put limits on everything. Because we started without them, customers leveraged the lack of limits, and cardinality became a huge problem. Real example: at SendGrid, you can attach "categories" to emails which can help organize your email analytics by enabling you to group emails by type. Just as you can view the statistics on all your email activity, you can go a step further and view the statistics by a particular category. Our ability to provide analytics blew up when several customers exploded that to literally millions of categories, most totally unique to a single message. We no longer release anything as unlimited. If a use case arises, we can always expand the limit, but establishing a limit after the fact is hard and customers don't like having to go back to change integrations.
- paxys 4y agoPutting a user-facing restriction in place is very different from having your underlying infrastructure itself make that assumption. If the product spec says a user will be allowed 5 messages per day, and that's all you design the system to support, you will inevitably run into challenges when the number has to be changed to 20 or 2000 or 20 billion down the line. At that point "but we only used an 8-bit integer because you said the max would be..." isn't a good enough answer, and you are going to be stuck in a very messy rewrite.
- bee_rider 4y agoWas it hurting anything to have millions of categories? I mean, I’d assume the metrics interface they’d gotten from you would be essentially useless, but if they had some workflow they worked, why not let them have it?
- paxys 4y agoThis is especially relevant when designing systems that may need to scale unpredictably. We dealt with a lot of such growing pains at my company, and then made a rule that every dataset has to be theoretically infinite in size. So for cases like doing a database query, returning lists via an API call etc. you cannot make assumptions like the result set will be small enough to fit in the server's memory or fit on a single web page. Pagination, indexes, search/typeahead are all a must for any case where you expect > 1 result, even though for all practical uses that number may just be 5 or 10. Many years later we are still seeing massive dividends from this rule
- IIAOPSW 4y agoWow. Just + and - i away from completing the Riemann sphere.
- renewiltord 4y agoThis is easily misunderstood (e.g. many peer comments). It's a design structure heuristic. It isn't about the limit in there. It's about the style of algorithm or data structure. An obvious example is something like you want to support a primary data source and if something is missing there you want to fall back. Either you implement it is as no fallback, you implement it as one fallback, or you write your code to support arbitrary fallbacks. What you shouldn't do is specifically support two fallbacks. Another example is something like say you want to have badges on a user. You want to store this in the backend and then you want to display badges next to their comment. Suppose you decide you want to allow a maximum of 3 badges per user. Conforming to 0-1-infinity is about having a badge[]. Not conforming to it is having, on your User, a badge1, badge2, and badge3. The two rules of 0-1-infinity and always-have-a-limit are orthogonal.
- falcor84 4y agoApologies for the spoiler, but I just wanted to mention that this rule plays a pivotal role in Asimov's highly recommended "The Gods Themselves" https://en.wikipedia.org/wiki/The_Gods_Themselves https://en.wikipedia.org/wiki/The_Gods_Themselves
- 2-718-281-828 4y agoIt's my rule of thumb that the only numbers one should find in code are 0 and 1. Anything else is a magic number and needs to be handled accordingly.
- xigoi 4y agodef solve_quadratic_equation(a, b, c): d = b * b - 4 * a * c if d >= 0: return [(-b + sqrt(d)) / (2 * a), (-b - sqrt(d)) / (2 * a)] else: return [] How would you deal with the “magic numbers” here?
- 2-718-281-828 4y agogood question. but if you look at the "magic" concept from a higher level then you'll find that this function of course is based on magic numbers as it itself is a _magic function_. it doesn't solve generally equations but specifically _quadratic_ equations. a more extreme and obvious example in the same vain would be: def print_every_second_for_a_minute(): ... having said that - there are always exceptions.
- xigoi 4y agoHow would you define a “magic function”? Solving equations in general is not possible, so if you're trying to say that this function is too specific, good luck generalizing it.
- 2-718-281-828 4y agoI talk about magic numbers from an abstract, theoretical perspective. from that perspective it's not relevant that you can't generalize an equation solver. but would bet that if it was possible then there would be no numbers except for 0 and 1. --- you could also think of it this way. a generalized equation solver would necessarily derive the solution in a complete fashion. for someone analyzing the code it would be come clear what's going on. your specialized equation solver otoh just has some "magical" solution in there.
- nixpulvis 4y agoWeak wiki article.
- skissane 4y agoIf you took this rule literally though, you’d have to support bigints everywhere. Yet, in practice, setting the limit as INT64_MAX is seen as sufficient to count as “infinity”. In computing, “infinite” is almost never meant literally. When people say “infinite”, they really mean “finite but really really big”
- iudqnolq 4y agoInfinity here means "so big you don't have to think about reaching out". For example, the Rust standard library assumes no system could possibly support more usize::MAX/2 threads, but it worries about you cloning an atomically reference counted pointer usize::MAX times.
- xigoi 4y agoYou'll run out of memory long before your array can reach 2^64 items.
- skissane 4y agoWhich means in a practice “infinity” is a lot lower than 2^64, although exactly how much lower depends on system configuration (how much memory the system has, how much of it this process is permitted to consume)
- xigoi 4y agoThe point is that the limit should be determined by physical limitations of the hardware, not an arbitrary number chosen by the programmer.
- skissane 4y ago> The point is that the limit should be determined by physical limitations of the hardware, not an arbitrary number chosen by the programmer. A machine might have 64GB of RAM, but this application might be configured to be allowed to consume a maximum of 4GB of it. In which case, the limit isn’t being determined by the physical limitations of the hardware; whether or not it is under the control of the programmer depends on who does what. Some programmers get to decide how much memory to allocate to their program, for others that decision is made by somebody else.
- closeparen 4y agoA lot of people talking about correctness and performance, but I have a suspicion that most limits in older software had less to do with that and more to do with the fact that things were written in C, where arrays whose size is not known at compile time are just a lot more work for the programmer. There are cases where the allocations and memcpys when a Go or Java collection grows can be a real problem, but the vast majority of the time it works out fine to leave the size unspecified.
- bandrami 4y agoArbitrary limits are fine as long as they are powers of 2.
- iamnotsure 4y agohttps://en.wikipedia.org/wiki/Linear_logic#The_resource_interpretation https://en.wikipedia.org/wiki/Linear_logic#The_resource_inte...
- zarzavat 4y agoFor the complete opposite point of view, see Limits in SQLite: https://www.sqlite.org/limits.html https://www.sqlite.org/limits.html
- cleanchit 4y ago> In real-world software design, violations of this rule of thumb are common. For example, the FAT16 file system imposes a limit of 65,536 files to a directory.[3] Isn't it because 2^16 == 65536?
- dclowd9901 4y agoI believe Cyrillic languages have denominations that are beyond absent, singular and plural, like a large or small plurality. We may ask for an ideal in software but as long as people exist, exceptions will exist.
- hermannj314 4y agoOccasionally, other numbers have interesting properties: 1. No closed form solution for polynomials of degree 5 or larger. 2. 4-color theorem for painting planar graphs. There are lots more counter-examples: not 0, not 1 and probably not infinite. Probably some other number of counter-examples. If you were making a paint the map algorithm - your data structure should assume you need 0, 1 or infinite colors, instead of no more than 4? Is that the point of the principle?