views:

91

answers:

2

Hi there

I have abstract class called Tenant and Customer. The tenant in this case is like owner of the application for multi tenant application model.

The relationship between these 2 class are Many to One relationship.

public abstract class Tenant
{  
  protected Int32 id;  
  protected String name;  
  public Int32 ID { get; set; }  
  public String Name { get; set; }  
  public abstract bool Add();  
  public abstract bool Update();  
  public abstract bool Delete();
  public abstract List<Tenant> Get();
}

public class ApplicationTenant: Tenant
{  
  public ApplicationTenant() { }  
  public override Int32 ID  
  {  
    get { return id; }     
    set { id = value; }  
  }  
  public override String Name  
  {     
    get { return name; }     
    set { name= value; }  
  }  


  public override List<Tenant> Get()
  {
     ...
  }
}

public abstract class Customer
{  
  protected Int32 id;  
  protected String name;  
  protected Tenant tenant;  
  public Int32 ID { get; set; }  
  public String Name { get; set; }  
  public Tenant Tenant { get; set; }  
  public abstract bool Add();  
  public abstract bool Update();  
  public abstract bool Delete(); 
  public abstract List<Customer> Get();
}

public class CorporateCustomer : Customer
{  
  public CorporateCustomer () { }  
  public override Int64 ID  
  {     
    get { return id; }     
    set { id = value; }  
  }  

  public override String Name  
  {     
    get { return name; }     
    set { name= value; }  
  }  

  public override Tenant Tenant  
  {     
    get { return tenant; }     
    set { tenant= value; }  
  }  

  public override List<Customer> Get()
  {
     ...
  }

  ...
}

With the OO design above, we know that method of List<Tenant> Get() needs to be overrided.

BUT the issue are:

1) The return value of the Get() in the CorporateCustomer is always going to be List<CorporateCustomer>. It meeans that I have to override List<Tenant> Get() without being implementation and create another following method

  public List<CorporateCustomer > Get()
  {
     return ???;
  }

2) If I override anyway for this method above and on the retun I just cast it ... it won't work anyway. ?!!? Casn casting to List<CorporateCustomer> from List<Customer>

3) The property below:

  public override Tenant Tenant  
  {     
    get { return tenant; }     
    set { tenant= value; }  
  }

means again I have to override this BUTI don't I really used this cause the CorporateCustomer is always going to be used the ApplicationTenant instead as return NOT Tenant.

  public CorporateTenant Tenant  
  {     
    get { return corprateTenant; }     
    set { corprateTenant= value; }  
  }

So is this the right design? Cause it's kinda waste of the abstraction.

Some people suggests to use Generic abstract class instead which I am not sure it's going to help anyway.

I am appreciated your feedback.

Thanks

A: 

The concept of abstraction can help you make your code modular, it helps clients of your model to define right abstraction in their designs and thereby avoiding repetition of logic I will try to elaborate on this,

Consider a class called CorporateTenantManager which say deals with management of Corporate Tenant. This class will be 'aware' of the presence of CorporateTenant and 'CorporateCustomer' classes and so will process things in Corporate* type.
However now consider a class which is responsible for say authentication of customer, that class may not be interested in knowing what type of customer it is and so will deal in Customer language only.

So you do not have to add getters-setters for each concrete class. In case of a getter-setters, client of class knows what to expect so even if return type is an abstract type client will type cast it to the concrete class it expects.

Chetan
In that case then, I shouldn't set abstraction for Get() methods as well as Tenant property on the Customer class ... correct? You know the it will be nice to put those Get() and Tenant property because it makes sense BUt what I found is that the implementation of the Customer abstract class which is CorporateCustomer is required the same Get() and Tenant BUT slighly different implementation in relation to the return value.
dewacorp.alliances
Yes you could keep base implementation in base class (Customer) and override the required method(s) in the concrete class (CorporateCustomer) when behavior is gonna be different.I would also recommend you to use Interfaces in following manner, ICustomer defines methods to interact with any Customer, Customer abstract class implements ICustomer interface and provides base implementation, a concrete class like CorporateCustomer extends Customer class and overrides/re-uses functionality provided by Customer class.
Chetan
In abstraction, you can override inside the methods BUT not the return value as well as passing variable. This is where I am struggle a bit.
dewacorp.alliances
As described above theres no need to return with specific types (ie subclasses) client of the model will be aware of the data type it expects so it can always cast it to subclass moreover if you still feel like giving a specific type then you can always define interface for subtype say ICorporateCustomer, define a method which shall return CorporateCustomer object so CorporateCustomer concrete class extends Customer abstract class and implements ICorporateCustomer. But I sincerely dont think you should be hell bent on having concrete classes as your return type.
Chetan
A: 

It seems like you need to separate out your concerns some. The Tenant class should be responsible for storing stuff about a single tenant or doing something to a single tenant. I don't really understand why or how you would return a list of tenants from a single tenant object. Or what the Add method is supposed to do. If you want to store a bunch of Tenants, you should use a collection of some sort.

If you don't have any specific implementation that is applicable across the classes that will inherit your base class, you're probably better off using an interface instead of an abstract class.

public interface ITenant
{
    int ID { get; set; }
    string Name { get; set; }
}

public interface ICustomer
{
    int ID { get; set; }
    string Name { get; set; }
    ITenant Tenant { get; set; }
}
mdm20
Get method on the Tenant is for listing all Tenants. You could return a multiple tenant on one of the single object. I know this is not ideal. Regarding the abstraction, I do need specific implementation such Add(), Update(), Delete() BUT as per explanation above, the Get() might return differently plus actual Tenant property as well.
dewacorp.alliances
Technically I do have a specific implementation such as GetAll() but the return value is different implementation for each overrided class.
dewacorp.alliances