Design dilemma with relation between entities and ‘global’

  softwareengineering

I have the following dilemma with designing a piece of software.

  1. How can I design a relation between the follwing entities so that a configuration rule can be global or apply to a building / room or a combination of buildings / rooms?
  2. How should the result data

I think I should use the following entities:

ConfigurationRule {
    id: number; 
    key: string;
    value: any;
}

Global: {
    building: Building[]; 
}

Building: {
    id: number; 
    name: string;
    rooms: Room[];
    stories: number;
    builddate: date:
}

Room: {
    id: number; 
    name: string;
    dimensions: {
        height: number;
        width: number;
        depth: number;
    }
}

We have the following requirements:

  • a building consists of many rooms (one-to-many)
  • a configuration rule may be applied to one or more buildings (one-to-many)
  • a configuration rule may be global and will apply to all buildings and rooms in the building
  • a building configuration rule overrules a global rule
  • a room configuration rule overrules a building rule

Sample data

configurationRules = [  
    { id: 1, key: 'hasPower', value: "220Volts" }  
    { id: 2, key: 'hasInternet', value: false },  
    { id: 3, key: 'hasInternet', value: 'fiber' },  
    { id: 4, key: 'hasInternet', value: 'dsl' },  
    { id: 5, key: 'hasInternet', value: 'sattelite' },  
    { id: 6, key: 'plotter', value: true },  
]

Buildings = [  
    { id: 1, name: 'Location A' },  
    { id: 2, name: 'Location B' },  
    { id: 3, name: 'Location C' },
    { id: 4, name: 'Location D' }
]

Rooms = [  
    { id: 1, name: 'Room A1' },  
    { id: 2, name: 'Room A2' },  
    { id: 3, name: 'Room A3' },  
    { id: 4, name: 'Room A4' },  
    { id: 5, name: 'Room B1' },  
    { id: 6, name: 'Room B2' },  
    { id: 7, name: 'Room C1' },  
    { id: 8, name: 'Room C2' },  
    { id: 9, name: 'Room C3' },  
    { id: 10, name: 'Room C4' },  
    { id: 11, name: 'Room C5' },  
]   { id: 12, name: 'Room D1' },  
]

Sample relations:

  • configuration rule 1 should be global and apply to all rooms in all buildings
  • configuration rule 2 should be global and apply to all rooms in all buildings
  • configuration rule 3 should be applied to building A & B and thereby to all rooms in these buildings
  • configuration rule 4 should apply to only building C
  • configuration rule 5 should apply to only room C3
  • configuration rule 6 should apply to only room D1

So that following function can be executed with:
configRuleByIdAppliesTo(1) => return a result for global
configRuleByNameAppliesTo(‘hasInternet’) => return a result for the config rules 2, 3 and 4 with the applied config rules.
getConfigRulesForBuilding({ id: 2, name: ‘Location B’ }) => return a result for with config for the building and rooms.

2

Forget about the types. You only have one hierarchical type. lets call it Room

Room
{
  Id //use a guid
  parentId //null = its the world
} 

configurationRoomMapping
{
  ConfigurationId
  RoomId
}

Now if you want to find out if a rule applies to particular room you just check the mapping for the room and then loop up that rooms parents checking each in turn, building the list of configurations as you go.

9

Solution

I finally went with the following solution (extending on @Ewan answer).

This gives me, imho flexibility to add new levels and types without much hustle. Without opening the classes for modifications, I just need to add a class for the new type.

Location {
    id: number;
    parentId: number | null;
}

Global {
    location: Location; 
}

Building {
    id: number; 
    location: Location; 
    name: string;
    stories: number;
    builddate: date:
}

Room {
    id: number; 
    location: Location; 
    name: string;
    dimensions: {
        height: number;
        width: number;
        depth: number;
    }
}

ConfigurationRule {
    id: number; 
    key: string;
    value: any;
}

ConfigurationLocationMapping {
  configurationId: number;
  locationId: number;
}

Please let me know what you think of this solution?

1

LEAVE A COMMENT