Form pairs and discuss how you can refactor the code below. Make notes on the different steps you would take to do this in a safe way.
For safety, we need to make sure we don't exceed the maximum occupancy in any zone of the building.
We've installed cameras pointed at all the entrances of each zone of the building. The cameras can count people coming in and going out. We can query this data using the cameras' API. We calculate the occupancy of each zone and show it on a monitor in the security's control room.
Some questions you can ask yourselves:
- Can we epxress the domain language better? What domain concepts are hidden or implicit?
- Are there any (DDD) design patterns we can use? Can we make use of immutability? Are there opportunities for introducing better abstractions?
- How can we test this code (or make it more testable)?
- Can we isolate side effects? Can we introduce Hexagonal Architecture (aka Ports & Adapters)?
- Rewrite this in a FP language (or using FP style in an OOP language).
- Find opportunities to use monoids, map/fold/filter/...
\pagebreak
+ main()
httpClient = new HttpClient()
lobby = new Zone('South Auditorium',
[ new Counter(httpClient, 'Camera1', '192.168.55.130')
, new Counter(httpClient, 'Camera2', '192.168.55.131')
, new Counter(httpClient, 'Camera3', '192.168.55.132')
, new Counter(httpClient, 'Camera4', '192.168.55.133')
, new Counter(httpClient, 'Camera5', '192.168.55.134')
])
repeat
lobby.update()
print "Lobby: {lobby.occupancy()}"
sleep(1)
endrepeat
\pagebreak
class Counter
- ip
- name
- total_in = 0
- total_out = 0
- friendly_name = ""
- last_update
- serial
- httpClient
+ constructor(httpClient, ip, name)
this.httpClient = httpClient
this.ip = ip
this.name = name
update()
+ update()
try
data = httpClient.get("http://{ip}/people-counter/api/live.json")
total_in = data['in']
total_out = data['out']
friendly_name = data['name']
last_update = data['timestamp']
serial = data['serial']
catch (Exception e)
friendly_name = "error connecting to {name}"
+ totalIn()
return total_in
+ totalOut()
return total_out
+ friendlyName()
return friendly_name
\pagebreak
class Zone
name
counters = []
totalIn = 0
totalOut = 0
occupancy = 0
constructor(name, counters)
{
this.name = name
this.counters = counters
this.update()
}
+ update()
totalIn = 0
totalOut = 0
for (counter in counters)
update()
totalIn += counter.totalIn()
totalOut += counter.totalOut()
}
occupancy = totalIn - totalOut
}
+ counters()
return counters
+ totalIn()
return totalIn
+ totalOut()
return totalOut
+ occupancy()
return occupancy
(c) Mathias Verraes verraes.net