6 ms·
Whoever wrote the original code is missing a major point in OOP: you should (almost) never be passing in simple types. Create an object that holds the data (c
by dhimes 14y ago
Whoever wrote the original code is missing a major point in OOP: you should (almost) never be passing in simple types. Create an object that holds the data (class IDObject, for instance), and pass an instance of this class in for the parameter. Then, the parameters are de facto named in the data object.
This importance of this method is that it allows the you to update the information passed in via the data object (when ID needs change, and they will over the course of a project) without breaking the interface. And that's the point of it all.
- TazeTSchnitzel 14y agoNever passing in simple types? I don't know about you, but one of the reasons I like languages such as Python and JavaScript is I don't have to create a wrapper object for every type I'm using. The fact I had to, for instance, create URL and IP Address and such objects in C# drove me crazy.
- jebblue 14y agoWhen I program in Python I would do it the same way, create a class that represents the types. The class can be made into a persistence class easily, this approach is clear, readable and maintainable. Oh and I try to avoid JavaScript, too much clever coding makes it a hard language to maintain.
- nessus42 14y agoNamed tuples are nice in Python. I wonder how easy it is, though, to modify a namedtuple constructor to do argument validation and to allow for default field values.
- TazeTSchnitzel 14y agoIf you see how namedtuple is implemented, you'd realise it's extremely easy. namedtuple uses eval(). It really shouldn't, since there are far better ways to do what it does, but it does.
- dhimes 14y agoThe idea is to write a wrapper that encapsulates all of the (related) data. This is useful in type-checked languages where changing the signature can have repercussions across multiple classes. I actually do this in javascript, too. I'll pass in object (it's nice in js because you can just write them in json) and refer to the variable by object property verifyID({idNum: 1234, surname: 'Himes', firstName: 'Dan'}); {where the signature is verifyID(idObect) } This has the advantage of not requiring you to remember the order of parameters.
- Roboprog 14y agoOTOH, I kind of like languages that support map literals and/or tuples, rather than making me define a new class for use in a single place as a parameter object or return value. On the gripping hand: click on the method name (in an IDE), and let the IDE tell you what the params are to the method. Why bother with static typing if you aren't going to use the information?
- nessus42 14y agoOn the other hand, the Law of Demeter says that you should almost always be passing in and fetching primitive types. At least in an API. Does it not? Though I'm guessing that "primitive types" would include algebraic data types, which serve the same purpose here as little objects like IDObject. And since Java doesn't have algebraic data types.... All the more reason to switch to Scala. Edit: I should have written "built-in types" above, rather than "primitive types".
- peeters 14y agoHmm, I've never seen Demeter interpreted to mean that you should favour primitives over rich types. Can you explain your interpretation?
- nessus42 14y agoI've heard the Law of Demeter at times stated explicitly as that you should usually return only primitive data types from an API. Rich Hickey certainly claims this too, although he doesn't refer to it as the Law of Demeter. The Law of Demeter is also sometimes summarized by "One dot: good. Two dots: bad." Or from Wikipidia: In particular, an object should avoid invoking methods of a member object returned by another method. For many modern object oriented languages that use a dot as field identifier, the law can be stated simply as "use only one dot". That is, the code a.b.Method() breaks the law where a.Method() does not. Edit: I should have written "built-in types" above, rather than "primitive types".
- deleted 14y ago[deleted]
- hkolek 14y agoThat has nothing to do with primitive types. Otherwise in Java it would mean you shouldn't return a String ever because it's not primitive! It has nothing to do with primitive types whatsoever. It's about encapsulation, i.e. you should not depend on the internal structure of an object. As a simple example, when one wants to walk a dog, one would not command the dog's legs to walk directly; instead one commands the dog which then commands its own legs. i.e. this is violating the law: dog.getLegs().walk() and should instead be written: dog.walk() with this implementation: class Dog { void walk() { legs.walk(); } }
- arethuza 14y ago"when ID needs change, and they will over the course of a project" That sounds awfull like YAGNI would apply: http://en.wikipedia.org/wiki/You_ain%27t_gonna_need_it http://en.wikipedia.org/wiki/You_ain%27t_gonna_need_it
- dhimes 14y agoThere is a small but meaningful distinction: Encapsulating the data in OOP fashion allows you to respond when the need arises. You don't build it until you need it, but when/if you do ever need it you won't have to refactor the interface (and the interfaces of all the classes that use these data). This minimizes changes down the road and leads to maintainability.
- arethuza 14y agoBut it also means that you are introducing a lot of extra classes that do almost nothing but wrap primitives and provide little or no additional behaviour. If you do need to pass in additional information, refactor and change the primitive to an object when you really need to, not because you might need it at some point in the future (and the chances are you won't).
- flatline3 14y ago> If you do need to pass in additional information, refactor and change the primitive to an object when you really need to, not because you might need it at some point in the future (and the chances are you won't). That's a lot harder than doing it right to begin with, and requires significant API-breaking changes across the code base. Due to the cost of doing so, it's far more likely that the code will be hacked poorly to incorporate the necessary addition, as the substantial changes now required would be much too costly. YAGNI is misused to justify being lazy. You're always going to need maintenance (except when you have the rare piece of throw-away code), certain approaches are always going to incur high costs to maintenance and future development. YAGNI doesn't apply when past experience provides sufficient evidence that you do need it, and you need it now, when you're writing the code.
- sixbrx 14y agoI think types are orthogonal to why named parameters are helpful, because parameters don't just indicate a type but a particular usage of a type. So for example, in a bank transfer method the named parameter would help distinguish the from-account from the to-account. The accounts are already not simple types, but their usages (roles in the sentence underlying the semantics of the method) are different. You could create a "transfer" class of course for the pair of accounts, but are we going to do this for each combination of usages of our types. Hopefully not - we'd basically be encoding each combination of parameters that our methods accept into an object - not practical or productive in my opinion.