Composition of Methods - Gnorion/BizVR GitHub Wiki

Composition of Methods Example

Sample Business Problem

Is the average weight of the five lowest income people over age 21 greater than 200lbs?

Approach 1 Applying Methods In Separate Steps

Apply the methods in separate steps, creating intermediate objects for each component of the problem

Expression Description
C1 ={p in Persons where age>21} unordered collection (bag) of persons each of which has age > 21
L1=C1.sortedBy(income) creates a list sorted by age in ascending order
L2=L1.first(5) creates a list containing the first 5 persons in L1
N1=L2.weight.avg sets N1 to the average weight of the 5 persons in L2
B1=N1>200 B1 is true if avg weight>200, otherwise its false

image

DISCUSSION POINT: Is this a copy of the data elements, or a list of pointers to the originals?

Approach 2

The same things can be done in a single expression by concatenating the methods and without the need for all the intermediate lists.

While this results in a more concise expression it can be a bit harder to comprehend.

B1={p in Persons where age>21}.sortedBy(income}.first(5).weight.avg>200 image

Because we are not creating lots of intermediate variables (C1,L1,L2):

  • This has fewer side effects. No left over variables to cleanup.
  • It also takes less memory, particularly if the collection is large
  • It allows for more flexibility in the underlying implementation of the methods (instead of actually copying the data elements we could simply keep a reference to it. This is particularly useful if the data elements themselves might be large structures such as json objects. This way we only ever need to keep a single copy of the original data)

We can interpret the expression by reading from left to right:

  1. First a collection of Persons over 21 is created.
  2. Then the .sortedBy(income) method is applied to that collection to produce an ordered list (sequence)
  3. Then the .first(5) method is applied to that list to create a list of just five elements
  4. The the weight attribute of those five is processed by the .avg method to produce a single number as the result.
  5. This number is compared with 200 resulting in a boolean True or False

Approach 3

We can go one step further and define a composed method comprising a sequence or chain of methods, the output of one being the input to the next

define method {Persons}:avgWeightFivePoorest = sortedBy(income).first(5).weight.avg

Now we can say

B1={p in Persons where p.age>21}.avgWeightFivePoorest>200

image

Approach 4

We could also express it in two steps like this

C1 ={p in Persons where p.age>21}
B1=C1.avgWeightFivePoorest>200

This would be appropriate if the collection C1 was going to be processed by other functions or methods such as this image

  • B2=C1.sortedBy(age).first(5).height.max>80 Is the maximum height of the five youngest persons over 21 greater than 80?
  • B3=C1.sortedBy(age).last(5).forAll(gender='male') Are the oldest five persons over 21 all male?
  • B4=C1.select(gender='male',state='CA').size>50 Are there more than 50 male persons in CA over 21?