I have trouble understanding if I should pass an argument to a method as a primitive value or as an already-obtained object.
Consider this simple example
interface Channel{
String getId();
String getName();
}
interface ChannelRepository{
Channel findBy( String id);
}
public class DummyChannelRepository implements ChannelRepository{
@Override
public Channel findBy(String id) {
return null;
}
}
interface Customer{
String getId();
String getChannelId();
String getName();
}
interface CustomerRepository{
Customer findBy( String id);
}
public class DummyCustomerRepository implements CustomerRepository{
@Override
public Customer findBy(String id) {
return null;
}
}
Now I want to create a common calculator interface that receives a channel and a customer. For me it's not clear if the calculation method of my interface should use primitive parameters (in that case Ids) or it should use object instances. So I came up with two solutions.
Variant #1 using object instances
interface CalculatorThisWay{
double calculate( Channel channel, Customer customer );
}
public static class DummyCalculatorThisWay implements CalculatorThisWay{
public double calculate( Channel channel, Customer customer ){
// do whatever
return 1.5d;
}
}
public static void main(String[] args) {
String channelId = "Channel-1";
String customerId = "Customer-999";
ChannelRepository channelRepo = new DummyChannelRepository();
CustomerRepository customerRepo = new DummyCustomerRepository();
Channel channel = channelRepo.findBy( channelId );
Objects.requireNonNull( channel, "Channel must not be null");
Customer customer = customerRepo.findBy( customerId );
Objects.requireNonNull( customer, "Customer must not be null");
DummyCalculatorThisWay calc = new DummyCalculatorThisWay();
calc.calculate(channel, customer);
}
Variant #2 using primitive identifiers
interface CalculatorThatWay{
double calculate( String channelId, String customerId );
}
public class DummyCalculatorThatWay implements CalculatorThatWay{
private final ChannelRepository channelRepo;
private final CustomerRepository customerRepo;
public DummyCalculatorThatWay( ChannelRepository channelRepo, CustomerRepository customerRepo ){
this.channelRepo = channelRepo;
this.customerRepo = customerRepo;
}
public double calculate( String channelId, String customerId ){
Channel channel = channelRepo.findBy( channelId );
Objects.requireNonNull( channel, "Channel must not be null");
Customer csutomer = customerRepo.findBy( customerId );
Objects.requireNonNull( csutomer, "Customer must not be null");
// do whatever
return 1.5d;
}
}
public static void main2(String[] args) {
String channelId = "Channel-1";
String customerId = "Customer-999";
DummyCalculatorThatWay calc = new DummyCalculatorThatWay(
new DummyChannelRepository(),
new DummyCustomerRepository()
);
calc.calculate( channelId, customerId);
}
So for me both ways feel correct but consider reusing the logic of how to get the channel and the customer object in different places. In Variant 1 I would have to duplicate that logic or put it in some Helper class where as in Variant 2 the logic is in the class itself and can be reused.
So is there any guide when to use what or any best practice?