4 ms·
Don't use boolean parameters to toggle behaviour - they're indecipherable from the calling context. But don't then mindlessly create the cross-product of method
by barrkel 8y ago
Don't use boolean parameters to toggle behaviour - they're indecipherable from the calling context. But don't then mindlessly create the cross-product of methods from every combination of true and false for your boolean parameters: If the caller would have used an expression rather than a literal to determine which version of the method to call, use enums instead of booleans or multiple methods. And don't turn setEnabled into enable/disable pairs, or setVisible to show/hide pairs - these are understood as properties, not parameterized methods.
Enums vs inheritance isn't straightforward. Enums make it easy to add new kinds, while inheritance makes it easy to add new methods. They are more extensible in different directions. If it's very rare for you to add new values to your enum, and more frequent for you to switch on that enum, prefer enums (and always throw in your default clause!). If you are adding enum values all the time, and only have a couple of methods that switch on them, then prefer inheritance. Although if you're using Java, consider methods on your enum values instead.
To understand the enum / inheritance tradeoff better, examine the Expression problem: https://en.wikipedia.org/wiki/Expression_problem https://en.wikipedia.org/wiki/Expression_problem
- TorKlingberg 8y ago> Don't use boolean parameters to toggle behaviour - they're indecipherable from the calling context This is mostly solved in languages with named parameter calling (if you use it). Example: createFile(name, contents, temporary=True) Sometimes it is already obvious enough. In C I have no problem with set_visible(item, true);
- fao_ 8y agoEven something like int temporary = true; create_file(path, contents, temporary);
- tabtab 8y agoIn some languages you can use the named-parameter version to indicate what's being true-ified: create_file(path, contents, temporary:=true);
- blattimwind 8y agoC++ has named parameters, too. If you want it to.
- hellofunk 8y agoWould like an example; this is hardly "solved" in C++. There is an old Boost library that does this, but it's not idiomatic and rarely used. Unless you are using a different definition of named parameters, I've never seen C++ code in the wild that used them.
- ninkendo 8y agoThat’s a bold statement, I’d love to see an example to show this.
- CmdrKrool 8y agoSounds like the "named parameter idiom", the function comes with a struct that contains all the possible parameters and the caller passes one of those to the function instead of each parameter seperately. http://www.cs.technion.ac.il/users/yechiel/c++-faq/named-parameter-idiom.html http://www.cs.technion.ac.il/users/yechiel/c++-faq/named-par...
- sanderjd 8y agoYou can mimic this in most languages: createFile(name, contents, /* temporary= */ true). Of course that doesn't guarantee that that's what that parameter is actually named, but you can write a lint for that (with quite a bit of effort).
- acdha 8y ago> Of course that doesn't guarantee that that's what that parameter is actually named I’ve found the odds of that happening approach certainty once you have more than one or two parameters. If you’re using a language without named arguments I usually treat adding a third parameter as a cue to reconsider using a more idiomatic interface, whether that’s something like classic Java OOP (.setTemporary(true)) or limiting that knowledge to one place by e.g. creating a subclass, struct, or a specialized function so you call createTemporaryFile() and know that ordering check only needs to be done in one place rather than by every caller.
- lower 8y agoI'm not sure about this, because it's easy to mix up two arguments of the same type. For example, you could mean createFile(name, contents, /* temporary= */ true, /* overwrite= */ true) but write createFile(name, contents, /* overwrite= */ true, /* temporary= */ true) by accident.
- SomeCallMeTim 8y agoNow I want to see something like Prettier (a code formatter that enforces _exact_ whitespace and specific optional syntax) that will parse C code and fill in the correct parameter names, in comments, based on the headers, for any boolean parameters (maybe excluding single boolean parameters?).
- fjsolwmv 8y agoA decent linter checks those Boolean comments for accuracy. Writing documentation that that merely copies existing code is terrible: it's either going to be wrong (because it's not automatically checked and will go sour in a refactoring, or it's right because it's so obvious that no one will guess wrong when looking at it.)
- carlmr 8y agoI'm also usually pro enum and against inheritance. I find inheritance is harder to read when you jump into a codebase. The expression problem of course is to be considered. Many languages now also have discriminated unions (enums with data), like F# and Rust, which make enum the better choice in more cases.
- tigershark 8y agoIt always depends on the language that you are using. In c#, for simple cases, enums are perfect, but otherwise you should switch to classes hierarchies. In Java you can use them in more complex cases because you can encode data quite easily. If the amount of data encoded is becoming too much (let’s say more than a couple/three fields per case) than you should switch to classes. In F# you can use a combination of sum and product types and have a happy life with automatic deconstruction and a somehow less happy one with lenses/optics.