According to the docs ObjectIdentifier is:
A unique identifier for a class instance or metatype.
Is this uniqueness guaranteed to apply to only existing (i.e. not disposed of) objects? Or does extend through the whole application lifetime (i.e. no matter how long the app runs and how many objects it creates/destroys there will be never a collision)? Obviously, I suspect the former, but would like to get some confirmation. (E.g. it seems that the implementation is that ObjectIdentifier is somehow derived from the address of an object in memory.)
The use case is that I consider to use ObjectIdentifier for hashValue for the Set of weak objects, but if there is a possible collision of ids for existing and already destroyed objects then that won't work.
Related
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.
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 need to send an object (NSManagedObject (NSMO) subclass) up to a web service and retrieve it later. I was hoping I could somehow serialise it, but I'm hoping not to have to jump through the encoding hoops.
I can convert a simple NSMO object into a dictionary using:
[instance dictionaryWithValuesForKeys:instance.entity.attributesByName.allKeys];
However, my NSMO is a number of levels deep in terms of relationships to other NSMOs. What would be the best way to create a full serialised version of the object?
If you want to do this in a general way, you could write a recursive method serializedDictionary (either in a subclass of NSManagedObject or in a category) which:
Creates an empty NSMutableDictionary.
For each property, adds the key and value to the dictionary.
For each relationship, adds the relationship name as key and then calls serializedDictionary on the object and adds that as the value. If it's a to-many relationship, you'll have to put those values in an NSArray.
Note that if it's at all possible for a child object to be related back up to a parent (which is very possible if you have inverse relationships like Core Data recommends) you will either need to whitelist the relationships you save (easier) or pass along a set to keep track of which objects have already been serialized, so you don't encode them again (harder, I don't recommend this).
GWT-RPC requires that transfer objects to be serialized must have a default (zero-argument) constructor. Similarly, final fields will not be serialized (see issue 1054).
On the other hand, I know I am supposed to "minimize mutability". My tendency is to want my TOs to be immutable, with final fields, no default constructor, and no mutators.
How can I use GWT-RPC while respecting the immutable paradigm as much as possible. Do I have to convert to a mutable object to marshall, and then back to an immutable one? Is this even worthwhile?
Item 13 in Effective Java (item 15 in second edition) gives strategies on how to minimize mutability or to favor immutability.
Suppose we remove mutators but retain non-final fields and a default constructor. The effect will be a theoretically mutable object, but a practically immutable one. Yes, one could mutate the object via reflection with a bit of effort, but by simply closing off the exposed methods we can at least discourage mutating it in cases like this where it's impractical to make the object truly immutable.
Apple's document says if I override isEqual: then I have to override hash to make sure the hash value should be same for two objects that are consider to be equal by isEqual:
Then I read the docs about hash and below is part of it:
Therefore, either the hash method must not rely on any of the object’s internal state information or you must make sure the object’s internal state information does not change while the object is in the collection.
My customize class MyClass have few of members which are int and bool and NSArray which contains number of MyClass and I want two instance of MyClass to be equal if all of the members are equal.
I have no problem with how to override isEqual: but for hash.
Of my understanding, hash should calculate the hash value by combine the members' hash value using bit operation such as XOR or rotational shift.
The problem is how to implement hash in a such way that meets the Apple's requirement that mention at above. Docs says that the hash value should not rely be the internal state(which is the members) but I found I have to use them to compute the value.
Or even do I really need to implement it? Because I sure I will not use this class as a key for NSDictionary and this is the only way I know where hash is used. Are there any other places where hash is used and I should care about it?
There's two options - either don't rely on the internal state, or ensure that the internal state doesn't change while the object is in a collection.
The second option will allow you to rely on the internal state to generate the hash, but your object must be immutable when in a collection, so that changing it doesn't change its hash.
Collections in Cocoa rely on the hash of an object to perform methods such as containsObject:.
If your object implements a hash that relies on its internal state, is inserted into a collection and then changed, its hash will change, and the collection will lose track of the object.