4 ms·
This is what refactoring is for. Start out simple (maybe a primitive is all you need) and then, if and when the need arises, refactor and introduce a value obj
by carsongross 14y ago
This is what refactoring is for. Start out simple (maybe a primitive is all you need) and then, if and when the need arises, refactor and introduce a value object. That's where the failure is in this story.
I've seen a lot of premature abstraculation blow up the opposite way: incomprehensible, elaborate object models attempting to be The Best Abstraction Evar around fundamentally simple concepts. These things can be hard to work with and change, contribute difficult to discern complexity to applications and cause huge performance headaches.
You aren't gonna need it, worse is better, simplicity of implementation above all else.
- famousactress 14y agoYes Yes Yes, this. The world is littered with code that never made a dent in the world but was uber-prepared for the day that we'd suddenly need a new way to talk about numbers/dates/strings.
- swanson 14y agoThanks for the comment, I definitely agree that this should have been picked up in a refactoring. I've also been on other projects that go the opposite direction of abstracting everything to the point that you don't realize some function has already been abstracted so you write a new one!
- fizx 14y agoThis is also what experience is for. It teaches you the probability that you will need the abstraction in the future. As a beginner, you should err on the side of YAGNI; as an expert, you probably already know what to do.
- jdlshore 14y agoIt's not quite that simple. Primitive obsession is a form of duplication, and it's particularly difficult to spot without practice. Once found, it can be a real bear to remove. Chapter 4 of my screencast [1] shows this; it took me an hour and a half to refactor a trivial application to remove its primitive obsession. (And there's strong case to be made that some of the difficulty I had in earlier episodes was due to primitive obsession as well.) I agree that premature abstraction is a pain, too, so I wouldn't want to go down that route. However, preventing primitive obsession can be as trivial as using a two-method wrapper class. More methods and abstraction can be added on an as-needed basis. Also, removing the wrapper class is automatable with the "Inline Method" refactoring in some IDEs. So the design tradeoffs I see are: 1- Primitive obsession: high duplication burden, high complexity burden, hard to remove 2- Wrapping primitives that don't need it: low complexity burden, easy to remove So I prefer to error on the side of wrapping primitives. That said, I've never actually encountered a case where I wrapped a primitive that didn't need it, and I still accidentally create the primitive obsession smell a lot. It seems so innocuous at first. [1] http://jamesshore.com/Blog/Lets-Play/ http://jamesshore.com/Blog/Lets-Play/
- skybrian 14y agoThat's language-specific advice. Go handles this much more elegantly. You can create a Celsius type very simply: type Celsius float64 // Temperature in degrees Celsius It's no harder to use than 'typedef' in C and similarly it doesn't get in your way, but you get a real type and nice errors when you screw up. There's no reason not to do it right away.