4 ms·
You could provide even more clarity by using meaningful types like Money or TaxPercentage instead of Double. This would allow you to ensure only valid values a
by benjiweber 11y ago
You could provide even more clarity by using meaningful types like Money or TaxPercentage instead of Double.
This would allow you to ensure only valid values are passed and would help avoid problematic floating point arithmetic :)
- marcelocure 11y agoThe general idea was to show a simple exemple. But I really appreciate your point. Thanks
- pvg 11y agoI think money stuff is complicated and finicky enough to immediately make the example distractingly non-simple. In English, at least, taxes are usually charged and calculated on, not over things. Do you really mean transfer? Those often have fees rather than taxes. Or is it a Purchase? A Transaction? Isn't 'amount' clearer than 'transferValue?'. Is 'tax' supposed to be a percentage? A fraction? An absolute amount? This sort of thing is probably why such examples are always blandly about cars and their colors and shapes and their areas.
- thameera 11y agoI guess you mean typedefs and not separate classes for Money, TaxPercentage etc. I recently came across a codebase that implement type classes for almost all types of things it handles and found that to be overkill. Almost always, name and age can be represented by a string and an integer respectively; separate Name and Age classes just reduce the readability in your code.
- nhaehnle 11y agoIn a language that supports it reasonably, the advantage of genuinely separate types is that the language will prevent you from doing stupid things like accidentally multiplying to monetary amounts or adding a percentage to a monetary amount. Reasonable support here mostly means that you can implement operator overloads, so that you can define e.g. a Money type that can be added but not multiplied. Money handling may not actually be such a good example for this, because you should really have proper unit testing there anyway. I did work on a codebase that had types for SI units, and it was quite a nice experience.
- crimsonalucard 11y agoActually, I think using non standard types increases complexity, despite the more informative naming. I would now have to look up the implementation of Money and TaxPercentage to be sure of what it does, whereas if you move the type names into the variable names like in the following examples: 'double total_money' and 'double tax_percentage' I would immediately understand what's going on. I do see how a TaxPercentage type allows you to create a type that restricts itself to percentages. I feel that it is serves readability better to leave this checking to the function using the value itself rather than having the type do it.
- benjiweber 11y agoWell I disagree, but I doubt I'll convince you if you prefer that style :). You're not really making best use of the type system. Here's some of the reasons I'd prefer modeling this kind of thing with types How can you find all the uses of money throughout your codebase if they're just doubles? They'll be mixed up with all other uses of doubles. What happens when you need to add precision because double is no longer good enough? Not only do you need to find them all but then factor them out to different types. How do you support currencies? How do you know what currency "double total_money" is at the moment? The meaning is lost as soon as you pass it to another function. Even if you are only dealing with USD right now good luck adding currency support in the future if you're using primitives. Yes, you might have to press a key shortcut to look at the definition to see this information, but duplicating it in the variable name everywhere you use it seems barely better than comments. Furthermore, the variable names can be wrong because they're not enforced by the typesystem. The typechecker can enforce for me that I don't pass a negative value or a value in the wrong currency. Variable names don't do any enforcement Primitive obsession[0] also tends to lead to lots of duplication of logic. Multiple functions have tests that check what happens when passed an invalid value, logic that would be in one place with a type definition. [0] http://c2.com/cgi/wiki?PrimitiveObsession http://c2.com/cgi/wiki?PrimitiveObsession While not really related to the primitive obsession vs domain modelling debate - it's a really bad idea to use floating point numbers for monetary calculations, and from experience I can tell you how hard it is to fix this down the road in an existing codebase processing large amounts of money.