I am trying to model a domain as records and discriminated unions, i.e. immutable. I noticed, that I have a m:n relationship, say authors and books. And now I'm looking for a good way of expressing it, such that:
ideally immutable
changing a property on a book is easy, that is, if I want to create a copy, I don't have to iterate over all the authors
access is straightforward; ideally somehow an author has a books list
So far, i didn't find any solution fulfilling all of the criteria. What I found was:
Each author has a list of books (I don't really need the opposite direction). This allow for easy access and is immutable, however changing a property on a book entails changing every autor
Hold an immutable list of ref cells of books and each author has an immutable list of ref cells. This makes changing a property easy and access is easy, however this is not actually immutable, since the ref cell is not immutable.
Hold an immutable list of books and each author has an immutable list of IDs. This is immutable and makes changes to the books easy, however the access is more difficult because you need to do a lookup and you might have a non-existing ID.
Are there any solutions that fulfil all of the above, maybe something like an immutable ref cell? And if so, what do they look like.
As I mentioned in the comments, if you have an immutable list of authors and map over it, you do not actually end up copying all the authors. The authors who do not change will just be pointing to the same instance (so the overhead of immutable solution is not that big).
However, it is true that if you have multiple books with the same author, there is no aliasing and so the authors will all be separate values (and you will have to map over all books).
I think a reasonable representation in this case would be to keep the authors and books separate and link them via a key (such as author name - in the example below - or some other ID):
type Author = { Name : string; Address : string }
type Book = { Title : string; Author : string }
// For efficient lookup, create a hashtable with authors
let authors = dict [ "Tomas", { Name = "Tomas"; Address = "Cambridge" } ]
// Books are stored simply as a list
let books = [ { Title = "Real World FP"; Author = "Tomas" } ]
// To get nice access, add AuthorDetails property to the Author record
type Book with
member x.AuthorDetails = authors.[x.Author]
for book in books do
printfn "%s (%s, %s)" book.Title book.Author book.AuthorDetails.Address
This does not let you mutate the collection authors. If you were writing this in a purely functional way, you would probably have some recursive function that keeps current authors as argument and so you would not need mutation (just build a new dictionary).
But I think it is reasonable to have a ref value holding the dictionary, or even keep a mutable dictionary (but I would do that only if you do not have concurrency; in fact, in presence of concurrency, Map might be safer choice).
Related
The principle of always valid domain model dictates that value object and entities should be self validating to never be in an invalid state.
This requires creating some kind of wrapper, sometimes, for primitive values. However it seem to me that this might break the ubiquitous language.
For instance say I have 2 entities: Hotel and House. Each of those entities has images associated with it which respect the following rules:
Hotels must have at least 5 images and no more than 20
Houses must have at least 1 image and no more than 10
This to me entails the following classes
class House {
HouseImages images;
// ...
}
class Hotel {
HotelImages images;
}
class HouseImages {
final List<Image> images;
HouseImages(this.images) : assert(images.length >= 1),
assert(images.length <= 10);
}
class HotelImages {
final List<Image> images;
HotelImages(this.images) : assert(images.length >= 5),
assert(images.length <= 20);
}
Doesn't that break the ubiquitous languages a bit ? It just feels a bit off to have all those classes that are essentially prefixed (HotelName vs HouseName, HotelImages vs HouseImages, and so on). In other words, my value object folder that once consisted of x, y, z, where x, y and z where also documented in a lexicon document, now has house_x, hotel_x, house_y, hotel_y, house_z, hotel_z and it doesn't look quite as english as it was when it was x, y, z.
Is this common or is there something I misunderstood here maybe ? I do like the assurance it gives though, and it actually caught some bugs too.
There is some reasoning you can apply that usually helps me when deciding to introduce a value object or not. There are two very good blog articles concerning this topic I would like to recommend:
https://enterprisecraftsmanship.com/posts/value-objects-when-to-create-one/
https://enterprisecraftsmanship.com/posts/collections-primitive-obsession/
I would like to address your concrete example based on the heuristics taken from the mentioned article:
Are there more than one primitive values that encapsulate a concept, i.e. things that always belong together?
For instance, a Coordinate value object would contain Latitude and Longitude, it would not make sense to have different places of your application knowing that these need to be instantiated and validated together as a whole. A Money value object with an amount and a currency identifier would be another example. On the other hand I would usually not have a separate value object for the amount field as the Money object would already take care of making sure it is a reasonable value (e.g. positive value).
Is there complexity and logic (like validation) that is worth being hidden behind a value object?
For instance, your HotelImages value object that defines a specific collection type caught my attention. If HotelImages would not be used in different spots and the logic is rather simple as in your sample I would not mind adding such a collection type but rather do the validation inside the Hotel entity. Otherwise you would blow up your application with custom value objects for basically everything.
On the other hand, if there was some concept like an image collection which has its meaning in the business domain and a set of business rules and if that type is used in different places, for instance, having a ImageCollection value object that is used by both Hotel and House it could make sense to have such a value object.
I would apply the same thinking concerning your question for HouseName and HotelName. If these have no special meaning and complexity outside of the Hotel and House entity but are just seen as some simple properties of those entities in my opinion having value objects for these would be an overkill. Having something like BuildingName with a set of rules what this name has to follow or if it even is consisting of several primitive values then it would make sense again to use a value object.
This relates to the third point:
Is there actual behaviour duplication that could be avoided with a value object?
Coming from the last point thinking of actual duplication (not code duplication but behaviour duplication) that can be avoided with extracting things into a custom value object can also make sense. But in this case you always have to be careful not to fall into the trap of incidental duplication, see also [here].1
Does your overall project complexity justify the additional work?
This needs to be answered from your side of course but I think it's good to always consider if the benefits outweigh the costs. If you have a simple CRUD like application that is not expected to change a lot and will not be long lived all the mentioned heuristics also have to be used with the project complexity in mind.
I've found this great article where in the section on aggregates' structure, I can see a distinction being made between child entity (here: order item) and value object (here: address).
I'm not entirely sure how they differ on an architectural level. I'd like to say that both of them are value objects (aggregated within the root Order).
What am I missing in the picture?
Value Objects are much "values with methods" than they are "objects".
"Address" as a value, isn't fundamentally different from a primitive like integer. The significant difference between the two is that most generic programming languages don't come with a built in address type. So we have to roll our own -- or re-use one from a library.
In many modern languages, you can only roll your own by using the "object" idioms to create your customized data structure and the query semantics that you want.
Value objects are data with query semantics attached.
Entities, on the other hand, change over time. A way of thinking of an entity's implementation is that, under the covers, the entity is a mutable reference to a value.
void Entity::onChange(data) {
// dereference to get the current state value
val oldState = this.state;
// use a pure function to compute a new state value
val newState = stateChange(oldState, data);
// update the reference
this.state = newState;
}
The specific data structure being used to hold the state is an implementation detail of the entity of no interest to other elements in the solution.
A child entity is an entity, which is to say that it is an object with the responsibility for managing some implicit data structure. It is designed for change.
It's "just like the root", but on a smaller scale -- the root has a more complete sense of the entire context.
See also
Classes vs Data Structures -- Robert Martin
Perception and Action -- Stuart Halloway
According to DDD principles, it's often advised that value objects be used to encode values which don't have a life cycle of their own, but are merely values. By design, such objects are made immutable. They often replace primitives, which makes the code more semantic and error-safe.
The rationale is very sensible, but sometimes it leads to some cumbersome operations. For example, consider the case where an address is encoded as a value object along the lines of:
class Address extends ValueObject {
public Address(String line1, String line2, String postalCode, String String country) {
...
}
...
}
In an application, it wouldn't be unusual for a user to change only one field of an address. In order to achieve that in code, one would have to do something like:
String newCity = ...;
Address newAddress = new Address(
oldAddress.getLine1(),
oldAddress.getLine2(),
oldAddress.getPostalCode(),
newCity,
oldAddress.getCountry());
This could lead to some very repetitive and overly verbose code. What are some good strategies for avoiding this, while keeping immutable value objects?
My own ideas:
Private setters, which could enable helper methods like this:
public Address byChangingPostalCode(String newPostalCode) {
Address newAddress = this.copy();
newAddress.setPostalCode(newPostalCode);
return newAdress;
}
A downside is that the object now isn't immutable anymore, but as long as that's kept private, it shouldn't be a problem, right…?
Make the value object a full-fledged entity instead. After all, the need for fields to be modified over a longer time indicates that it does have a life cycle. I'm not convinced by this though, as the question regards developer convenience rather than domain design.
I'll happily receive your suggestions!
UPDATE
Thanks for your suggestions! I'll go with private setters and corrective methods.
There's nothing wrong with having immutable values return other immutable values.
Address newAddress = oldAddress.correctPostalCode(...);
This is my preferred approach within the domain model.
Another possibility is to use a builder
Address new Address = AddressBuilder.from(oldAddress)
.withPostalCode(...)
.build()
I don't like that one as much, because build isn't really part of the ubiquitous language. It's a construction I'm more likely to use in a unit test, where I need a whole address to talk to the API but the test itself only depends on a subset of the details.
Private setters, which could enable helper methods like this:
This is my preferred solution for changing a Value object. The naming of the method should be from the ubiquitous language but this can be combined to a team/programming language convention. In PHP there is a known convention: immutable command method names start with the word "with". For example withCorrectedName($newName).
The object must not be fully constant but only act as such in order to be considered immutable.
Make the value object a full-fledged entity instead.
It wouldn't be a ValueObject anymore, so don't!
I would solve this with derive methods:
Address newAddress = oldAddress.derive( newPostalCode);
Address newAddress = oldAddress.derive( newLine1 );
And so on...
I'm working on designing a gradually typed language as a personal project and I'm stuck at a particular design decision regarding immutability.
Talking about this in a language agnostic (and probably crude) way, I say there are two things that could be immutable or constant: the variable binding and the value itself.
The variable binding being constant is like const in Javascript or final in Java, where the variable cannot be reassigned. The value itself being immutable is like const in C++ or Object.freeze() in Javascript.
The question I'm having is, in the case of immutable values (not bindings) what should immutability be a property of?
The value/object itself in Javascript's Object.freeze?
var point = {x: 10};
var frozenPoint = Object.freeze(point);
or part of the type as in C++?
const Point p(10);
or as the variable binding as in Rust?
let p = Point { x: 10 };
// vs let mut p = Point { x: 10 };
or as part of the API of a library? Facebook's Immutable.js, Google's Guava library for Java (ImmutableList class), etc.
I understand that there's probably no "correct" answer for this, so what I'm really looking for is a comparison of the philosophies and motivations for these approaches.
There is a correct answer, but it is very different than what you expect.
The best is to not have mutability at all. In other words : the language should be purely functional. There is no reason to have mutability in a language with garbage collection. Haskell is a proof of this.
I have a tuple list that look like this:
{[{<<"id">>,1},
{<<"alerts_count">>,0},
{<<"username">>,<<"santiagopoli">>},
{<<"facebook_name">>,<<"Santiago Ignacio Poli">>},
{<<"lives">>,{[{<<"quantity">>,8},
{<<"max">>,8},
{<<"unlimited">>,true}]}}]}
I want to know how to extract properties from that tuple. For example:
get_value("id",TupleList), %% should return 1.
get_value("facebook_name",TupleList), %% should return "Santiago Ignacio Poli".
get_value("lives"), %% should return another TupleList, so i can call
get_value("quantity",get_value("lives",TupleList)).
I tried to match all the "properties" to a record called "User" but I don't know how to do it.
To be more specific: I used the Jiffy library (github.com/davisp/jiffy) to parse a JSON. Now i want to obtain a value from that JSON.
Thanks!
The first strange thing is that the tuple contains a single item list: where [{Key, Value}] is embedded in {} for no reason. So let's reference all that stuff you wrote as a variable called Stuff, and pull it out:
{KVList} = Stuff
Good start. Now we are dealing with a {Key, Value} type list. With that done, we can now do:
lists:keyfind(<<"id">>, 1, KVList)
or alternately:
proplists:get_value(<<"id">>, KVList)
...and we would get the first answer you asked about. (Note the difference in what the two might return if the Key isn't in the KVList before you copypasta some code from here...).
A further examination of this particular style of question gets into two distinctly different areas:
Erlang docs regarding data functions that have {Key, Value} functions (hint: the lists, proplists, orddict, and any other modules based on the same concept is a good candidate for research, all in the standard library), including basic filter and map.
The underlying concept of data structures as semantically meaningful constructs. Honestly, I don't see a lot of deliberate thought given to this in the functional programming world outside advanced type systems (like in Haskell, or what Dialyzer tries hard to give you). The best place to learn about this is relational database concepts -- once you know what "5NF" really means, then come back to the real world and you'll have a different, more insightful perspective, and problems like this won't just be trivial, they will beg for better foundations.
You should look into proplists module and their proplist:get_value/2 function.
You just need to think how it should behave when Key is not present in the list (or is the default proplists behavior satisfying).
And two notes:
since you keys are binnary, you should use <<"id">> in your function
proplists works on lists, but data you presented is list inside one element tuple. So you need to extract this you Data.
{PropList} = Data,
Id = proplists:get_value(<<"id">>, PropList),