tags:

views:

133

answers:

3

I am designing an API and I would like it to be simple to use. So, if I have Customers, Statements, and Payments. Does it make sense to have objects such as: Customer, CustomerHandler, Statement, StatementHandler, Payment, PaymentHandler? This way when the developer wants to do something with customers he/she knows to create a CustomerHandler and then all of the possible functions that one would like to perform with a customer are inside the handler.

Methods like: CustomerHandler: AddCustomer(customer), GetCustomer(customerID), GetCustomerCount()… StatementHandler: AddStatement(customerID), GetStatement(statementID), GetStatementCount(customerID)… PaymentHandler: GetPaymentsByCustomer(customerID), GetPayment(paymentID), GetPaymentCountByCustomer(customerID)…

This way if the developer wants to work on receiving payments he/she knows to go to the PaymentHandler. My coworker thought that functions like GetPayments(customerID) belong in a class that manages the customer. So, it would be like Customer.GetPayments() AS Payments. But if I have some other entity like Worker, there would be Worker.GetPayments() AS Payments. So, I see the logic with both approaches. The first one groups things together so that if no matter whom the payment is coming from you get it all from one class by having functions like GetPaymentsByCustomer(CustomerID) and GetPaymentsByWorker(WorkerID). This way one does not have to stumble through different handler or manager objects to get payments. Both approaches make sense to me, how about you? Or, are we both off and there is a better way to do this? Thanks in advance!

A: 

In the "where does it belong" debate, I usually decide where something belongs based on what it returns. If you have a GetPayments() method that returns a list of Payment objects, it should be on the PaymentHandler.

It's really a pretty subjective thing, but doing it by return type ensures that everything that creates Payment objects will be in the PaymentHandler, Customer objects in the CustomerHandler, etc.

This can simplify things a bit when you need to make changes later, and as you mentioned makes it very easy for users of your API to figure out which handler they need to call - if they need a Customer, they'll work with the CustomerHandler.

It also eliminates confusion if you have a hypothetical method like GetPayments( customerId, workerId ) that would get payments for a customer and a worker. Using your co-workers suggestion, it's unclear where this method would go since it involves payments, customers and workers. Categorizing by return type is almost always clear since a function only returns one thing.

Eric Petroelje
+2  A: 

If you're designing an API, then maybe you could try writing a few mock-ups from your intended users' point of view. Implement a few use cases, even if it's just on a white board, and see which approach is more valuable.

In your payments example, both Worker and Customer could implement a Payable interface. If you then later had to add an object that could be "paid", you would simply have it implement the same interface. If you had a payment handler and need to add a new type of thing that could be paid, you would have to change the handler by adding a new method. Over time this could get cumbersome I suppose. You could of course use a combination of the two, and have a handler utility that acted as a front for your payment system.

Boden
+1  A: 

You are pretty much describing two ways (patterns) for data access:

Please, get Martin Fowler's book Patterns of Enterprise Application Architecture and read through all pros and cons. In particular if you try to expose your objects and APIs as web services you might want to go with the data mapper approach (as you suggest).

Active record is very popular because it is simpler. Decide for yourself what suites your needs the best.

David Pokluda
Wow, this really goes over my head. I guess I need to get that book.
Please don't worry. It is not a rocket science. It is a very well written book that is easy to read -- especially if you did some of that work already.
David Pokluda