The purpose of this method is to find out where a
sighting occurred. Due to inheritance, however, the
effective location may live in the Sighting instance, or in its parent BirdForm, or
it may be the default locality for the day, which resides
in the related DaySummary.
While working on an earlier version of this module, the
author became embroiled in an interesting discussion
involving the Law of
Demeter. Consider the case where a sighting
does not define a location code, so that it inherits its
location code from the DaySummary. How
are we to find out the day's default location?
In the original version (with different names), this ugly code I wrote drew fire from colleagues:
locCode = None
if self.locGroup is not None:
locCode = self.locGroup.locCode
if locCode is None:
if self.birdForm.locGroup is not None:
locCode = self.birdForm.locGroup.locCode
if locCode is None:
locCode = self.birdForm.dayNotes.daySummary.defaultLoc
That is, if the sighting defines a location code,
use that; if not, and the parent form
defines a location code, use that; otherwise, go up to the
form element's parent day-notes, then down to that element's
day-summary, and dig out the default
location code.
However, this violates the Law of Demeter, which in the succinct form quoted in the Wikipedia article above, says “Only talk to your immediate friends.” Dr. Allan Stavely suggested a much cleaner approach:
If the Sighting instance defines a
location, use that.
If the Sighting has no location code, ask the
parent BirdForm instance what location code
it uses. In this code, that uses the BirdForm.getLocGroup() method.
The BirdForm.getLocGroup() method uses its
own .locGroup value if there is one; if
not, it interrogates the parent DayNotes.defaultLoc() method for the
default location.
The DayNotes.defaultLoc() function is
a pass-through that interrogates its daySummary.defaultLoc() method.
The payoff here is that the Sighting
element does not need to know anything about the
internals of two classes that are not its immediate
neighbors: DayNotes and DaySummary.
# - - - S i g h t i n g . g e t L o c G r o u p
def getLocGroup(self):
"""Find self's effective location.
"""
First we ask the parent BirdForm instance for a
LocGroup that describes the locality from which
we may inherit. See Section 12.6, “BirdForm.getLocGroup(): Find the
effective locality”.
#-- 1 --
# [ parentGroup := a LocGroup representing the
# effective locality of self.birdForm ]
parentGroup = self.birdForm.getLocGroup()
If self.locGroup is None,
we'll just return the parent locality. Otherwise we use
inheritance to form the sighting's effective locality;
see Section 14.3, “LocGroup.inherit(): Implement
inheritance for locations”.
#-- 2 --
# [ if self.locGroup is None ->
# return parentGroup
# else ->
# return a new LocGroup made from self.locGroup,
# inheriting from parentGroup ]
if self.locGroup is None:
return parentGroup
else:
return self.locGroup.inherit(parentGroup)