Joris Eijmberts

Turning crazy ideas into games!

CP Social SOLID

CP Social is build on the SOLID principles, SOLID is a set of design principles that can help creating maintainable, understandable and flexible software

“Design principles encourage us to create more maintainable, understandable, and flexible software”

The S.O.L.I.D. acronym stand for the following 5 concepts:

  1. Single Responsibility
  2. Open/Closed
  3. Liskov Substitution
  4. Interface Segregation
  5. Dependency Inversion

Here is the entire paper on the software design principles by Robert C. Martin.

Single Responsibility

To achieve the single responsibility concept CP Social is split into 3 different services:

  1. Achievement service
  2. Authentication service
  3. Cloudsave service

As an example I’ll show how one if these services is again split up into multiple smaller services that all handle on a single functionality within the service.

Below is an image of the Achievement service, this service manages the retrieving, incrementing and unlocking of achievements.

ICP_Achievement service

In the image you can see the ICP_Achievement service interface at the top, this interface implements 3 other interfaces that all have a single responsibility to perform. The ICP_Achievement service is only used to access the implementation of the other 3 interfaces.

Open/Closed

The open closed principle simply put describes that classes should be open for extension, but closed for modification. By doing this you prevent yourself from writing new code that already exists and works.

In CP Social an example of this principle is the way results are created, the class diagrams below show the structure of the ‘Result’ classes in CP Social

In CP Social a ‘Result’ has to inherit either ‘CP_ParamResult’ or a ‘CP_Result’, these abstract base classes include the code to return a valid and correctly structure result when creating them via the ‘Success()’ or ‘Error()’ methods.

When a new result needs to be implemented the only thing that has to be done to create a new result class that describes the return values of the result via the Type parameters to the base class

Liskov Substitution

The Liskov Substitution describes a princible where if class A is a subtype of class B, then we should be able to replace with without disrupting the behavior of our program.

For an example in CP Social we’ll take a look at the CloudSave results.

Cloud save results Class diagram

In the class diagram shown above you can see an interface called ICP_SaveGameMetaData, this interface provides to application with some information about a save game stored in the cloud. Seen as CP Social can run on 4 different platforms and all these platforms have different ways of handling cloud saving, the ICP_SaveGameMetaData provides an overarching implementation of save game metadata. Using this the implementation can be of different sub classes but the required information for CP Social to run will always be available due to this interface.

Interface Segregation

When talking about the Interface Segregation principle mean that Large interfaces should be split up into smaller interfaces.

An example of this can be seen in the ICP_AchievementService, below are 2 different implementations of the same functionality, but the second uses the Interface Segregation principle

ICP_AchievementService no Interface Segregation
ICP_AchievementService no Interface Segregation

As you can see in the second image the ICP_AchievementService interface is split into 3 different interfaces all with a single responsibility. One for retrieving achievement data, one of unlocking achievements and one for incrementing achievement progress.

Dependency Inversion

The principle of Dependency Inversion refers to the decoupling of software modules. This way, instead of high-level modules depending on low-level modules, both will depend on abstractions.

Dependency inversion in CP Social was a very important one, seen as CP Social had to support 4 different platforms all with their own implementation of the required features. An example of this can be seen in the structure of ICP_Platform.

Note this diagram doesn’t show the Interface Segregation, to keep the diagram as simple as possible

ICP_Platform interface relations

As shown in the pre-processor directive CP Social uses the ICP_Platform interface to get the right implementation per platform. Using Dependency Inversion CP Social is able to perform all tasks without really know what kind of implementation it is running. I just talks to an interface and it get and abstract reprenstation of the expected answer without really know from what platform it came or how it came to exist.

Conclusion

Using the SOLID principles in CP Social made sure I created a more maintainable, understandable, and flexible product. Using these priciple was quite a challenge seen as some of the principles can take a lot longer to realize that using an easier or faster way.

But at the end these principles made sure I didn’t lose sight on how CP Social was build up and worked.