Thank youDJaggerProvide translation
In Domain Driven Design [1], the distinction between entity and value is reflected. Each entity has a unique identity, and the value is determined by its attributes.
NSFileHandle is an example of an entity: it encapsulates a file descriptor. If we want to know whether two objects of type NSFileHandle are the same, we can check whether they refer to the same object. Handles to files have a lifetime and change over time. If we have two different file handles with different file descriptors, they should be treated differently, even if other attributes are the same, and the file descriptors should be closed separately.
NSURL, for example, is a value — an immutable object that is identified by attributes. Two NSURL objects are the same if they represent the same URL. Urls are fixed and do not change over time.
When choosing between an entity and a value, one of the most important questions is: * “Does it need to be identified?” * In the case of file handles, the answer is yes, we need to manage the life cycle of each file handle separately. In the case of urls, we care if they represent the same URL and not the same reference.
In almost any program, there are many entities that play important roles. File descriptors, notification centers, network interfaces, database records, input devices, applications, and ccache are entities because they have their own life cycles and unique identities.
Values also have many uses in software. Urls, binary data, dates, errors, strings, notifications, and numbers define only their properties, which do not change over time. Code that uses immutable values is easier to understand. Immutability directly ensures that they are thread-safe: anything that is immutable is safe when shared between threads.
When we need to distinguish between values and references, the domain of application is one of the deciding factors. For example, in an application that displays contact information, an address should be defined as a value type whose identity is its value. If there are many contacts sharing the same address, we don’t want to change the address of one person while changing the address of others. In ride-sharing applications, however, addresses should be represented by entities: if multiple people share an address, we want them to share a car.
When defining a new type in Swift, we can choose among structs, enumerations, and classes. Classes are best suited to entities in most cases: classes are mutable by default, and instances of classes change their state over time.
When using value types, structs are usually best suited. We can force structures to be immutable through the compiler. In other words, the compiler can guarantee that our types have value semantics. In some cases, classes may also be the best choice for value types — for example, we need to connect to Objective-C. But then we need to make sure we’re immutable.
When you need to choose between a structure and a class, we recommend that you consider equality. Are instances identical by reference? In other words, are two instances that have the same data considered different? If the answer is yes, classes are a better fit. We can also ask, can we tell if the instance is the same by the data contained? If so, the structure is more suitable.
When docking with Cocoa and Objective-C, we almost always need to use classes. For example, when implementing a table View proxy, we have no choice but to use classes. Many Apple frameworks also rely heavily on subclasses. However, we may still need to design classes with value semantics for problems in different domains. For example, in the Core Image framework, CIImage objects are immutable: they represent an Image that can no longer be changed.
In the remainder of this chapter, we’ll explain how structures and classes behave differently, which will make it easier for you to decide whether to design your type as a class or a structure.
[1] : Domain model-driven design references Richie’s blog