Simpler service interfaces with Guice
I'm using Guice throughout my code, and I've found a pattern that works rather nicely. Suppose I've got a service interface method for scheduling a delivery:public interface DeliveryService {
/**
* Schedules {@link order} for delivery and returns a snapshot with
* the details of the scheduled delivery.
*
* @param loggedInUser the customer service rep who is making this request.
* @param selectedCustomer the customer to whom the order will be delivered
* @param order the order to schedule a delivery for
*/
Delivery scheduleDelivery(User loggedInUser,
Customer selectedCustomer, Order order);
}
The interface does exactly what it needs to do. But since it has so many parameters, calling it is a hassle for the caller. They need to inject the user and customer, only to pass it to the service:public class ScheduleDeliveryAction implements Action {
private final DeliveryService deliveryService;
private final User loggedInUser;
private final Customer selectedCustomer;
private Delivery delivery;
@Inject
public ScheduleDeliveryAction(DeliveryService deliveryService,
User loggedInUser, Customer selectedCustomer) {
this.deliveryService = deliveryService;
this.loggedInUser = loggedInUser;
this.selectedCustomer = selectedCustomer;
}
public String execute() {
/* parse HTTP parameters etc. */
Order order = ...
this.delivery = deliveryService.scheduleDelivery(
loggedInUser, selectedCustomer, order);
return SUCCESS;
}
...
}
A better approach
A better approach is have the service know about the logged in user and customer implicitly. I change the real implementation of the service so that it gets the Customer and User injected into it. Now the interface is simpler:
public interface DeliveryService {
/**
* Schedules {@link order} for delivery and returns a snapshot with
* the details of the scheduled delivery.
*
* @param order the order to schedule a delivery for
*/
Delivery scheduleDelivery(Order order);
}
And so is the calling code:public class ScheduleDeliveryAction implements Action {The other great benefit of this approach is that if we need to add more fields to DeliveryService, we don't need to change the callers. With Guice, your code is simpler because you don't need to worry about indirect dependencies.
private final DeliveryService deliveryService;
private Delivery delivery;
@Inject
public ScheduleDeliveryAction(DeliveryService deliveryService) {
this.deliveryService = deliveryService;
}
public String execute() {
/* parse HTTP parameters etc. */
Order order = ...
this.delivery = deliveryService.scheduleDelivery(order);
return SUCCESS;
}
...
}