Skip to main content

Use Case 1 - Adding a new employee

Use Case 1 - Adding a new employee

A new employee is added by the receipt of an AddEmp transaction. This transaction contains the employee's name, addess, and assigned employee number. The transaction has the following three forms:

$ AddEmp <EmpId> "<name>" "<address>" H <hourly-rate>

$ AddEmp <EmpId> "<name>" "<address>" S <monthly-salary>

$ AddEmp <EmpId> "<name>" "<address>" C <monthly-salary> <commission-rate>

The employee's record is created with its field assigned appropriately.

Alternative:
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.

Requirement Analysis

The Use Case describes various ways how Employee-data can be added to the system. AddEmp could be implemented as a polyadic function that receives 5-6 arguments, describing an Employee's personal information and the salary the Employee_receives, and the type of _salary (H, S or C). If the salary type is C, an Employee requires an additional commission-rate. Obviously, errors happening during transactions must be treated with care, appropriate error messages should be displayed. This is particularly important for the input provided by the client, e.g. salary types must be validated as well as the rates; also, check if empIds already exist and prevent multiple occurences of the same empId.

Takeaways

  • validate user input:
    • empId: existing? valid format?
    • salaryType: is it one of H, C, S?
    • salary should be greater than 0
  • display error messages if a transaction failed

Actors

Accountant - adds a new Employee to the system.

Figure 1 Actor "Accountant" carries out the "Add Employee"-Use Case.

The Actor carrying out the Use Case is an Accountant. Of course, any other "role" would be eligible, but since the system exists in a Domain dealing with Accounting, I assume Accountant describes (a part of the) target audience of the system quite well.

Specifications

  • For nN0n \in \N_0, SnS_n is a set of arbitrary characters Sn=n|S_n|=n. Then ""=S0S_0, an empty string.
  • "empId" Sn>0\in S_{n>0}
  • "salary type" {"H","C","S"}\in \{"H", "C", "S"\}
  • "salary type" ="C"= "C" \rArr <commission-rate> R0\in \R_{\ge0}
  • "rate" {x=\in \{x= <hourly-rate>  x=\lor \space x= <monthly-salary>  xR0}| \space x \in \R_{\ge0}\}

Design

The main program receives the input and forwards it to the Application Layer. A Repository manages transaction-calls for an Employee-Entity. This will be orchestrated by Payroll, a Domain Model part of the Domain Layer.

Domain Objects

  • The Employee-Entity providing information about salary, salary-type etc.
  • The EmployeeRepository accesses the required infrastructure for persisting Employee-Entities. The Repository should give the client the illusion that objects queried from it are in memory [📖DDD, p. 157]. Thus, the reconstitution as well as the creation of Employee-instances will be delegated to a Factory Method as part of the Employee-class. At this point, I do not see the need for a more complex factory that assembles intricate aggregates, but providing a Factory Method as part of this Domain Object (and Domain Objects in general) can help with leveraging responsibilities for constructing and reconstitution of said Domain Objects to the Domain Object itself [📖DDD, p. 139]. Following the Dependency Inversion Principle, the EmployeeRepository will provide the Interface to which the object in the Infrastructure Layer has to conform to.

Layers

Client Layer

  • We will receive input from here. This layer will be substituted by the test classes

Application Layer

  • Will consume the input and forward it to the Domain Layer. This layer will be substituted by the test classes. Thus, the test cases replace the controller method. It will accepts primitive data types which are forwarded to the Employee's Factory Method. Employee-instances will be forwarded to the Payroll's addEmployee-method

Domain Layer

  • Payroll exists in the Domain Layer in the form of a Facade.
  • The EmployeeRepository handles Domain Objects so it's associated with this domain and will a such become part of the Domain Layer.

Infrastructure Layer

  • The EmployeeRepository accesses lower-level objects facilitating write-operations for a data storage of an arbitrary type. The lower-level objects will be part of this layer. For this implementation, we will focus on the interface and provide simple file-based operations, but implement a Table Data Gateway that provides access to Employee-data. The Domain Layer will provide the interface for such an EmployeeGateway according to the Dependency-Inversion Principle.

Resulting UML

Figure 1 The up-front design for Use Case 1, spanning several layers.

Implementation

info

Source code is loaded from payroll. The branch is usecase1.

I have deliberately put the Employee into the Company namespace. According to the description of the software, the Payroll-system will make sure to pay an Employee - and I see an Employee in the context of a Company, although putting Employee into the Company-namespace hints to resembling a parent("company")-child("employee") relationship. Such namespaces often share symptoms of vacuous modelling - just like an Anemic Domain Model is of little functional and conceptual value. In general, Vernon suggests to "relax the rules a bit between child and parent Modules." [📖IDDD].

Even if the Use Case does not explicitly state such a context, at least the semantics indicate it. Is Company then eligible to understand the context of Employee? Not necessarily. But the discussion should be held with domain experts understanding the project to the fullest. Is the Software used with Public Administrations? Then Company might not be the best fit for the managed Employee.