First off, think of different parts of the attendance system.
User interface, finger print scanner, database repository, login process and workflow.
To design this system we can start designing parts in isolation and connect them as a system.
A rough design could be around following parts of the system:
- Fingerprint Scanner and Listener
- Attendance Service
- Employee Repository
- Login Repository
- User Interface
- Attendance Workflow Controller
- Fingerprint Signature
In the following code listing certain aspects of design principles will be visible already:
- SRP - One entity is responsible for one job
- LoD - Law of Demeter - Only talk to your immediate friends. You will notice Controller does not know anything about repositories.
- DbC (Design by Contract) - Work against interfaces
- Use dependency injection and IoC - constructor injection and method injections
- ISP (Interface Segregation Principle) - Interfaces are lean
- OCP - Override interface methods in derived classes or pass different implementation as injected interfaces can extend the behaviour without the need to modify the class.
Based on this much thought, the system might work like this:
[You can further improve on it and add missing logic, I am providing a very quick design outline with brief implementation.]
Code Listing
interface IAttedanceController
{
run();
}
interface IFingerprintHandler
{
void processFingerprint(IFingerprintSignature fingerprintSignature);
}
interface IFingerprintScanner
{
void run(IFingerprintHandler fingerprintHandler);
}
interface IAttendanceService
{
void startService();
void stopService();
bool attempEmployeeLogin(IFingerprintSignature fingerprintSignature);
string getFailureMessage();
}
interface ILoginRepository
{
bool loginEmployee(IEmployee employee, DateTime timestamp);
void open();
void close();
}
interface IEmployeeRepository
{
IEmployee findEmployee(IFingerprintSignature fingerprintSignature);
void open();
void close();
}
//-----------------------------------------
class AttendanceService : IAttendanceService
{
private IEmployeeRepository _employeeRepository;
private ILoginRepository _loginRepository;
private string _failureMessage;
public class AttendanceService(
IEmployeeRepository employeeRepository,
ILoginRepository loginRepository)
{
this._employeeRepository = employeeRepository;
this._loginRepository = loginRepository;
}
public bool attempEmployeeLogin(IFingerprintSignature fingerprintSignature)
{
IEmployee employee = this._employeeRepository.findEmployee(fingerprintSignature);
if(employee != null)
{
//check for already logged in to avoid duplicate logins..
this._loginRepository.loginEmployee(employee, DateTime.Now);
//or create a login record with timestamp and insert into login repository
return true;
}
else
{
this._failureMessage = "employee not found";
return false;
}
}
public string getFailureMessage()
{
return "reason for failure";
}
public void startService()
{
this._employeeRepository.open();
this._loginRepository.open();
}
public void stopService()
{
this._employeeRepository.close();
this._loginRepository.close();
}
}
//-----------------------------------------
class AttendanceController : IAttedanceController, IFingerprintHandler
{
private ILoginView _loginView;
private IAttendanceService _attedanceService;
private IFingerprintScanner _fingerprintScanner;
public AttendanceController(
ILoginView loginView,
IAttendanceService attendanceService,
IFingerprintScanner fingerprintScanner)
{
this._loginView = loginView;
this._attedanceService = attedanceService;
this._fingerprintScanner = fingerprintScanner;
}
public void run()
{
this._attedanceService.startService();
this._fingerprintScanner.run(this);
this._loginView.show();
}
public void IFingerprintHandler.processFingerprint(IFingerprintSignature fingerprintSignature)
{
if(this._attedanceService.login(fingerprintSignature))
{
this._loginView.showMessage("Login successful");
}
else
{
string errorMessage = string getFailureMessage();
this._loginView.showMessage("errorMessage");
}
// on return the fingerprint monitor is ready to take another finter print
}
}
//-----------------------------------------
App.init()
{
// Run app bootstrap
// Initialize abstract factories or DI containers
IAttedanceController attedanceController = DIContainer.resolve("AttedanceController");
attedanceController.run();
}
//-----------------------------------------