|

C# Relationships Between Classes

C# Relationships Between Classes

In the last several tutorials we have gone through the process of identifying several classes that would facilitate a basic CRM application. During the identification phase, we determine business entities, create properties, and scope out methods. Next we separate responsibilities with the goals of reducing coupling and making the code simpler. Now we reach the phase for establishing relationships between classes. The relationships define how objects work together to perform the work needed for the application to run.


Types of Relationships

There are many types of relationships in object-oriented programming. The first one we will look at is the collaboration relationship. In a collaboration relationship, you often refer to it as a “Uses A” relationship. This is because you can think of one class using another class. The next type of relationship we’ll look at is a composition relationship. A composition relationship can be referred to using a “Has A” relationship type. The idea of composition is that an object can be composed of other objects. An Order has a Customer. An Order also has a OrderItem. The last relationship type we will look at is Inheritance, or a “Is A” relationship. A CommercialCustomer is a Customer or a ConsumerCustomer is a Customer.


Collaboration

Here we have a diagram of a collaboration type relationship between classes. The OrderRepository “uses a” Order object to populate on a Retrieve, and to serialize on a save. The same goes for the CustomerRepository “using a” Customer object and a ProductRepository “using a” Product object.

object-oriented collaboration class relationship

In this code we can see how the CustomerRepository class uses a Customer class. Inside of the Retrieve() method, we see how a new Customer object is created. That object is then populated with data. In our case it is simply hard-coded, but you could imagine this data coming from a database.

The CustomerRepository uses a Customer object once again in the Save() method. In order for that method to do its job, it needs to accept a Customer object as a parameter. Inside that method, the data from the Customer object would be used to persist to the database. The repository classes use an entity class to populate the entity, or serialize the entity depending on if it is being used in the Retrieve() or Save() methods. This pattern holds true for the other repository classes we have been working with as well.

You can spot a collaboration type relationship any time you see a class use an instance of another class to perform an operation in the application.


Composition

Composition is another key relationship type in object-oriented programming. A composition relationship exists when an object from one class, is made up of or composed of one or more objects from another class. It is also known as a “Has A” type relationship. In our CRM application this type of relationship exists between the Customer class and the Address class. A Customer “Has A” Address.

object-oriented composition class relationship

In the diagram above we show some composition relationships. The Customer class “Has A” Address. The Order object is also composed of other objects. Every Order has a Customer, has an Address, and has an OrderItem. Additionally, each OrderItem “Has A” Product. So we can kind of see how a given object can be composed of other objects to make the application work.


Composition With References

The Composition relationship can be accomplished using references in our code, which leverage class properties. Let’s have a look at the Customer class to see how this works. First we’ll look at the composition relationship between the Customer class and Address class. In the below code, we have highlighted a specific property. The Customer object is composed of one or more Address objects. Why one or more? Because there could be a home address or a work address. So we use a property of type List to allow for one or more Address objects to help compose a Customer object. A property declaration in the Customer class establishes the composition relationship between the Customer class and the Address class. Also note that since this property is a List, it must be initialized in the constructor like we also see below. If it is not, it would cause a null value exception.

The key takeaway is that in composition style relationships, an object from one class is constructed from objects of another class. In this case the construction of a Customer object constructs a List of Address objects. Often times Composition is preferred over Inheritance.


Populating the Referenced Objects

To populate the Customer object with data, we need some code to do the work of retrieving that data. This would best be placed in an AddressRepository class. It will be used to get one or more addresses for a Customer. Just like the other repository classes in this CRM application, the AddressRepository class has a Retrieve() and a Save() method.

Interestingly, what we can do now is to set up a collaborative relationship between the CustomerRepository and AddressRepository classes. To display the dependency on the AddressRepository in CustomerRepository, we define the relationship at the top of the class and create an instance in the constructor. Additionally, the private property addressRepository now holds an AddressRepository object. The Retrieve() method is now updated to use the RetrieveByCustomerId() method that exists in the AddressRepository. That code is highlighted here.

So what is the purpose of this code then? Well now, when any code requests to Retrieve a Customer, it will now retrieve a Customer and its associated Addresses in one swoop.


Composition With Ids

A Composition type relationship is also accomplished by using id’s rather than a property of a class. Using id’s instead of object properties for composition has several benefits. Coupling is minimized as direct references are removed. You can think of these as simple id relationships. In the code below, we are highlighting the composition relationship between an Order and the Customer, as well as the composition relationship between the Order and the Address. These relationships are defined with public property integer id’s. Now, when the OrderRepository populates the Order, these property id’s will be populated.

That is great, but we have a problem. Those id’s are just that, simple integer numbers. They do not actually show us any information. The Order won’t have the Customer name or Shipping Address because we only used simple id’s. There is no populated Customer object or Address object. As a result of making the Order class so simple, we now require additional classes to be able to display an Order. We can start with a OrderDisplay class.

This class only contains the properties that are needed to display an order. It does not reference properties of other classes, but rather uses its own for the order information. There is a composition relationship with the OrderDisplayItem class which we’ll look at in a moment. It needs this relationship in order to retain a list of items that are associated with an Order. The OrderDisplayItem class is shown below. It contains only the properties that are needed to display the order items on the order.

How is this code used? By adding a new method to the OrderRepository class. Note the highlighted code that shows the RetrieveOrderDisplay() method. Inside the method the code is set up to retrieve the OrderDisplay, and the OrderDisplayItem information.


Inheritance

In object oriented programming we also have the Inheritance style of relationship. In Inheritance you have an “Is A” type of relationship. Inheritance allow you to build a class that inherits the members of its parent or base class. This allows you to define a more specific type of class. So consider the Customer class. We might have Business customers and Education customers. They are both customers, but different kinds of customers. This allows for code reuse since child classes that inherit members from their parent class, are using the properties and methods already defined in the parent class.

object oriented inheritance relationship

When using inheritance in C#, you can only directly inherit from one class. You can however set up inheritance chains if you like. In other words you could have a Customer class, and an Education class that inherits from Customer. Then, you could set up a College class, that inherits from the Education class.


C# Relationships Between Classes Summary

In this tutorial we had a look at Relationships between classes in a C# application. We saw that a Collaboration relationship is commonly referred to as a “Uses A” relationship. Classes with a Collaboration relationship use an instance of the needed Class and call its properties or use its methods. The OrderRepository Class uses an instance of the Order Class when retrieving or saving an Order as seen in this code here.

In addition, the AddressRepository Class uses an instance of the Address Class when retrieving or saving an Address. The CustomerRepository Class uses an instance of the Customer Class when retrieving or saving a Customer. So you can see how this type of relationship works.

We also had a look at Composition relationships which use the “Has A” convention. Composition relationships can be set up one of two ways. The first is by defining a property in one Class that references a different Class. In the Customer Class we defined a List of Addresses. This is really a List of Address objects. The AddressList property defines the Composition relationship between the Customer Class and the Address Class.

The second way to establish a Composition relationship is by using ids. An example of this is when we added a customer id and an address it to the Order class. Since these classes are just using ids instead of object references it is easier to retrieve and save Order data. With this approach you might need to add additional classes to get full functionality such as being able to display an Order. Finally, we had just a quick look at Inheritance in object oriented programming which sets up the “Is A” convention.