tags:

views:

73

answers:

5

Considering I have a service to calculate a customer account balance with the interface

public interface ICustomerAccountCalculation
{
    Decimal Balance(int customerId);
}

is it better style to rather than pass in the customer id to pass the customer object like this

public interface ICustomerAccountCalculation
{
    Decimal Balance(Customer customer);
}
A: 

More natural thing to do would be to pass the entity but this usually causes performance problems, so in most practical scenarios you would pass just the key.

Edgar Sánchez
There is no way to know if passing the entity is less performant in this situation. Not to mention you are just passing a reference to the entity.
Matt Greer
Mmm, most of the times an int will be more (slightly) more performant than an object reference. But you have a point, and I'd like to clarify I was thinking of web services, where the whole object would be serialized.
Edgar Sánchez
A: 

Pass only the values that are going to be used in the function. If the customerid is enough for you to carry out further computation then pass only that much - if any other field is required pass it as a different parameter to the function.

It is a good practice to abstract the function from the object. A function should only be concerned with input VS output. For example if your function is float computeBalance(float, float) then it should be able to take any two float values and carry out the computation. Passing the object means you have read the object and extract the desired fields ... not a good thing to do :)

Sagar V
+2  A: 

I think it is really a question you need to answer because it depends. What is the cost vs benefit of passing the entity vs just passing the id? In the case of your service contract it looks like an id would be sufficient information (I know I am making an assumption) to get the account balance for a customer. Some other things to consider are the cost to serialize/deserialize your entity, etc...

But in another case it may make sense depending on the operation you are performing. Lets say the operation needs more information from the caller about the customer, it doesn't make sense to go to the database to get that information within the operation if you already have it loaded from within the caller...

So, it depends.

Wil P
+1  A: 

If the purpose of the function is to calculate the account balance of the customer, I am going to assume that the customer is already created and contains an account balance. I am also going to assume that customerId is unique for each customer, so the account balance can be calculated (retrieved) by just using the customerId. Having said all this, if all you need is the customerId to create the balance, then just passing the id in is fine, but if you need other properties on the customer object, then passing in the whole customer may be a better idea or you may pass in multiple parameters instead.

As an example, if you were to create the balance solely based on the customerId, you might do something like this in your Balance() method (this looks more like a retrieval than a calculation though):

decimal balance = from c in Customers
                  where c.CustomerId == customerId
                  select c.Balance;

As shown above in the linq query, if all you need is customerId, then go ahead and just pass that in, but if you need other properties, pass in the whole customer or pass in more parameters. Looking at it further, you mentioned that this is for calculating the balance, so that would tell me that you might need more than just the customerId, so maybe passing more parameters or the whole object would be better in that case.

Xaisoft
+1  A: 

Lets break down the responsibilities for both implementations.

ICustomerAccountCalculation taking ID

  • Retrieve customer by ID
  • Perform calculation

ICustomerAccountCalculation taking Customer

  • Perform calculation

As you can see the first version does more than perform calculation. As such, it's a violation of Single Responsibility Principle. The second version should be your first attempt, and only change to the version taking ID if there is an explicit need for it. Even still, if for some reason you need to do calculation by ID, you can always retrieve it from the Customer instance.

Igor Zevaka
Not trying to flame you but I object to your using of the Single Responsibility Principle as your argument. Let's get this straight : the question to apply when SRP is more on the cohesiveness of the class/module rather than what you have used as an argument. Of course the class can retrieve the data, only that the class that performs the actual data retrieval is different class (e.g a DAO class). Does this make sense?
Syd
Hmmm, here is how I think about it. Even if `ICustomerAccountCalculation` delegates the task of retrieving the entity to another service, why should it know that customers are retrieved by `int` ID? This comes down to a more general principle of information hiding. The first version has one more *reason to change* over the second version - and that is the type of ID changing. This is why I think application of SRP is valid here. Equally valid is Open Closed Principle, where were close the `ICustomerAccountCalculation` interface from changes to ID type.
Igor Zevaka