Title: Payroll Case Study
1Section 3
2The Payroll System Initial Requirement
pay employees
correct amount (minus deductions)
Employee Database
Payroll System
on time
method specified
3Payroll Initial Spec
- Pay Type
- Hourly. Some employees work by the hour. Paid
hourly rate. Submit time cards. Paid overtime _at_
1.5 times rate. Paid every Friday. - Salary. Some employees salaried. Paid last
working day of month. - Commission. Some employees also paid commission
based on sales. Submit sales amounts. Paid every
Friday. - Commission rate, salary, hourly rate are part of
employee record. - Pay Method.
- Employees can choose for paychecks to be mailed,
held for pickup, or directly deposited to bank
account. - Deductions.
- Some employees belong to the union. Employee
record has field for weekly dues rate. Must be
deducted from pay. Union may assess service
charges from time to time. These are submitted
by union on weekly basis and must be deducted
from appropriate employees next pay amount. - Other requirements.
- Payroll application will run once each working
day and pay the appropriate employees on that
day. The system will be told to what date the
employees are to be paid, so it will calculate
payments from the last time the employee was paid
up to the specified date.
4Chapter 18
5How to begin?
- Obviously a database is involved. Should we
generate a database schema and some queries? - Common but this generates an application for
which the database is the central concern. - Databases are implementation details!
- Considering the database should be deferred as
long as possible. - Abstraction the amplification of the essential
and the elimination of the irrelevant. The
database is irrelevant at this stage it is
merely a technique used for storing and accessing
data, nothing more.
6Analysis by Use Cases
- Start by considering the behavior of the system.
- Use case similar to a story, but elaborated with
more detail - Stories for this iteration
- Add a new employee
- Delete an employee
- Post a time card
- Post a sales receipt
- Post a union service charge
- Change employee details (e.g., hourly rate, dues
rate) - Run the payroll for today
7Use Case 1 Add New Employee
- A new employee is added by the receipt of an
AddEmp transaction. This transaction contains
the employees name, address, and assigned
employee number. The transaction has 3 forms - AddEmp ltEmpIdgt ltnamegt ltaddressgt H
lthourly-rategt - AddEmp ltEmpIdgt ltnamegt ltaddressgt S
ltmonthly-salarygt - AddEmp ltEmpIdgt ltnamegt ltaddressgt C
ltmonthly-salarygt ltcomm-rategt - The employee record is created with fields
assigned appropriately. - Alternative 1
- An error in the transaction structure.
- If the transaction structure is inappropriate, it
is printed out in an error message and no action
is taken.
8Thinking about the design
- Use case 1 hints at an abstraction
Well look at the COMMAND pattern for this
abstract base class
AddHourly Employee Transaction
AddSalaried Employee Transaction
AddCommissioned Employee Transaction
SRP adhered to each responsibility in its own
class
Dont get sucked into the database yet!!
9OK to think about objects
Employee
Hourly Employee
Salaried Employee
Commissioned Employee
Possible Employee class hierarchy
10Use Case 2 Delete an Employee
- Employees are deleted when a DelEmp transaction
is received. The form of this transaction is as
follows - DelEmp ltEmpIdgt
- When this transaction is received, the
appropriate employee record is deleted. - Alternative 1
- Invalid or unknown EmpID
- If the ltEmpIDgt field is not structured correctly,
or it does not refer to a valid employee record,
then the transaction is printed with an error
message and no other action is taken.
No design insights from this use case, so lets
move on
11Use Case 3 Post Time Card
- On receiving a TimeCard transaction, the system
will create a time-card record and associate it
with the appropriate employee record. - TimeCard ltEmpIdgt ltdategt lthoursgt
- Alternative 1
- The selected employee is not hourly
- The system will print an appropriate error
message and take no further action - Alternative 2
- An error in the transaction structure
- The system will print an appropriate error
message and take no further action
12Design insights
- Some transactions apply only to certain kinds of
employees strengthen case for different
classes. - Indicates association between time cards and
hourly employees.
Hourly Employee
0..
TimeCard
remember aggregation?
13Use Case 4 Posting a Sales Receipt
- Upon receiving the SalesReceipt transaction, the
system will create a new sales-receipt record and
associate it with the appropriate commissioned
employee. - SalesReceipt ltEmpIdgt ltdategt ltamountgt
- Alternative 1
- The selected employee is not commissioned.
- The system will print an appropriate error
message and take no further action. - Alternative 2
- An error in the transaction structure.
- The system will print an appropriate error
message and take no further action.
14Design insights
- This is very similar to use case 3. It implies
the following structure
Commissioned Employee
0..
Sales Receipt
15Use Case 5 Post Union Service Charge
- Upon receiving this transaction, the system will
create a service-charge record and associate it
with the appropriate union member. - ServiceCharge ltmemberIDgt ltamountgt
- Alternative 1
- Poorly formed transaction
- If the transaction is not well formed or if the
ltmemberIDgt does not refer to an existing union
member, then the transaction is printed with an
appropriate error message.
16Design Insights
- Union members are not accessed through employee
IDs. The union maintains its own numbering
scheme. The system must be able to associate
union members and employees. Could be done
various ways, so postpone decision until later.
Just show association for now.
Example of how this differs from waterfall
0..
UnionMember
ServiceCharge
17Use Case 6 Change Employee Details
- Upon receiving this transaction the system will
alter one of the details of the appropriate
employee record. Several possible variations - ChgEmp ltEmpIDgt Name ltnamegt
- ChgEmp ltEmpIDgt Address ltaddressgt
- ChgEmp ltEmpIDgt Hourly lthourlyRategt // Change to
hourly - ChgEmp ltEmpIDgt Salaried ltsalarygt // Change to
salary - ChgEmp ltEmpIDgt Commissioned ltsalarygt ltrategt
- ChgEmp ltEmpIDgt Hold
- ChgEmp ltEmpIDgt Direct ltbankgt ltaccountgt
- ChgEmp ltEmpIDgt Mail ltaddressgt
- ChgEmp ltEmpIDgt Member ltmemberIDgt Dues ltrategt
- ChgEmp ltEmpIDgt NoMember
- Alternative 1
- An error in the transaction structure.
- If the transaction structure is inappropriate, or
ltEmpIDgt does not refer to a real employee, or
ltmemberIDgt already refers to a member, then print
a suitable error and take no further action
18Design insights
- Use case has shown all aspects of employee that
are changeable. - Note that employees can change from hourly to
salaried and vice versa. Initial class design
may not be appropriate. Use STRATEGY pattern
instead (see class diagram next slide) - Use the NULL OBJECT pattern for union membership.
19Updated class design
ltltinterfacegtgt Payment Method
Employee
ltltinterfacegtgt Affiliation
Payment Classification
NoAffiliation
HoldMethod
0..
ServiceCharge
Commissioned Classification - CommissionRate -
Salary
0..
0..
TimeCard
SalesReceipt
20Use Case 7 Run Payroll for Today
- Upon receiving the Payday transaction, the system
finds all those employees that should be paid on
the specified date. The system then determines
how much they are owed and pays them according to
their selected payment method. - Payday ltdategt
21Finding Abstractions
- Must hunt for abstractions, because often not
stated or even alluded to by application
requirements. - Example
- Some employees work by the hour
- Some employees are paid a flat salary
- Some employees are paid a commission
- Generalization All employees are paid, but they
are paid by different schemes. - Abstraction All employees are paid. Lead to
PaymentClassification.
22Another abstraction
- Scheduling the payroll
- They are paid every Friday
- They are paid on last working day of month
- They are paid every other Friday
- Generality All employees are paid according to
some schedule. - Abstraction schedule.
- Use cases link schedule to payment
classification. BUT, it seems possible that this
could change (e.g., employees in different
departments might be paid on different days).
Also, if linked then a change in payment
classification would require testing the schedule
as well. - Schedule abstraction not included in original
design
23Chapter 13
- COMMAND and
- ACTIVE OBJECT
24COMMAND simple elegant
public interface Command public void do()
ltltinterfacegtgt Command do()
Elevates the role of a function to the level of a
class. Blasphemy! But interesting designs can
unfold
25Simple Commands
do()
ltltinterfacegtgt Command do()
do()
RelayOn Command
MotorOn Command
ClutchOn Command
init ClutchOnCommand MotorOnCommand
RelayOff Command
MotorOff Command
ClutchOff Command
Embedded real-time software for a photocopier.
Pass Command() objects around system and call
do() without knowing which type of Command they
represent. Example sensor needs to engage
clutch at point in paper path. Bind appropriate
ClutchOnCommand to object, Sensor detects event,
calls do(). Complexity of determining which
relays to connect to which sensors is now handled
by an initialization function.
26Transactions a type of do()
- Maintain database of employees. Number of
operations that users can apply (add, delete,
modify). - Command object collects unvalidated data,
implements validation methods, executes
transactions.
ltltinterfacegtgt Transaction validate() execute()
Employee - name - address
ltltinterfacegtgt PayClassification CalculatePay()
AddEmployee Transaction - name - address
validate() execute()
ltltinterfacegtgt Pay Classification CalculatePay()
Salaried Classification - monthlyPay
Hourly Classification - hourlyRate
Commissioned Classification - basePay -
commissionRate
0..
0..
SalesReceipt - date - amount
TimeCard - date - amount
27Command Benefits
- Physical and Temporal Decoupling
- Decouple code that procures data from user
(probably a dialog in some GUI) from code that
validates and from business objects. If coupled,
validation code couldnt be used other places.
Code that manipulates database should also be
separate. - Temporal decoupling. Transaction data can be
collected and processed later. For example,
maybe changes to database should only occur in
the evening. - Undo
- Easy to add an undo() method to the COMMAND
pattern. Can reverse the effects of a do().
28ACTIVE OBJECT
- Old technique for implementing multiple threads
of control. - Not covered threads covered in OS and PL
29Chapter 14
- TEMPLATE METHOD
- STRATEGY
- Inheritance vs. Delegation
30Inheritance
- Brave new world in early 90s
- Could program by difference find class that did
something almost useful to us, create subclass
and change only what didnt work in new domain - BUT, easy to overuse inheritance
- New advice Favor object composition over class
inheritance - Need to carefully consider, use inheritance,
composition and delegation appropriately
31TEMPLATE METHOD - inheritance
- Common main-loop structure
Initialize() while (!done()) // main loop
Idle() // do something useful Cleanup()
Use the pattern to create abstract base classes
that can work on various types of objects.
32Example Bubble Sorter
- First, we have a sort that knows how to work with
integers
public class BubbleSorter static int
operations 0 public static int sort(int
array) operations 0 if
(array.length lt 1) return operations
for (int nextToLast array.length-2
nextToLast gt 0 nextToLast--) for (int
index 0 index lt nextToLast
index) compareAndSwap(array, index)
return operations
private static void swap (int array, int
index) int temp arrayindex
arrayindex arrayindex1 arrayindex1
temp private static void compareAndSwap
(int array, int index) if
(arrayindexgt arrayindex1) swap(array,
index) operations
33Bubble Sorter, continued
- Can create abstract class instead
public abstract class BubbleSorter private
int operations 0 protected int length 0
protected int doSort() operations 0
if (length lt 1) return operations
for (int nextToLast length-2 nextToLast gt
0 nextToLast--) for (int index 0
index lt nextToLast index)
if (outOfOrder(index)) swap(index)
operations return operations
protected abstract void swap(int
index) protected abstract boolean outOfOrder
(int index)
BubbleSorter abstract outOfOrder swap
DoubleBubble Sorter
IntBubble Sorter
34Bubble Sorter, continued
- Implement methods for Int and Double
public class DoubleBubbleSorter extends
BubbleSorter private double array null
public int sort(double theArray) array
theArray length array.length return
doSort() protected void swap(int index)
double temp arrayindex arrayindex
arrayindex1 arrayindex1 temp
protected boolean outOfOrder (int idx)
return (arrayidxgt arrayidx1)
public class IntBubbleSorter extends
BubbleSorter private int array null
public int sort(int theArray) array
theArray length array.length return
doSort() protected void swap(int index)
int temp arrayindex arrayindex
arrayindex1 arrayindex1 temp
protected boolean outOfOrder (int idx)
return (arrayidxgt arrayidx1)
35STRATEGY pattern
- Another way to solve the problem of inverting the
dependencies - Instead of putting generic application algorithm
in an abstract class, place it in a concrete
class named ApplicationRunner - Abstract methods that must be called are defined
in the Application interface - ftocStrategy is derived from this interface. An
object of this class can be passed to
ApplicationRunner
ftoc fahrenheit to celcius
ltltinterfacegtgt Application init idle
cleanup done boolean
concrete class
ftocStrategy
concrete class
36Strategy code
public class ApplicationRunner private
Application itsApplication null public
ApplicationRunner(Application app)
itsApplication app public void run()
itsApplication.init() while
(!itsApplication.done()) itsApplication.idle
() itsApplication.cleanup()
can pass in ftocStrategy, etc.
public interface Application public void
init() public void idle() public void
cleanup() public boolean done()
calls methods from interface
37Strategy code, continued
import java.io. public class ftocStrategy
implements Application private
InputStreamReader isr private BufferedReader
br private boolean isDone false public
static void main(String args) throws Exception
(new ApplicationRunner(new
ftocStrategy())).run() public void
init() isr new InputStreamReader(System.
in) br new BufferedReader(isr) //
More code in textbook
38Strategy pros and cons
- Strategy involves more classes
- Delegation pointer in ApplicationRunner incurs
some overhead - BUT
- Easy to reuse ApplicationRunner by passing in
different implementations of Application
39Another example sorting again
public class BubbleSorter private int
operations 0 private int length 0
private SortHandle itsSortHandle null public
BubbleSorter(SortHandle handle)
itsSortHandle handle public int
sort(Object array) itsSortHandle.setArray(ar
ray) length itsSortHandle.length()
operations 0 if (length lt 1) return
operations for (int nextToLast length-2
nextToLast gt 0 nextToLast--)
for (int index 0 index lt
nextToLast index) if
(itsSortHandle.outOfOrder(index))
itsSortHandle.swap(index) operations
return operations
public interface SortHandle public void
swap(int index) public boolean outOfOrder(int
index) public int length() public void
setArray(Object array)
40Sorting continued
public class IntSortHandle implements
SortHandle private int array null
public void swap(int index) int temp
arrayindex arrayindex arrayindex1
arrayindex1 temp public void
setArray(Object array) this.array
(int)array public int length()
return array.length public boolean
outOfOrder(int index) return (arrayindex
gt arrayindex1)
- Notice
- IntSortHandle knows nothing of BubbleSorter
- IntSortHandle could therefore be used with other
sorts e.g., QuickBubbleSorter that stops when
the array is in order (code in text) - Strategy allows the details to be reused
independently of the high-level algorithm!
More comparison sorts covered in CSCI406
41Chapter 15
42Policy patterns
- Both Façade and Mediator impose some kind of
policy on another group of objects - Façade imposes policy from above
- Mediator imposes policy from below
- Façade is visible and constraining
- Mediator is invisible and enabling
43Facade
- Used to provide a simple, specific interface for
a group of objects that has a complex, general
interface
Product-specific sql interface complex but
shields users from knowing sql details
public class DB private static Connection
con public static void init() throws Exception
public static void store(ProductData pd)
throws Exception // Products private static
PreparedStatement buildProductInsertionStatement
ProductData pd) throws SQLException
public static ProductData getProductData(String
sku) throws Exception private static
PreparedStatement buildProductQueryStatement(Strin
g sku) private static ProductData
extractProductDataFromResultSet(ResultSet rs)
public static void store(ItemData id) throws
Exception // Items private static
PreparedStatement buildItemInsersionStatement(Item
Data id) public static ItemData
getItemsForOrder(int orderId) throws Exception
private static PreparedStatement
buildItemsForOrderQueryStatement (int
orderId) throws SQLException private static
ItemData extractItemDataFromResultSet(ResultSet
rs) public static OrderData
newOrder(String customerId) throws Exception
private static int getMaxOrderId() throws
SQLException // Orders public static OrderData
getOrderData(int orderId) throws SQLException
private static void executeStatement(PreparedState
ment s) public static void close() throws
Exception public static void clear() throws
Exception
44DB Facade
DB store(ProductData) getProductData(sku)
deleteProductData(sku)
Application
ProductData
java.sql
Connection
Statement
DriverManager
ResultSet
Prepared Statement
SQLException
All database calls must go through DB. Direct
calls to java.sql violate convention. Policy is
visible application sees interface it provides.
Valid operations are all provided. Simplifies
application programmers dont all need to learn
sql interface, just use DB.
45Mediator
- Imposes policy in hidden, constrained way.
QuickEntryMediator selects the first entry in a
list that matches the current prefix in a
JTextField.
State
JTextField
JList
CO
ALABAMA ALASKA ARIZONA ARKANSAS CALIFORNIA
COLORADO CONNECTICUT DELAWARE
ltltanonymousgtgt Document Listener
QuickEnty Mediator
Hidden Users of JList and JTextField have no
idea that this Mediator exists.
46Mediator QuickEntry Example
State
List of states
public class QuickEntryMediator public
QuickEntryMediator(JTextField t, JList l)
itsTextField t itsList l
itsTextField.getDocument().addDocumentListener(
new DocumentListener() public void
changedUpdate(DocumentEvent e)
textFieldChanged() public
void insertUpdate(DocumentEvent e)
textFieldChanged() public
void removeUpdate(DocumentEvent e)
textFieldChanged() // new
DocumentListener ) // addDocumentListener
// QuickEntryMediator()
responds to JTextField events, shown
on next slide
47Mediator QuickEntry continued
private void textFieldChanged() String
prefix itsTextField.getText() if
(prefix.length() 0) // clear selection if
user clears field itsList.clearSelection()
return ListModel m
itsList.getModel() // finds first item that
matches boolean found false //
text typed so far for (int i 0 found
false i lt m.getSize() i) Object o
m.getElementAt(i) String s
o.toString() if (s.startsWith(prefix))
itsList.setSelectedValue(o, true)
found true // found is true if any items in
list match prefix if (!found)
// clear if nothing matches text entry
itsList.clearSelection() //
textFieldChanged private JTextField
itsTextField private JList itsList // class
QuickEntryMediator
48Chapter 16
49Sometimes you only need one
- Normally there is a one-to-many relationship
between classes and objects - Some classes should only have one instance
- factories
- managers (e.g., print, other resources)
- root of application
- If more than one, logic errors may occur
- May be able to just create one when application
starts and be done with it - Sometimes it is important to enforce singularity
- Two patterns to do that singleton monostate
application root
50SINGLETON pattern
- Simple to implement
- Access through public method, e.g., Instance
- Instance always returns same object
- No public constructors, so cant create a second
object of same type
public class Singleton private static Singleton
theInstance null private Singleton()
public static Singleton Instance() if
(theInstance null) theInstance new
Singleton() return theInstance
51Testing the SINGLETON
public void testCreateSingleton() Singleton s
Singleton.Instance() Singleton s2
Singleton.Instance() assertSame(s,
s2) public void testNoPublicConstructors()
throws Exception Class singleton
Class.forName("Singleton") Constructor
constructors singleton.getConstructors() asser
tEquals("Singleton has public constructors.",
0, constructors.length)
52Pros and Cons
- Benefits of SINGLETON
- Cross platform. Can extend to work across many
JVMs and computers. - Applicable to any class. Just make constructors
private and add static functions and variable. - Can derive a singleton from some other class.
Given a class, can create a subclass that is a
SINGLETON - Lazy evaluation. If SINGLETON is never used, it
is never created
- Costs of SINGLETON
- Destruction undefined. If NULL out theInstance,
other modules may still hold reference. - Not inherited. Class derived from SINGLETON is
not a SINGLETON. Would need to add function to
subclass. - Efficiency. Each call to Instance invokes an if
statement, most often useless. - Nontransparent. Users of SINGLETON must know
they are using SINGLETON because they must invoke
Instance method.
So??
important?
53SINGLETON Example
No IF statement, using Java initialization
- private static UserDatabase theInstance
- new UserDatabaseSource()
- public static UserDatabase instance()
- return theInstance
-
-
- private UserDatabaseSource()
-
- public User readUser(String userName)
- // Some Implementation
- return null // just to make it compile.
-
-
- public void writeUser(User user)
- // Some Implementation
-
Common usage, ensures all database access via
single instance of Façade.
54Two possible approaches
- MONOSTATE enforces the behavior of singularity
- SINGLETON enforces the structure
55MONOSTATE
- Have multiple instances of Monostate, all act as
one
import junit.framework. public class
TestMonostate extends TestCase public
TestMonostate(String name)
super(name) public void
testInstance() Monostate m new
Monostate() for (int x 0 xlt10 x)
m.setX(x) assertEquals(x, m.getX())
Two instances of Monostate behave as though they
were one
public void testInstancesBehaveAsOne()
Monostate m1 new Monostate()
Monostate m2 new Monostate() for (int
x 0 xlt10 x) m1.setX(x) assertEquals(x,
m2.getX())
56MONOSTATE continued
- How can that be?
- Objects share same variables because they are
static - BUT, none of the methods are static so they are
accessed via actual instances of class objects
public class Monostate private static int
itsX 0 public Monostate() public
void setX(int x) itsX x
public int getX() return itsX
not static
57Monostate Turnstile Example
- Turnstile begins in locked state. Returns to
locked state after people pass. - If coin is deposited, transition to Unlocked
state, unlock gate, reset alarm, deposit coins in
its bin - Abnormal condition 1 user deposits two coins
before passing through. Coins are refunded, gate
remains unlocked. - Abnormal condition 2 user passes through without
paying. Alarm sounds, gate locked.
Turnstile finite state machine
Coin / Unlock, AlarmOff, Deposit
Pass / Alarm
Locked
Coin / Refund
Pass / Lock
58Turnstile Code
public class Turnstyle private static boolean
isLocked private static boolean
isAlarming private static int
itsCoins private static int itsRefunds protect
ed final static Turnstyle LOCKED new
Locked() protected final static Turnstyle
UNLOCKED new Unlocked() protected static
Turnstyle itsState LOCKED public void
reset() lock(true) alarm(false) itsCoins
0 itsRefunds 0 itsState LOCKED
59Turnstile code, continued
class Locked extends Turnstyle public void
coin() itsState UNLOCKED lock(false)
alarm(false) deposit() public
void pass() alarm(true)
class Unlocked extends Turnstyle public
void coin() refund() public void
pass() lock(true) itsState LOCKED
The event functions (coin and pass) are delegated
to two derivatives of Turnstyle (Locked and
Unlocked) that represent the states of the
finite-state machine. Derivatives are
automatically MONOSTATE. Since these are all
MONOSTATE, Locked and Unlocked are not really
separate objects, so no violation of OO
principles. NOTE Controlling more than one
turnstile would require significant refactoring.
60Turnstile code, continued
- See rest of code JUnit tests in textbook
61Benefits of MONOSTATE
- Transparency. Users do not need to know that
object is MONOSTATE, because usage is same as for
a regular object - Derivability. Derivatives of MONOSTATE are
MONOSTATE they share the same variables - Polymorphism. Since methods are not static, they
can be overridden. Different behavior, same set
of static variables. - Well-defined creation and destruction. Static
variables in MONOSTATE have well-defined creation
and destruction times.
62Costs of MONOSTATE
- No conversion. Normal class cannot be converted
to MONOSTATE through derivation. - Efficiency. May have many creations and
destructions because MONOSTATE is a real object.
These are costly operations. - Presence. Variables of MONOSTATE take up space,
even if MONOSTATE never used. - Platform local. You cant make a MONOSTATE work
across several JVM instances or across several
platforms.
63Which option to use?
- SINGLETON is best when you have an existing class
that you want to constrain through derivation,
and you dont mind requiring users to call
instance() - MONOSTATE is best when you want singular nature
of class to be transparent or when you want to
employ polymorphic derivatives
64Chapter 17
65Common null code technique
- Rely on short-circuit evaluation
- Error-prone (may forget)
- Try/catch can be even worse
Employee e DB.getEmployee(Bob) if (e ! null
e.isTimeToPay(today)) e.pay()
66An alternative NULL OBJECT
- Employee interface has two implementations
- Normal implementation works as usual
- NULL implementation methods do nothing
ltltinterfacegtgt Employee
DB
ltltcreatesgtgt
NullEmployee
Employee Implementation
ltltcreatesgtgt
NullEmployee is returned if Bob object doesnt
exist isTimeToPay will return false
Employee e DB.getEmployee(Bob) if
(e.isTimeToPay(today)) e.pay()
67NULL Object Code
public class DB public static Employee
getEmployee(String name) return
Employee.NULL
public interface Employee public boolean
isTimeToPay(Date payDate) public void pay()
// NULL EMPLOYEE METHODS public static final
Employee NULL new Employee() public
boolean isTimeToPay(Date payDate) return
false public void pay()
Anonymous inner class ensures single instance
68NULL Object Code continued
public void testNull() throws Exception
Employee e DB.getEmployee("Bob") if
(e.isTimeToPay(new Date())) fail()
assertEquals(Employee.NULL, e)