19

The question about default values in general - default return function values, default parameter values, default logic for when something is missing, default logic for handling exceptions, default logic for handling the edge conditions etc.

For a long time I considered default values to be a "pure evil" thing, something that "cloaks the catastrophe" and results in a very hard do find bugs. But recently I started to think about default values as some sort of a technical debt ... which is not a straight bad thing but something that could provide some "short term financing" get us to survive the project (how many of us could afford to buy a house without taking out the mortgage?).

When I say a "short term" - I don't mean - "do something quickly first and do refactor it out later before it hits the production". No - I am talking about relying on a hardcoded default values in a production software. Granted - it could cause some issues, but what if it only going to cause a single trouble in a whole year.

Again - I am talking about the "average" mainstream software here (not a software for a nuclear power station) - the average web site or a UI application for the accounting software, meaning that people lives are not at stake, nor millions of dollars.

Again, from my experience, business users would rather live with the software which "works somehow", rather then wait for a perfect one. And the use of default values helps a lot if you develop a software in a RAD style. But again - the longest debug sessions I have spent were because of the bugs introduced by a default value which either stopped being "a default" along the way or because a small subsystem has recently been upgraded and as a result of this upgrade it does not handle the default correctly (e.g. empty list vs null, or null string vs empty string).

So my question is - are the default values good or evil. And if they are a technical debt - how do measure up how much you can borrow so you can afford the repayments?

0

6 Answers 6

34

The concept of Convention over Configuration is impossible without sensible default values. The key word here is "sensible". The default values have to make sense for at least 80% (if not more) of all the uses of a library/service/framework.

General rules of thumb:

  • If a value is sensible for 80% or more uses, it needs to be a default value
  • If there are no values that are used for the majority of cases, do not use defaults.
  • Default values prevent stupid mistakes from the setup code. If the defaults are reasonable for most cases, fewer people mess with the working configuration.
  • Non-standard configurations are more visible when you use defaults.
  • Bad defaults are worse than no defaults.

Essentially, once you learn how the default configuration works, you can make educated decisions about how/when to do non-standard configurations.

4
  • Thanks for pointing me to "Convention over Configuration" concept. I did use it without knowing it has a name. Can you explain this rule: "Non-standard configurations are more visible when you use defaults." please.
    – user18404
    Mar 31, 2011 at 13:29
  • 3
    @Andrew if there's a dozen calls to Foo() and one call to Foo("bar"), that one call tends to stand out and is hence more visible. Mar 31, 2011 at 14:12
  • 2
    Right, and if most uses of an FTP service use new FtpService() the one that sets an alternate port will stand out (service.SetPort(12345)). Mar 31, 2011 at 14:38
  • Instead of having default values, you could have a "default" function doStuff() that doesn't take arguments , and a "non-standard" function doStuffWeirdly(..weird args) that does. All the advantages of defaults without any of the disadvantages.
    – Juan Perez
    May 19, 2023 at 17:45
49

Take for example a library that implements the FTP protocol. By default FTP is expected to operate on port 21. Now I would be very irritated if I had to specify to use port 21 every time I construct a object of a random FTP class. If I need a different port, let me specify.

Defaults are perfectly fine when they are sane defaults.

8
  • 25
    +1. When was the last time you typed http://programmers.stackexchange.com:80/questions/?sort=newest&pagesize=50 into an address bar? Mar 31, 2011 at 11:34
  • 1
    So, how do you measure/estimate/ect a sanity level of the default variable.
    – user18404
    Mar 31, 2011 at 13:24
  • 5
    How long it takes to think of a reasonable default value. Mar 31, 2011 at 13:56
  • 1
    @Andrew, see my answer below. If a value is good for 80% or more uses, it's a good default. Mar 31, 2011 at 14:40
  • 2
    @Berin Loritsch: If the default value is used for failing safely, you could argue that it's good even when it's used only 1% of the time.
    – oosterwal
    Mar 31, 2011 at 15:06
19

You're probably using a default keyboard layout with default key mappings, default mouse button mappings, the default browser, typing in the system default language, booting from the default OS in the boot loader, default positioned menus, default color scheme, default font width/height/face/style, default character set, default monitor resolution, default... you get the idea.

But in all seriousness, I think the concern you're having isn't with defaults but with something else. Default behavior doesn't inherently mask bugs. Most of the time your code is going to be running under common conditions anyway, regardless of whether or not you set defaults. Unhandled edge cases are things that you're going to want to make sure you avoid regardless (presumably through adequate and proper testing), for when the defaults are changed or an uncommon scenario happens.

Also, "catch-all" exception handling is arguably a design flaw rather than anything you could call "default".

6
  • OK, "catch-all" actually is a good example. Yes - it is causing a lot of grief when someday something is going wrong for some unknown reason, and these "some-s" are unknown largely because the real exception was lost in a catch-all block. So it is a bad thing - right? On the other hand - without a catch-all block the software could be either dying altogether (if the exception is not handled) or would require a complicated error handling logic (at least it would have to log the exception and initialize some data with a default values).
    – user18404
    Apr 2, 2011 at 7:15
  • So to add to my original question - if I am using the default values as a way to cut the corners during the development - and if the corners cutting results in a bugs and issues - what is the best way to recover from these issues?
    – user18404
    Apr 2, 2011 at 7:16
  • 1
    As far as exceptions goes, there's an article that says there should be one catch-all exception per thread, if any at all. It would be used for error reporting, so you're looking at the program as a single "thing" the same way the OS would look at a process. Since you've got the end user (and hopefully the developers) in the loop, you're not actually "swallowing" the exception -- so it's all good. Article here: codeproject.com/KB/architecture/exceptionbestpractices.aspx Apr 2, 2011 at 9:41
  • 1
    As for using defaults to avoid bugs -- how about using a consistent comment that you can control+f/mac+f for? For instance, Visual Studio actually show any comment that starts with TODO: or TEMP: in the tasks list. If I'm ever cutting a corner for development's sake, I try to be extremely careful to make sure I put a TODO there -- then, once in a while, I'll do a "find all" to go back and make sure none of that gets into any important builds. Apr 2, 2011 at 9:49
  • Whoops, I meant using hard-coded values to help development. By the way, I just realized that "hard-coded values" is probably the word you're looking for, rather than "default values". Apr 2, 2011 at 11:29
6

The root cause of the problems you cite is not default values per se, but integration problems due to changing interface contracts, interpretation misunderstandings and/or invalid assumptions. Basically all of these (specific examples) seem to be the result of improper communication - between client and developer, or between different developers / teams. Fair enough, these problems may manifest as invalid default values, but also in countless other forms.

Handle the root cause, not the symptom.

And note also, that - as others have pointed out with excellent examples - default values, when used wisely, can make the life of users significantly easier. And that is ultimately our aim, isn't it?

2
  • "Improper communication" could be the root cause, but isn't a root cause for pretty much anything? And since "my ultimate aim" is to deliver a "good-enough" software on time in cost constrained environment, I wanted to know how to tell the bad/evil defaults from the good ones.
    – user18404
    Apr 2, 2011 at 6:59
  • @Andrew, communication (or lack thereof) is a major factor in the success/failure of a project, but far from being the only one. However, when it is the culprit, it should be dealt with properly, otherwise your project is almost certainly doomed. I don't know of any magic tool for separating bad defaults from good ones: IMHO requires a careful analysis of the problem domain, use cases etc. and, well, lots of communication. Apr 2, 2011 at 19:32
4

Defaults should be used when they save the user or developer from performing repetitive tasks. They should never be used to mask errors or exceptions. It is not a bad practice to use them to prevent errors, but only so long as the prevention doesn't mask something bad happening. Default values are a tool just like everything else. Properly used they can save you a lot of headache and time. Improperly used they can bring the whole house down.

2
  • Sort of like C++ blowing your whole leg off... Apr 2, 2011 at 8:45
  • 1
    @muntoo: Hey, Lisp gave me a limp back in '03. Apr 2, 2011 at 13:37
3

Default values which are not a part of the communication protocol/convention are evil. By being "not a part" I mean they're not documented where the protocol is strict, or they're simply not expected, where the protocol is loose.

If the default value is documented/expected, it's still can be evil, but it can safe lives too. It depends on the domain area. It is very often when they can be very dangerous (e.g. default medicine dosage, default elevator floor, default car move direction), and sometimes it can be dangerous not not have them (e.g. default car move direction, default meeting time).

1
  • Personally, it seems safer if elevators have floors by default. Dec 9, 2023 at 2:37