Warmup: understanding the Money classes

In this exercise we explore the various Money classes, and see how examples are used to cover the features of these classes. We will need these classes next to model Prices.

To simplify the Price modeling exercise somewhat, we assume that we already have classes to model money in different currencies.

An amount of money can be created by sending a currency type to a number, for example:

42 euros.
  

#euros is just a factory method that constructs an instance of GtTCurrencyMoney GtTMoney << #GtTCurrencyMoney slots: { #amount . #currency }; tag: 'Model'; package: 'GToolkit-Tutorial-Prices' with euros as the currency, like this:

GtTCurrencyMoney new
	amount: 42;
	currency: GtTCurrency euros.
  

Task: Have a closer look at the method Number>>#euros euros ^ GtTCurrencyMoney new amount: self; currency: GtTCurrency euros . See that its category is “*GToolkit-Tutorial-Prices”.

NB: The “category” of a method can be found in the first of two buttons at the bottom right of the method Coder window. The other button distinguishes instance methods from class methods.

Categories starting with * are extension methods that are defined in a different package from the class. In this case the package GToolkit-Tutorial-Prices extends the Number Magnitude << #Number slots: {}; tag: 'Numbers'; package: 'Kernel' class with the euros method, without touching its original Kernel package.

This particular example is also an example method : GtTMoneyExamples>>#fortyTwoEuros fortyTwoEuros <gtExample> <return: #GtTCurrencyMoney> | money | money := 42 euros. self assert: money isZero not. self assert: money equals: 42 euros. ^ money

An example is any unary method that has the <gtExample> pragma, and returns an object. Examples also serve as tests, as we can see with the assertions above. Finally, we can inspect and explore examples.

Task: Inspect the fortyTwoEuros example by clicking on the Play and Inspect Example button. (Black triangle + i.)

See that the result has a dedicated Details view. See how the view is implemented by ALT-clicking on the Details label. Don't worry too much about the details of the implementation for now, but note that it is just a few lines of code.

Open a contextual playground at the bottom of the inspector on the fortyTwoEuros instance (pull up the handle with the two grey bars) and evaluate (inspect) self isZero. Click on the grey triangle next to isZero to open the code bubble and see how it is implemented.

Note that this example is an instance of a GtTCurrencyMoney GtTMoney << #GtTCurrencyMoney slots: { #amount . #currency }; tag: 'Model'; package: 'GToolkit-Tutorial-Prices' , but the example is defined in the classs GtTMoneyExamples Object << #GtTMoneyExamples slots: {}; tag: 'Examples'; package: 'GToolkit-Tutorial-Prices' . It is common practice to defined examples in a separate class from the class that they exemplify, just like unit tests for a class X will be defined in a separate class TestX. In this case there is a hierarchy of Money classes with GtTMoney Object << #GtTMoney slots: {}; tag: 'Model'; package: 'GToolkit-Tutorial-Prices' at the root, and we put all the examples in GtTMoneyExamples Object << #GtTMoneyExamples slots: {}; tag: 'Examples'; package: 'GToolkit-Tutorial-Prices' .

A GtTCurrency Object << #GtTCurrency slots: { #name }; sharedVariables: { #Currencies }; tag: 'Model'; package: 'GToolkit-Tutorial-Prices' represents a specific sum of money in a given currency. Its superclass is GtTMoney Object << #GtTMoney slots: {}; tag: 'Model'; package: 'GToolkit-Tutorial-Prices' , which is the abstract root of the Money hierarchy.

NB: The UML diagram below is live. Click on the classes to browse them.

A GtTMoneyBag GtTMoney << #GtTMoneyBag slots: { #monies }; tag: 'Model'; package: 'GToolkit-Tutorial-Prices' represents a bag of money in multiple currencies, for example:

bagWithEurosAndDollars
	<gtExample>
	<return: #GtTMoneyBag>
	| bag |
	bag := self fortyTwoEuros + self fortyTwoDollars.
	self assert: (bag isKindOf: GtTMoneyBag).
	self assert: bag monies size equals: 2.
	^ bag
    

Task: Inspect the example above and evaluate self - 42 usd. What is the class of the result? Is it GtTCurrencyMoney GtTMoney << #GtTCurrencyMoney slots: { #amount . #currency }; tag: 'Model'; package: 'GToolkit-Tutorial-Prices' or GtTMoneyBag GtTMoney << #GtTMoneyBag slots: { #monies }; tag: 'Model'; package: 'GToolkit-Tutorial-Prices' ? Can you explain the result? In which method is the class of the result determined?

Task: Explore GtTMoneyExamples Object << #GtTMoneyExamples slots: {}; tag: 'Examples'; package: 'GToolkit-Tutorial-Prices' . Can you find an example that tests this scenario in which we remove the euros from a money bag with euros and dollars?

Task: Are there examples for GtTZeroMoney GtTMoney << #GtTZeroMoney slots: {}; tag: 'Model'; package: 'GToolkit-Tutorial-Prices' ? What is it used for?

Hint: Browse the GtTZeroMoney GtTMoney << #GtTZeroMoney slots: {}; tag: 'Model'; package: 'GToolkit-Tutorial-Prices' class and explore the References tab. Then look for Senders to see where these methods are used.