3

I'm trying to write an Entity-Component System and I want to have different factories creating different kinds of entities. For example the HumanEntityFactory class will create human entities.

Would it break separation of concerns if I store the different types of human that the factory can create, or should I create a factory for each kind of human?

HumanEntityFactory
===========
-HashMap<String, Component[]> humanEntityTypeComponents

+addHumanType(String typeName, Component[] components)

+createHuman(String type)
Entity
======
-HashMap<String, Component> components
10
  • 1
    It's unclear from your question whether "human type" is an entity in its own right, or whether it is merely a property of "human." Also, Separation of Concerns doesn't mean what you think it means. Dec 3, 2017 at 17:58
  • "human type" are common properties for different kinds of human, for example the maximum speed of human child might be A, whereas the maximum speed of a HumanSprinter might be B. Dec 3, 2017 at 18:01
  • 1
    If you're using a factory for storage you haven't built a factory. You've built a repository. Factories make things. Dec 3, 2017 at 21:16
  • It also creates the humans of the certain types... Does this violate SRP? Dec 3, 2017 at 21:20
  • SRP doesn't mean what you think it means either. Dec 3, 2017 at 23:25

1 Answer 1

2

First, it is important to make a difference between Single Responsibility Principle (SRP, related to Clean Code) and Separation of Concerns (SOC, related to engineering at large).

Analyse of your design

The Entity-Component-System has the purpose of avoiding a rigid compile-time class hierarchy by using a flexible data structure based on a flat Entity type enriched through run-time composition with components.

I understand that:

  • your HumanEntityFactory creates human Entities of different kind, each kind being characterized by a different set of default Components.
  • in order to keep the system flexible, you define at run-time the standard components to use for each kind of human (e.g. addHumanType("Warrior", { new Sword(), new WarriorRenderer() }) )
  • then a new human is instantiated by the factory with the method createHuman() (e.g. createHuman("Warrior"), createHuman("Magician") and so on). I'll assume that the standard components are cloned, in case they have a state (e.g. defensivePower, offensivePower, depreciation).

Single responsibility

The name of this principle is somewhat misleading. So let's look at R.C.Martin's own explanations: SRP is about reasons to change, which are in general related to people responsibilities.

What are the possible changes that may require a change of the factory ?

  • change of the Entity interface. That's natural because we factor Entities.
  • change the Component creation logic. Someone may for example change the way the Components are created, moving from cloning to a factory.
  • change of the way the kinds of humans are managed, together with their component "templates".

I see here 3 different reasons for change, so no, it's not compliant with the SRP.

Note that having more "templates", i.e. more kinds of humans, will not require any changes to the factory class. So this is not relevant for SRP.

Separation of concerns

The separation of concerns is about modularity and decoupling. Your factory class seems to addresses two distinct concerns:

  • First, it manages the human types (via the method addHumanType() and the property humanEntityTypeComponents).
  • Then, it creates a new Entity according to the configuration

The first concern, is something that is related to the configuration. You certainly do this during the initialization, and probably it's the consequence of loading some configuration file. The second concern is unrelated.

So this design does not respect the separation of concerns either.

Way forward

The first thing would be to have a class managing the configuration of human entities.

The second thing would be to have a generator class, that generates a list of components for a given kind, based on the configuration.

The entity factory could then be instantiated by injecting the configuration and the generator,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.