Can we use List<ValueObject> inside entity? or we should use them as List<entity>?
When I use 'List<Discount>' inside my 'Product' entity class, entity framework creates a 'Discount' table with a generated column id.
Is it OK that i have defined Discount as List of value objects?
When a value object is used as a list, is it better to use it as an entity with its identity?
The second question is about updating 'List<Discont>' inside entity. how can I update this value object list inside its entity( add,remove discount)?
thanks
As mentioned in the comments by #Ivan Stoev, your domain model is not your database model. You need to model your domain in an object-oriented way with, ideally, no regard for the database. BTW, having some identifier in a Value Object does not make it an Entity. An Entity would, however, always require a unique identifier within that entity set but an identifier isn't the defining factor to make a class an entity (that would be whether it has its own lifecycle).
In the real world one would need to be pragmatic about the general guidance. For instance, if you need an identifier of sorts for your value object then that is fine. However, it may be that there is already something there that may be used. In an OrderItem one would use the ProductId since there should only be a single item for each product. In your Discount scenario perhaps there is a DiscountType where only unique discount types are permitted. On the point of mutable value objects, the reason a value object is usually not mutable is that it represents a particular value. You would never change 10 since that would be another value. It would seem that one would be changing 10 to, say, 15 when you need 15 but, in fact, that 15 is another value object. Again, one would need to be pragmatic and in many circumstances we end up using a Value Object that isn't as primitive as a single value so it may make sense to alter something on the value object. An order item is certainly not an entity but one would need to change the Quantity on the item every-so-often. Well, that may be another discussion around Quote/Cart vs Order but the concepts are still applicable.
On another note, I tend to nowadays define any "value object" that exists only within an aggregate as a nested class within the aggregate. I would not have Order and OrderItem classes but instead an Item class within the Order class... Order.Item. That is a design choice though but I thought I'd mention it.
Related
C# 9 introduces record reference types. A record provides some synthesized methods like copy constructor, clone operation, hash codes calculation and comparison/equality operations. It seems to me convenient to use records instead of classes in general. Are there reasons no to do so?
It seems to me that currently Visual Studio as an editor does not support records as well as classes but this will probably change in the future.
Firstly, be aware that if it's possible for a class to contain circular references (which is true for most mutable classes) then many of the auto generated record members can StackOverflow. So that's a pretty good reason to not use records for everything.
So when should you use a record?
Use a record when an instance of a class is entirely defined by the public data it contains, and has no unique identity of it's own.
This means that the record is basically just an immutable bag of data. I don't really care about that particular instance of the record at all, other than that it provides a convenient way of grouping related bits of data together.
Why?
Consider the members a record generates:
Value Equality
Two instances of a record are considered equal if they have the same data (by default: if all fields are the same).
This is appropriate for classes with no behavior, which are just used as immutable bags of data. However this is rarely the case for classes which are mutable, or have behavior.
For example if a class is mutable, then two instances which happen to contain the same data shouldn't be considered equal, as that would imply that updating one would update the other, which is obviously false. Instead you should use reference equality for such objects.
Meanwhile if a class is an abstraction providing a service you have to think more carefully about what equality means, or if it's even relevant to your class. For example imagine a Crawler class which can crawl websites and return a list of pages. What would equality mean for such a class? You'd rarely have two instances of a Crawler, and if you did, why would you compare them?
with blocks
with blocks provides a convenient way to copy an object and update specific fields. However this is always safe if the object has no identity, as copying it doesn't lose any information. Copying a mutable class loses the identity of the original object, as updating the copy won't update the original. As such you have to consider whether this really makes sense for your class.
ToString
The generated ToString prints out the values of all public properties. If your class is entirely defined by the properties it contains, then this makes a lot of sense. However if your class is not, then that's not necessarily the information you are interested in. A Crawler for example may have no public fields at all, but the private fields are likely to be highly relevant to its behavior. You'll probably want to define ToString yourself for such classes.
All properties of a record are per default public
All properties of a record are per default immutable
By default, I mean when using the simple record definition syntax.
Also, records can only derive from records and you cannot derive a regular class from a record.
I have a problem with the boundaries of aggregates. I was trying to read about aggregates, aggregate roots, and boundaries, looking for some code examples but I still struggle with it.
The app that I'm working on is an app to manage architecture projects.
Among the screens in the app there will be a screen with all details for the selected project, and one with all jobs for the selected constructor.
I have one AggregateRoot - ArchitectureProject.It has an Architect, Stages, etc. and it has a list of ConstructorJobs (as it has to be on the screen with project details). ConstructorJob has its name, some value, and a Constructor. A Constructor can have some ConstructorType. As for me, Constructor is another AggregateRoot. I have a problem with ConstructorJob. Where should I place it? What should be responsible for managing it?
I was trying to thing what cannot exist with what, and ConstructorJob cannot exists without Project, but on the other hand it has to have Constructor as well...
I can't imagine that Constructor would belong to Project Aggregate, as ConstructorType would be 4th level child to id, so searching for all constructors of that type would be painful, wouldn't be?
I would appreciate any explanation, how to handle such cases.
I think you are missing an important rule which usually makes your life a lot easier:
Rule: Reference Other Aggregates by Identity
See also Vaughn Vernon's Book Implementing Domain-Driven Design, chapter 10 - Aggregates.
It is important to note that Aggregates in the sense of domain-driven design are not so much focused on if the existence of one aggregate makes sense without the other. It is more about transactional boundaries. So an aggregate should create a boundary around elements that should only change together within the same transaction - to adhere to consistency.
So I guess, that you will change your Project in different use cases you would change the Constructor - which I guess can be referenced in different projects.
This means you should reference other aggregates within aggregates only by id which avoids modelling huge aggregates with deep hierarchies. It also means that if your aggregates tend to grow bigger over time that you might have missed some new aggregate which you initially modelled as entity and should be an aggregate on its own.
As for me, Constructor is another AggregateRoot. I have a problem with ConstructorJob. Where should I place it? What should be responsible for managing it?
In your case I would model it the following way:
The ConstructorJob is a Value Object which holds some data (name, etc.) and also a reference to a Constructor aggregate. But this reference is not a reference in terms of object reference like you would do it with a child entity of an aggregate root. The constructor aggregate is referenced by an identifier (UUID, integer or whatever you are using as id type) in the ConstructorJob.
The ConstructorJob value object would be part of the Project aggregate. The project aggregate could of course directly hold the id of the constructor aggregate but I guess in your case the value object might fit quite well.
Let's say I want an immutable model, a world. How one should model references?
case class World(people: Set[Person])
case class Person(name: String, loves: Option[Person])
val alice = Person("Alice", None)
val peter = Person("Peter", Some(alice))
val myWorld = World(Set(alice, peter))
println(myWorld)
Outputs:
World(Set(Person(Alice,None), Person(Peter,Some(Person(Alice,None)))))
But now we have two separate persons named Alice (in the people set and in the peter person).
What is the best practice(s) on approaching this referencing in an immutable model in Scala?
I thought about referencing strictly through ids, but it doesn't feel right. Is there a better way? (Also current implementation doesn't support recursion/circle like A loves B and B loves A.)
I think you have to distinguish between pure values, and things that have a notion of identity that survives state changes.
A person might be something in the latter category, depending on the requirements of your model. E.g. if the age of a person changes, it is still the same person.
For identifying entities over state changes, I don't think there is anything wrong with using some kind of unique identifier. Depending on your model, it might be a good idea to have a map from person id to person state at top level in your model, and then express relationships between persons either in the person state, or in a separate data structure.
Something like this:
case class Person(name: String, age: Int, loves: Set[PersonRef])
case class PersonRef(id: Long) // typesafe identifier for a person
case class World(persons: Map[PersonRef, Person])
Note that a person state does not contain the ID, since two persons with different IDs could have the same state.
A problem with this approach is that the world could be in an inconsistent state. E.g. somebody could love a person that does not exist in the world. But I don't really see a way around this.
I think it might be worth looking at scala libraries that are confronted with a similar problem. E.g.
diode has the concept of a reference to a value elsewhere in the model
scala graph allows to define custom node and edge types.
Although alice is printed two times, it only exists as one and the same value in your example. In general, you would introduce perhaps an id field that carries a unique identifier if you want to trace the mutation of an otherwise immutable object. But here, clearly, you only have one value.
For recursive references, see this question. For example, you could use a by-name parameter.
When modelling some application domain using immutable data structures, you should not use object identity to rely on anything. Just think about how you would update an immutable model: you would generate a modified copy which would have different identity, even if it represents the same "thing". How would you ensure, that you've set all references in your model to the new, modified copy?
Thus, you have to make identity explicit: ask yourself what is the identity of something, e.g. a unique id or a set of unique attributes, e.g. for a person name, date and location of birth an so on. (Be careful though, while the real date of birth of a person never changes, the one stored in your date model might because of an error in your data set).
Then use this information to point to an object from everywhere else.
Making identity explicit requires you to think about it when you build your data model. This might feel like an extra burden but in fact it avoid a lot of trouble later on.
For example, serialization will be easy, distribution will be easy, adding some kind of versioning support will be easy and so on.
As a rule you should only use references to the same information, if this information is just the same by coincidence. If you are pointing to the same "identity" and the information at both places has to be the same, use some explicit id.
I have table name Transaction in the DB. I want to have 2 subclasses TransactionA and TransactionB. I've made it as described here: http://www.robbagby.com/entity-framework/entity-framework-modeling-table-per-hierarchy-inheritance/comment-page-1/#comment-607
The problem is I need to use the field that is discriminator here (see the example, it's PersonCategory there). But it has to be deleted after that I cannot use it.
How to solve this problem?
Thanks
If it is a discriminator its only usage is to map record to either TransactionA or TransactionB. It cannot be set in the application. It is set if you insert TransactionA instance or TransactionB instance and record. It also cannot be updated because object of one type cannot change to object of other type - if you need such logic you cannot model it as inheritance.
Yes it is used as a EF helper to identify type of the specific type of the object. One disadvantage is that approach is every field should be a nullable field and tables are not normalized. However, no joins are involved hence, it is fast approach. Table per type is relatively good approach you have two classes TransactionA and TransactionB with generic class called Transaction.Although, you have to do join as a result of that, performance is not that great compair to earlier approach.
Is there better way rather than to fetch with predicate and see the number of results in order to check that the attribute exists when adding it into managed context? I'm trying to make an attribute unique for given entity...
I think you may have scrambled your nomenclature. You don't add attributes to context. You add managed objects which are defined by entities which have attributes. You could be asking about two different types of test.
If you're asking whether a means exist of testing if a managed object already exist with the exact same attributes of the one you planning on inserting, the answer is no. Since entities can be arbitrarily complex and since it takes only literally one bit different to make them logically distinct, there is no means of testing whether two objects are logically identical i.e. have the same attributes and relationships, without fetching them and testing them.
If you're asking whether you can test for a unique value of an attribute of a particular entity then you can. First you fetch on a property using [NSFetchRequest setProperty:] and then set you're predicate for the sought value. When walking relationships, you can use the Set and Array Operators to find managed objects with unique values.