4 ms·
Solution in C#: use named parameters: RaiseInvoice(taxInvoice: false, sendEmail: true)
by kierenj 2y ago
Solution in C#: use named parameters: RaiseInvoice(taxInvoice: false, sendEmail: true)
- gary_0 2y agoWhich is far more realistic than defining single-use enums all over the place. I don't know why more languages don't have named parameters...
- kerkeslager 2y agoWhy is defining an enum "unrealistic"? It's at most 4 lines of very simple code to define an enum that replaces a boolean.
- edflsafoiewq 2y agoThink about cases more complicated than passing a bare literal. // Booleans + Named Parameters foo(should_scrub=not options.scrubbing_disabled) // Single-Use Enum import ScrubbingOption, ShouldScrub; foo( if options.scrubbing == ScrubbingOption::Disabled { ShouldScrub::No } else { ShouldScrub::Yes } )
- oneeyedpigeon 2y agoIf you format the second example more sensibly: foo(options.scrubbing == ScrubbingOption::Disabled ? ShouldScrub::No : ShouldScrub::Yes) it doesn't look much worse at all
- kerkeslager 2y agoI'd actually go further and say that there's no reason I can think of that foo() shouldn't have access to the ScrubbingOption, so just pass that in. If you have two-option enums and for some reason you transform them into two-option enums that represent essentially the same thing, of course that's going to be unnecessarily complex. As a general rule, "it's more verbose" isn't much of a concern to me: verbosity is a very poor indication of complexity, and entering code with your keyboard simply isn't the bottleneck for writing code (if it is, you aren't thinking about what you're writing enough).
- edflsafoiewq 2y ago> If you have two-option enums and for some reason you transform them into two-option enums that represent essentially the same thing, of course that's going to be unnecessarily complex. "For some reason" being anything so prosaic as they come from different libraries.
- kerkeslager 2y agoIf you have two libraries that aren't explicitly made to work with each other and operate on the same problem domain, being explicit about the translation layer between those two libraries is very much a feature, not a bug. That's absolutely a spot where verbosity and named enums will shine.
- kerkeslager 2y agoThat doesn't fix readability (is the invoice being raised not a tax invoice? Or are we not taxing the invoice being raised?). That doesn't fix the possibility of adding a third possibility either (what if we separate non-tax invoices into two types of invoices?). RaiseInvoice(InvoiceType::Tax, Notifications::Email);
- edflsafoiewq 2y agoIf you don't have named parameters, you can fall back to variables var taxInvoice = false var sendEmail = true RaiseInvoice(taxInvoice, sendEmail) It's obvious, but people tend not to do it.
- wrs 2y agoSadly there is nothing that can tell you that you got those arguments backwards.
- edflsafoiewq 2y agoPoint taken. But you can check the declaration of RaiseInvoice and see if the names match. If you had RaiseInvoice(false, true) then you really wouldn't know.
- wrs 2y agoTotally a matter of taste, but for an equal level of protection and less vertical waste I’d rather just do RaiseInvoice(/*taxInvoice*/ false, /*sendEmail*/ true)
- deleted 2y ago[deleted]
- keithnz 2y agono, way better to make an options object then set the options you want, also works a lot better later when you want more options.
- HumblyTossed 2y agoWay better use a bit pattern.
- worble 2y agoYou can't force the caller into using named parameters though. So when it's late at night, you're tired but also think you know better, there's nothing stopping you from doing RaiseInvoice(true, false) when you actually meant the inverse.