OOP Design Question - Need an opinion...

I know there is no "100% correct" way to design the following but any suggestions or shared opinions would be appreciated:

I want to create a Customer business entity. Should this Customer class only contain properties and simple validation or should it also contain all the business logic and CRUD functions Should I create a separate class called CustomerService that handles logic by passing around and working with the Customer entity

Example: How to add a new Customer

1) All domain logic in one Customer object.

Customer.Name = "Bla"

Customer.Save

OR

2) Customer object to hold properties and Service object to perform business logic.

Customer.Name = "Bla"

CustomerFactory.AddCusomer(Customer)

What are the pros and cons of each approach




Answer this question

OOP Design Question - Need an opinion...

  • L123

    Are you planing to reuse these business entities via other services If the answer is "not right now" then you are over-engineering.

    What is the nature of these services and how do "light" objects help reuse them

    "Light" entity objects are not used in OOP - they are used in Procedural Programming. Microsoft's samples are good for evaluating Microsoft's techologies and class libraries and not as a reference to proper OOP/OOD.



  • Edmaneiro

    One of the basic priciples of OOP is Cohesion - this means the things that change together should stick together. In you case if the logic of CustomerFactory.AddCustomer changes whenever the Customer class changes then they should remain in one class.

  • Cappy Popp

    In object-oriented systems reuse is acheived by programming to an interface instead of programming to am implementation. Once the Sales System Domain is constructed an interface will be defined for what a Customer represents in the problem domain. This may very well be similar to the interface defined for Customer in the CRM domain but not identical, as you've mentioned.

    With polymorphism and design patterns you can reuse the Customer class in both systems, encapsulate the common logic that is relevant to a Customer in both systems and still provide the minimal interface in both situations.

    I still advise you to wait until you actually require this feature and not get out of your way trying to support it now. Experience shows it is a lot easier to accommodate unpredictable future requirements when you accept the fact that they are unpredictable and focus on the quality of implementation of the known requirements.

    I can also advise you to try and move as much logic as you can into the Customer class and remove its exposed properties in the process, this is in order to remove duplication and coupling exposed properties entail.



  • Adhvika

    Thats really a good explanation.

    Could you please highlight on which approach is better the one having static methods or having instance method Considering thread safe in multi user application.

    What I need is basically is CustomerFactory.AddCustomer(Customerobject). Suppose addcustomer method does not change customer object then which is better

    Let me know. I am sure you have good answer for this.

    Thanks,

    Sreenath



  • Snow Teo

    Well, I guess I was worried what would happen If I wanted to resuse a Business Object in a different application. Lets say a Customer object. The object would contain all the business logic for the CRM domain. Maybe this logic would not be needed in my Sales System Domain. However, I would want to resuse the Customer Object's properties such as Cust.Name, Cust.Address, etc. I would not need Cust.UpdateSeconadryAddress().

    Maybe you are right and I am over thinking this a bit. Does my above example make any sense How would you deal with this situation

    Thanks for your help.



  • Cody55

    This is a very interested topic. I would like to add my opinion. I may be wrong (because I am not an OOP expert).

    I used to program with option 2, i.e. Customer Class does not contain any method and it is just a data mapper. The reason is that:

    1. It is logically not correct to, say, delete itself (Customer.delete()) or add to itself (Customer.add()). It should be done by another class, e.g. CustomerCollection.

    2. I usually create an interface called ICustomerMethod and use another class (e.g. SQLCustomerMethod) to implement this interface. I find it very flexible. If I change to back end database from MS SQL to Oracle, I just create another class (e.g. OracleCustomerMethod) implementing the same interface. In this way, we only need to change the data access logic and we do not need to change the business logic. (i.e. Customer and CustomerCollection classes).



  • liujj_xujj

    I would call it a matter of programming style, and these two programming styles have very little in common. If you are more familiar with OOP - which means you are used to working with abstractions, interfaces, design patterns, immutable objects etc... then a single Customer class is the way you should go. If you are more accustomed to static functions performing operations on data structures, then you should use one class as a data structure and a second static class for logic.

    "Persistence related code" simply refers to code having to do with storing and retrieving in-memory data to some form of persistent storage (a reational database, a file, an XML stream, etc...).



  • imanish11111

    Hello y'all.
    My two cents. Like I've read somewhere in these forums, "it depends" on what the requirements of the application are. In my own opinion, I try to find a common best practice that accomodates upscaling or downscaling and use that as much everywhere as possible.
    The issue I see here is the balance between the size of the object in respect of the fact that you'll be moving it around the application. I think it should be as lean and mean as possible. The business logic can be packaged seperately in a services layer.
    Here's an MSDN article that's been of help
    http://msdn.microsoft.com/library/default.asp url=/library/en-us/dnbda/html/BOAGag.asp

    Again, I think it depends on what works for you. It would be nice to go with an approach that's most easily maintainable. If the application needs to be scaled up/out will the current approach have to be trashed.

    In closing, I use lean, mean data objects, just properties. Then I have data access components that do the basic database operations and then some. Simply These are the only components aware of multiple database platforms. Then, I have the services(the business logic). They do funky calculations, multiple data entity update within transactions etc.)

    Regards,

    Bisi Akintunde





  • SpoonmanUK

    The more I read and research this topic the more it seems to be just a matter of prefference. The OOP purists would tend to put all logic and properties in 1 Customer object. However, others might layer their design by having the Customer business logic in a separate class that manages the "the property only" customer business entity. I would imagine both approaches would work fine and get the job done.

    One thing to clarify: Can someone give a real world example of "persistence related code". I am just starting to get involved in design patterns and the jargon throws me off sometimes.



  • ShylaN

    Sreenath, since this thread attempts to address OOP I should mention that static methods are not really object-oriented, and therefore are harder to mock in tests and generally increase coupling. So I would rarely use static methods for this purpose, and I don't see how this should influence thread-safety...

    Arnon, general perpose persistence code definitely should not be a part of the customer object. However, specific code related to persistence of a customer object belongs in the Customer class. O/R mappers assume all specific code having to do with persistence of a Customer resides in the external interface (Properties, Constructor) or can be extracted with reflection. This is not always the case and forcing a design to support this paradigm is a liability.



  • ChrisMcCabe

    If you are trying to acheive runtime flexibility of your back end database an interface called ICustomerMethod would not suffice. First you must define an interface called IBackEndDatabase which Customer (or an implementation of ICustomerMethod) uses. This is because I assume Customer is not the only class being persisted in your application. Only then would you be able to switch from one database to another by a simple reimplemetation of an interface. If you stick with your current settings a change of the database will require a reimplementation of numerous interfaces, and this is the thing that usually scares people off of migrating to a different DBMS.

  • WayneSpangler

     Yoni Rapoport wrote:
    One of the basic priciples of OOP is Cohesion....

     Which is exactly why persistence related code should not be a part of the customer object (also see my blog on   Single Responsibility Principle)

    You can use O/R mapping to externalize the specifics of the persistence that are related to the customer

     

    Arnon



  • Kardi

    OK. But one argument I hear is that these business entities should be "light" if you plan on resusing via other services. Why pack them with domain specific logic if you want share them with other applications.

    The reason I bring this up is that I've been looking at the Microsoft PetShop v4 application and it uses this approach.



  • Danalynn

    Bisi, how does having business logic defined within a class affects its being lean and mean Since logic is usually non-persistent I don't see how it can affect the size of the object.

  • OOP Design Question - Need an opinion...