(EditHint: Feel free to move discussions from ZeroOneInfinityRule here.)
Related to ZeroOneInfinityRule.
On computers with finite space, you can only give the illusion of being able to handle Infinity of anything. You can handle Zero of any number of things, and One of something provided it fits in the memory you have available, but you can only provide arbitrary numbers of things up to memory limits. Other considerations may also come into play; for instance, a network driver can only handle so many outgoing connections at a sane speed/without dropping them, a call stack can only grow for so many frames, or even such trivial things as "The screen has only so much space."
This does not mean that the ZeroOneInfinity rule should be disregarded; instead, when designing for an "Infinity" limit, one should choose a reasonable ApproximationOfInfinity as the capacity.
A good ApproximationOfInfinity has the following characteristics:
- Larger (preferably much larger) than the end user is anticipated to use. (Determining this might be non-trivial.)
- Determined by hardware statistics and/or empirical testing.
- Invisible to most layers of software, which ties in with the next characteristic:
- Trivial to change. (The meaning of "trivial" depends on the application, but the global maximum of difficulty should be "changing a constant in a header, rebuilding the software, and breaking backwards-compatibility with the old file-format." and the ideal is "if the hardware changes, the software knows about it," which is usually the case for purely memory-limited infinity.)
[roughly paraphrased from
FixedQuantityOverflowBug:]
In all cases, you should code either as if your types were unbounded. If, and ONLY if, this is impossible, code against some arcane UPPER_LIMIT constant and comment the hell out of it.
If it's possible to use unbounded/dynamically allocated types, then use them.
If the data you store will never leave a single machine, you may use machine types, but make sure you use the biggest machine type. Use no type smaller than size_t or long int. Essentially, the upper bound here should be one which will never be reached in any practical use. (MooresLaw helps with this, since the limit tends to grow much faster than the reasonable set of values--see, for instance, the Unix 2038 [non-]problem.
- If allocation of a non-persistent resource is limited only by available RAM, your theoretical infinity is (1 << 8 * sizeof(void*)) / sizeof(your_object_here). If possible, code as if you could have an infinite number of them; at minimum, code as if the number of them will not fit in anything smaller than a size_t.
- If allocation of a persistent resource is limited only by available disc space, code as if you have infinity of them. Use GUIDs, or just let the user take care of naming and organization of files. Coding to the maximum number of addressable bytes in the file system is possible, but probably a really bad idea.
If the data is persistent, try to use file formats with variable-length fields with massive upper bounds rather than fixed-length fields. This still might not solve the problem forever [what will happen when the field-length specifier overflows?], but it will solve it for longer.
If the limit is for legitimate performance reasons, i.e. hard real-time applications, then treat it as a hardware limit.
If a hardware/real-time limit would ever be reached for reasonable, practical reasons, order more hardware. HaHaOnlySerious.
Examples of good ApproximationsOfInfinity:
- Infinity memory ~= Amount of RAM in computer.
- Infinity memory ~= Amount of RAM in computer + maximum swap space.
- Infinity pointers ~= 1 << (sizeof(void *) * CHAR_BIT) addresses.
- Infinity GUIDs ~= Number of GUIDs that may be produced where the chance of collision is below some very small constant.
- Infinity free EMail storage ~= 2GB/user. (Assuming that EMail with attachments are rare.)
- Infinity EMail users ~= (Bulk storage on EMail server) / (2 GB)
- Infinity levels of folders ~= as many folders as metadata will fit on the disk partition.
- Infinity stack-frames ~= Some arbitrary-but-large space of reserved memory addresses.
- "Infinity" hourly-appointments/month == 24 hours/day * 31 max days/month
- But this is actually not an infinity--the "Infinity" is likely "Max meetings which could be held in an hour." Since humans seem to prefer half-hour increments, a good ApproximationOfInfinity for this value is two.
- Infinity miles per hour ~= 100 miles per hour, a good 25% faster than the upper bound of sane driving speed on an American highway. (Proof: No US state has a higher speed limit than 75 mph. No longer true, Texas has 85 mph speed limit on state highway 130 It is widely considered reasonable that all drivers should attempt to keep their speed within the speed limit plus-or-minus 5 mph. Therefore, the maximum sane driving speed is 80 mph, so an extra 20mph is certainly enough of a range to signify "too damn fast.")
- Infinite number of files in a directory ~= 10,000 if you're browsing, depending on the filesystem.
The EMail storage/users case is a particularly interesting one; while we could design the system so that the EMail space limits are invisible to the end-users, doing so would make it much harder to approximate infinity users (but on the other hand, if it was hard to change that amount, they wouldn't be able to provide extra storage space for money.) An important part of finding
ApproximationsOfInfinity is determining just how close each Infinity has to be, which Infinities are related, and which Infinities are most important.
Characteristics of bad ApproximationsOfInfinity include:
- Arbitrariness: the reasoning behind the value is unclear or nonexistant. (TheDailyWtf once showed code which failed if the year was 2012 or later...because it explicitly checked for 2012.)
- Hard to change: increasing the value by N requires >= O(N) lines of code or lines of storage. (This one seems to be surprisingly common on tdwtf, though one which comes to mind is code which used an index into a YN-string to determine if a day was a weekday. [To add insult to injury, the string was stored by year in a database called tblHoliday, and the string contained Y for weekday and N for weekend.])
- Conceivably small: it is easily possible to imagine someone needing more than the supplied "Infinity."
Examples of bad
ApproximationsOfInfinity:
- 5-10 E-mail fields. (It won't happen often, I grant you, but it's possible.)
- Any finite number of built-in operations. (There should be an easy way to add custom ones.)
- All kinds of magic values that could potentially become regular values.
- This goes double for dates, especially future dates. Y2K anyone? It's hard to claim YagNi when we'll need something capable of handling it some day by definition.
2^63-1 --
BottomMind