Monday 20 October 2014

Design Pattern : Light Weight Object

Introduction

This design pattern is one I use a lot and have done so for a long time, this might be similar to other patterns, if so please tell me so I can reference them. Although this looks like "yeah.. how else would you do this"  take a look at you objects for passing data and see if they contain bloat that would be better to be reduced.


Description

The Light Weight Object design pattern takes an object and reduces it to the absolute minimum for its intended purpose to increase speed and performance for systems. This means that you only pass the absolute bare object essentials rather than an object which is bloated with extra data and functionality that you might need (but most of the time don't). If you are passing large objects around in your application then it can be bad for performance, if you are passing hundreds or even thousands these between layers or are subject to serialization then this can have a very adverse effect on performance. This comes about by either design or function creep (or a mix of both).

Design

Large object by design are very common as all the functionality and methods to support the data (properties) is kept in a single place and its fairly easy to create large function rich objects that serve your business requirements well. Large objects are self descriptive and looks impressive and have all the functionality required to perform functions over the object life-cycle.

Function Creep

You start with an object, business or functionality changes come in; additional code added,  after a couple of major changes the object starts to bloat, functions are added to make calling calls easier to use the objects and old methods are often not removed. The objects starts to bloat and bloat as new functions and products are added to the application.

Classic Design 

One thing I've seem a lot in my development career is large objects, really large objects, C# classes with hundreds and even thousands of lines which carry a lot data and internal functionality.

Object- 1,000l+ lines
    |______   Properties
    |______   Methods
                          |______ Data Layer
                          |______ Serialization
                          |______ Business Logic
                          |______ Other Stuff...
         
   

I've seen large objects with as seen above with a mix or all of  the items mentioned.( and some with even more than you could imagine). This is extra baggage and is carried and supported by the system by functions that might be used or only used at initialization or used rarely.


Light Object Pattern

Keep the object you are passing around as small as possible and use service classes or layers to get data or perform functions as you need it.

Light Object --  50 lines

Data Layer  -- 300 lines
Business Logic -- 300 lines
Other Stuf --    nnn lines


Rules


  • Keep the object as small as possible
  • Remove methods to service layers
  • Only have a single use for the object (split if dual functions)
  • Remove unused  properties


When To Use

Use when you need to keep objects small and light ( you really should be doing this by default as good practice). if they are going to be placed in collection or used in large volumes. If you are running very large volumes of data in memory than this can make huge difference to your capacity and the performance of you systems.  Although  know your scale, will I have 100 users or 1 Million users on this system.

Pros


  • Lots of objects take up less memory
  • Quicker proccessing
  • Better OOP :  encapsulation, single use,
  • Better Testing 


Cons


  • More complex code
  • More re-factoring required
  • Objects are not as self descriptive
  • Developer has to know how to process the object


Example


Bob has a user object that contain the following which is created at login and held in session with the user. This is fairly standard and not as bloated as we think with of very large objects. Bob has noticed that each user only takes up a few kb  (kilo-bytes) of memory per user, but this is not really much but the amount of users is starting to hurt.

The user object

public class User
{
    public string SessionId  { get; set; }
    public int UserId { get; set;  }
    public string UserName  {get; set; }
    public string FullName  { get; set; }
    public string Email { get; set;  }
    public string Password { get; set;  }
    public string Address CurrentAddress { get; set; }
    public DateTime LastLogin { get; set;  }
    public DateTimecDateJoined  {get; set;  }
    public Bool AccountActive {get; set;  }
    public Bool LoggedIn { get; set;  }
    public string Address[]  PreviousAddress { get; set; }
    public string SecretQuestion { get; set; }
    public string Secret Answer {get; set;  }
    public void   Log (string message }
    public void Dispose()
    public bool Validate()
    public void Logout()
    private Log _log
}


This looks like a standard object, not too big with a few standard  methods you would expect.

But Bob has a problem, his user base is getting close to 250K users and the cost of his cloud bill seems to be going up a lot faster than the users on the system.  So Bob starts with the user object which is held in session for every user.

What can go or stay and why
  1. SessionId                           Not Needed, copy of system session field
  2. UserId                                Keep used in code
  3. UsedName                         Keep used for display
  4. FullName                           lose :  used rarely
  5. Email                                 lose :  used rarely
  6. Password                           delete not required in this 
  7. Address x 5                       lose :  used rarely
  8. Last Login                        delete not used 
  9. Date Joined                       delete not used
  10. AccountActive                 delete: If not active then it this object can't exist in session
  11. Logged In                         delete:  if not logged in then object not in session
  12. Previous Address             delete:  never used 
  13. Secret Question                delete : never used after login, only on lost password
  14. Secret Answer                  delete : never used after login, only on lost password
  15. Method :  Log                   move to service class
  16. Method :  Dispose             move dispose to service class as can be handled by session end or logout
  17. Method :  Validate            move to service class
  18. Method :  Logout              move to service class
  19. Method :  Other                 move to service class
  20. Object:   Log                     remove embedded logging object (NLOG, Log4Net etc..)

As can be seen you can reduce the user object for session storage to something like this

public class LightUser
{
     public int  UserId      { get; set; }   
     public string UsedName     { get; set; }
}


Although this does not represent the full user object/details it does cover  the user object used in 99% of the cases 99% of the time. 

Now bob can squeeze more session user objects in the  same memory space, he may have to make more calls to the service layers but this is a lot less cpu than the storage and service of the larger object footprint.


No comments:

Post a Comment

Comments are welcome, but are moderated and may take a wee while before shown.