I know there is a lot of questions (And answers) about the difference between Domain Service and Application Service.
One of the most viewed answers regarding this is this one: Domain Driven Design: Domain Service, Application Service
But I'm still having trouble to draw the line between this two kind of services. So I brought here an example.
This is entity I have:
package com.transportifygame.core.domain.entities;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.transportifygame.core.domain.constants.Drivers;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.time.ZonedDateTime;
import java.util.UUID;
@Getter
@Setter
@Entity
@Table(name = "drivers")
public class Driver
{
@Id
@GeneratedValue
private UUID id;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "salary", nullable = false)
private Double salary;
@Column(name = "age")
private Integer age;
@Column(name = "hired_at")
private ZonedDateTime hiredAt;
@Column(name = "bonus")
private Integer bonus;
@Column(name = "experience_level", nullable = false)
private Integer experienceLevel = Drivers.ExperienceLevel.BEGINNER.ordinal();
// And keep going...
}
And this is a Domain Service I have:
package com.transportifygame.core.domain.services;
import com.transportifygame.core.domain.entities.Company;
import com.transportifygame.core.domain.entities.Driver;
import com.transportifygame.core.domain.events.drivers.DriverFired;
import com.transportifygame.core.domain.exceptions.drivers.DriverInDeliveryException;
import com.transportifygame.core.domain.exceptions.drivers.DriverNotFoundException;
import com.transportifygame.core.application.repositories.DriverRepository;
import com.transportifygame.core.application.utils.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.UUID;
@Service
public class DriverService extends AbstractService
{
private DriverRepository driverRepository;
private DriverAvailableService driverAvailableService;
@Autowired
public DriverService(
DriverRepository driverRepository,
DriverAvailableService driverAvailableService
)
{
this.driverRepository = driverRepository;
this.driverAvailableService = driverAvailableService;
}
@Transactional
public Driver hire(Company company, UUID driverAvailableId) throws DriverNotFoundException
{
// First load the driver
var driver = this.driverAvailableService.getDriver(driverAvailableId);
// copy the data from the driver available
var newDriver = new Driver();
newDriver.setName(driver.getName());
newDriver.setAge(driver.getAge());
newDriver.setBonus(driver.getBonus());
newDriver.setHiredAt(DateTime.getCurrentDateTime(company.getUser().getTimezone()));
newDriver.setSalary(driver.getSalary());
newDriver.setCompany(company);
// save it
newDriver = this.driverRepository.save(newDriver);
this.driverAvailableService.deleteDriver(driver);
return newDriver;
}
public void fire(Company company, UUID driverId) throws DriverInDeliveryException, DriverNotFoundException
{
var driver = this.getDriverDetails(driverId);
if (!driver.getCompany().getId().equals(company.getId())) {
throw new DriverNotFoundException();
}
// First check if the driver it's in the middle of a delivery
if (driver.getCurrentDelivery() != null) {
throw new DriverInDeliveryException();
}
var driverFiredEvent = new DriverFired(this, company, driver.getName(), driver.getSalary());
this.publishEvent(driverFiredEvent);
// And delete the driver in the end
this.driverRepository.delete(driver);
}
public Iterable<Driver> getAllCompanyDrivers(Company company)
{
return this.driverRepository.findAllByCompanyId(company.getId());
}
public Driver getDriverDetails(UUID id) throws DriverNotFoundException
{
var driver = this.driverRepository.findById(id);
if (driver.isEmpty()) {
throw new DriverNotFoundException();
}
return driver.get();
}
}
Can this service be classified as Domain Service? If not what can it be sliced down to turn it in a ApplicationService?
Thanks!