Question

I have design level question in one of my project.I'm working on a project in which I need to fetch some objects using REST. Say for example fetch Customers and show it in a list.

Following operations that can be done on Customer,

  • Adding a Customer
  • Editing Customer details
  • Delete Customer

So I thought of including a Class named 'CustomerManager', included following methods,

  @interface CustomerManager
  - (CustomerManager *)sharedManager;

  - (BOOL)addCustomer:(Customer *)customer;
  - (BOOL)deleteCustomer:(Customer *)customer;
  - (BOOL)updateCustomer:(Customer *)customer;

  @end

  @implementation CustomerManager

   - (BOOL)addCustomer:(Customer *)customer;
    {
       NetworkManager  * manager = [NetworkManager manager]     addCustomer:customer ];
    }
   @end

In the ViewController where ever I need to perform customer related operations, I used to make it like this,

 Customer * manager = [Customer sharedManager];
 [manager addCustomer:customer];

 //fetch customer
 [manager customers];

 //While deleting
 [manager deleteCustomer:customer];

Everything is looking and working fine, until I get a design level question, why there was a manager in-between . All the work was done on Customer Object, so you need to have all the Customer related operations in the Customer Class, like something below.

  @interface Customer

  + (BOOL)addCustomer:(Customer *)customer;
  + (BOOL)deleteCustomer:(Customer *)customer;
  + (BOOL)updateCustomer:(Customer *)customer;
  + (NSArray *)customers;

  @end

The problem here is , even though network related code in a separate class, I need to have a Concrete reference of my network manager in all my model classes. Confused , which one to choose.

Which was the best way?. I would like to have some detailed answer for this.

Was it helpful?

Solution

I don't believe there to be a correct answer here. I personally have gone back and forth on how to have my web services interact with my models. But I can provide you with a few pointers:

  1. CustomerManager is overkill. The Customer model is responsible for managing itself -- you can place Customer-related methods inside of it. You don't need a separate object here.
  2. I typically use a super-class for my models. So, for example, you could have a class called ApplicationModel which Customer and all of your other models will inherit from. This is a great way to DRY up the code in your models. If you do decide to have network-related code in your models, I would suggest placing it in this super-class. That way if you need to make changes to the way the web services work, you only need to change code in 1 place.
  3. In general, I would suggest keeping network-related code separate from your models. I like to have my networking logic as isolated as possible. Network-related code is prone to change, and you want to minimize the number of places that networking changes impact your code. For example, I usually create a class that services as an API wrapper and it gives a public interface for making API calls. This class is also responsible for parsing the responses of those methods & interfacing with the models (i.e. parsing a JSON custom array and interfacing with Customer to add those objects to the database).

OTHER TIPS

I disagree with Michael Frederick on his first point.

Your CustomerManager is a much better idea than putting customer CRUD operations on the Customer model object itself. The first and foremost reason being that a customer model class' single responsibility should be to represent a single customer; not additionally to manage a set of customers (single responsibility principle). In DDD terms I would expect a Customer class to be an entity.

Take note that there is a big difference between a model object (as in the MVC pattern) and a domain object. The key difference being that a model object's responsibility is to provide a view with a representation of some data and a domain object's responsibility is, and should not be more than, to be a logical translation of a domain concept, independent of representation.

As I can tell from your controller your model should hold a set of customers. I would therefore have a CustomersModel hold a set of Customer objects. The controller's responsibility is to handle requests and manipulate the model appropriately based on the request, so that the result is a consistent view of the state of the application. It is not, and should not be, responsible for the CRUD operations itself. Typically in a multi-layer design an application layer service would be responsible for such operations, which would probably delegate it to an infrastructure layer repository (or DAO). Putting it together, at minimum my design would look something like:

customer crud uml

All CRUD, handing of requests and state management, is performed on the left side of this UML diagram.

Another way of looking at is is that in the simplest of terms all this could amount to a few lines of code. Let's say all you are doing the same CRUD operation on an array. Should the array elements themselves be responsible for manipulating the array? Of course not. The CustomerRepository is the array, the NetworkManager is its persistence (i.e. memory), the controller is the actor that uses the array, the CustomersModel is a local copy or subset and the Customer is the array element.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top