At the end of Part 2 I had barely working tests for the core logic of the kata.

Referring back to the original Birthday Greetings Kata, it’s clear that Employees know about more than just their birth date.

So, let’s get populating those extra fields.

Object subclass: Employee [
  <comment: 'I represent an Employee in the Kata.'>
  <category: 'BirthdayKata'>
  | birthDate firstName lastName email |

Expanding the set of instance variables is the first stage…

Updating the initialization

Employee class >> newBirthdate: aDate firstName: aFirstname lastName: aLastname email: anEmail [
  "Answer a new instance of the receiver."
  <category: 'basic'>
  ^self basicNew initBirthdate: aDate firstName: aFirstname lastName: aLastname email: anEmail
]

initBirthdate: aDate firstName: aFirstname lastName: aLastname email: anEmail [
  "Initialize the receiver."
  <category: 'private-initialization'>
  birthDate := aDate.
  firstName := aFirstname.
  lastName := aLastname.
  email := anEmail.
]

This simplifies the construction of the Employee class a bit.

Refactoring the tests

There was a bit of repetition in the instantiation of the Employee in the tests, this can easily be refactored to a factory method.

testIsBirthdayWhenDateIsBirthday [
    <category: 'tests'>
    | e today birthDate |
    birthDate := Date newDay: 14 month: #Feb year: 1990.
    today := Date newDay: 14 month: #Feb year: 2019.

    e := self newEmployee: birthDate.

    self assert: (e isBirthday: today)
]

newEmployee: aBirthdate [
  ^Employee newBirthdate: aBirthdate firstName: 'John' lastName: 'Smith' email: 'john@example.com'.
]

Updating the console representation

With the new fields, I need to update the printOn: method:

printOn: stream [
  <category: 'printing'>
  super printOn: stream.
  stream nextPutAll: ' ';
         nextPutAll: firstName;
         nextPutAll: ' ';
         nextPutAll: lastName;
         nextPutAll: ' born on ';
         print: birthDate;
         nextPutAll: ' with email ';
         nextPutAll: email
]

There’s some subtlety going on here, nextPutAll: iterates over the things that it’s putting on to the stream, for strings, that’s fine, they are series of characters, but for birthDate it’s not so simple, it’s not a string, by calling print: on the stream, with the birthDate, it delegates to printOn: from the Date class, and provides the stream, this makes the birthDate display itself in a nice human-readable mannner.

$ gst
GNU Smalltalk ready

st> FileStream fileIn: 'Employee.st'.
FileStream
st> birthDate:= Date newDay: 26 month: #Jul year: 1956.
26-Jul-1956.
st> Employee newBirthdate: birthDate firstName: 'John' lastName: 'Smith' email: 'john@example.com'.
an Employee John Smith born on 26-Jul-1956 with email john@example.com

Why not use print: on all lines?

The message print: is used to provide a printable represententation, which for strings means that they come out with ' wrapped around them, which we don’t want for the other parts.

Compare:

an Employee' ''John'' ''Smith'' born on '26-Jul-1956' with email ''john@example.com'

Next: reading and parsing Employees from the sample CSV data file.