I find it really similar to stuff in Effective Java. Sure there's nothing too revolutionary in that book, but in the aggregate it makes up my best coding practices, and when somebody questions one small piece of those coding practices, I can send them to a brief, to-the-point item in Effective Java.
Most code I read does not use value objects. It's more common for me to see primitive obsession [1], data clumps [2], arbitrary structs, or the "struct + service" antipattern (looking at you, Angular 1). Granted, I'm not working with FP languages.
When you migrate code to use value objects, then follow up by moving associated behavior into the value object, there are significant knock-on benefits to your design.
Value objects may be simple, but they're not obvious. If they were, more code would use them.
It sounds rather like value objects are strictly superior than immutable data structures, based on this statement. I'd love to hear an expansion of this rationale.
So, languages should stop thinking in terms of "this is a reference type" and "this is a value type", and start thinking about "this references something mutable" vs "this references something immutable". For the latter, the implementation can then use by-value semantics for perf reasons, where appropriate.
On the other hand, mutable objects with value semantics can provide the ergonomic advantage that mutation has in some cases (e.g. 'point.y += 10' rather than 'point = Point(point.x, point.y + 10)' as well as more predictable performance, while avoiding bugs caused by accidental aliasing.
How is that having value semantics? Or are you just referring to equality testing? Even then you're playing a dangerous game if you have multiple threads (one mutating, one running an equality check) and aren't using locks.
I think that's part of a problem. Object identity should not be used for unique IDs - when you need a unique ID, use a UniqueIdGenerator or something like that.
Java and C# and others have got this so very wrong, when they did things like, "okay, all objects have identity, let's just reuse it for other stuff", and made it possible to e.g. synchronize on arbitrary objects - synchronize(x) in Java, lock(x) in C#. Now they can't get rid of object identity, because it's part of the language semantics - even if you never synchronize on objects of your class, something else might, and making them identity-less will break that.
At the very least, let's make it explicit. When you define a class, it should be stated upfront whether it has identity or not. If it doesn't have identity, it should be immutable. If it does have identity, it still can be immutable if you want (if you need that identity for something, like your event example). But this state of affairs - immutable with identity - definitely shouldn't be normal. If it's needed, it should be requested explicitly.
I guess the real point here is that object identity has a heavier cost than it would seem from the first glance, and so it should be opt-in rather than opt-out (and it should definitely be possible to opt out).
As for `point.x += 10`, it doesn't preclude point from being immutable. It just means that the language has to desugar it into `point = Point(point.x, point.y + 10)` for you. That way, there's no accidental aliasing (since objects are still immutable - it's the reference that is mutating - so no alias can observe the change). And then the code generator, knowing that there's no aliasing, can replace it with actual in-place field update, when and where it makes sense.
To the extent that the concept is relevant, the difference is obvious unless you only ever use languages that are ambiguous about reference/value semantics.
If you use a language like C or C++ or even assembly, where pointers and taking an address are explicit and fundamental concepts, there's mostly no problem. Your data is a value by default, and if you want a reference (pointer) instead, you just make one, explicitly. The exception is arrays, and in not entirely unrelated news, array semantics in C and C++ are a significant source of bugs.
If you use a functional programming language, again data is typically immutable unless you explicitly use some sort of reference type, so again no problem.
I have long maintained that one of the worst of Java's many design flaws was using the exact same syntax to represent two distinct but related concepts, depending on whether you were referring to a primitive or a class-based type. At least with the static typing you can see which you've got, though.
I can't fathom why you'd deliberately design a language to work like JS or Python, where not only can the exact same syntax mean two completely different things but which you get depends on dynamic typing information that you can't even see until runtime, or even on the exact values you're using rather than their types, in a case like Python's handling of small integers.
I shudder to think how much productivity has been lost by now to bugs caused by mixing up .equals() with == in Java, == with === in JS, and == with `is` in Python.
He's had some real hits.
But I must admit, I find this article a bit silly. He's had some stinkers too. Worse still, this is an obvious problem because the solution's been in other languages for decades, overloading equivalence, it's just not in javascript. It's just not a common programming problem outside of certain domains.
And, he knows it.
So I really do not understand the point of that post. There was a time when every single one of the "learn .Net 1.0 in 28 days" books would have at least a paragraph about overloading Equals and GetHashCode. This is from 2005, for example, and even uses the same example:
https://msdn.microsoft.com/ru-ru/library/ms173147(v=vs.80).a...
The blog post seems a decade too late.
- Thinking differently about Values vs. References (which you may or may not be used to depending on your language)
- Mutable "values" are dangerous (and it might be worth thinking about what constitutes a "value")
- Translating incoming low-level numbers and strings into proper "values" helps avoid errors.
That can be useful, maybe not when you are in the thick of it, but for newcomer or people that have missed the great ideological battles of the last 6 months.
On the other hand, both this article and the "Collection Pipeline" one contain a lot of useful information, concisely and informatively expressed, which would be beneficial to a junior developer as a general introduction to the subject.
Also, for perceived thought leaders, all these people have completely failed to update their knowledge with modern technologies and languages. All you see from the Fowler and Uncle Bob of the world is Java and Javascript. How about some Rust, ELM, Kotlin, which encompass the more modern trends of programming and which address the kinds of problems described in this article in one liners?
Also, I still chuckle at the fact that Fowler's web site (which he developed himself and called a "bliki", blog + wiki) is still incapable of supporting article titles with spaces in them, hence "ValueObject". That's not exactly a resounding endorsement of software engineering abilities.
/s
That's not a new name. It's been around forever.