Stateful or Stateless classes?

Jun 8, 2017

What is mean by state of an object?

Before we discuss about Stateless/Stateful classes, let’s have a better understanding of what is the meaning of the state of an object. It is defined as, “the particular condition that someone or something is in at a specific time.” of state.

In programming and with respect to the condition of object at a specific time, it is the value of its properties or member variables at a given point of time. Who decides what are the properties of objects? It is the class which decides what the properties are. In case of members inside a class, the programmer who codes that class is the decider.

Are we all experts in taking decision on what are the properties needed for each class? A programmer, me or you who is reading this blog?

I don’t think so. This holds true for now, when we are referring to most programmers in India. It is not something that can be taught in colleges but is gained through experience because programming here is still in its early stages compared to other engineering studies. Decision making is fluid and doesn’t have hard and fast rules.

In spite of more than 15 years’ experience in programming, I still need considerable time to decide what are the properties needed for a class and the name of the class itself.

Could we bring in rules on what are the properties needed? What properties should the state of an object include? Or should the objects be stateless always?

Below are some thoughts on this.

Entity classes / Business Objects

Entity classes, business objects, etc. are some names given to classes representing a clear state of something. In case of Employee class, its sole purpose is to hold the state of an employee. This state would contain: EmpId, Company, Designation, JoinedDate, etc. So far so good? This type of classes is familiar to all since this is taught in college.

But how we should do salary calculation?

  • Should the CalculateSalary() needs to be a method inside the Employee class?
  • Should there be a SalaryCalculator class and that class should contain the Calculate() method
  • In case there is SalaryCalculator class
    • Whether it should have properties such as BasicPay,DA HRA etc?
    • Or the Employee object needs to be a private member variable in that SalaryCalculator which is injected via constructor?
    • Or SalaryCalculator should expose Employee public property (Get&SetEmployee methods in Java)

Helper / Operation / Manipulator classes

This is the type of classes which do a task for example: SalaryCalculator. There are numerous examples of this type where classes do actions and can be found in programs with many prefix and suffixes such as:

  • class SomethingCalculator eg:SalaryCalculator
  • class SomethingHelper eg: DBHelper
  • class SomethingController eg: DBController
  • class SomethingManager
  • class SomethingExecutor
  • class SomethingProvider
  • class SomethingWorker
  • class SomethingBuilder
  • class SomethingAdapter
  • class SomethingGenerator

A long list can be found here. There are different opinions how suffix could be used in different situations. But let’s focus on whether we could add state to this type of classes. My suggestion is stateless. Let me explain why I am against state.

Hybrid classes

According to Wikipedia, encapsulation in object oriented programming is defined as, “Packing of data and functions into a single component”. Does this mean all the methods which manipulate that object should be there in the entity class? I don’t think so. The entity class can have state accessor methods such as GetName() ,SetName(), GetJoiningDate ,GetSalary(), etc.

But why CalculateSalary() should be outside?

According to the SOLID – Single Responsibility Principle, “A class should change only for one reason.” If we keep CalculateSalary() method inside the Employee class, that class will change in case of below mentioned 2 violations.

  • A state change in Employee class eg: A new property has been added to Employee
  • There is a change in the calculation logic

Now we have 2 classes in this context. Employee class and SalaryCalculator class. There are multiple ways in which they connect to each other. One is to create object of SalaryCalculator class inside the GetSalary method and call the Calculate() to set the salary variable of Employee class. Then it becomes hybrid as it is acting like entity class and it initiates operation like helper class. However, this type of hybrid classes should not be encouraged. In situations such as Save entity method, there could be some sort of delegation of operation. Whenever you feel that your class is falling in this hybrid category, think about re-factoring. If you feel that your classes are not falling in any of these categories, stop coding.

State in Helper / Manipulator class

What is the problem if our helper classes keep state? Before that, let’s look at what are the different combination of state values a SalaryCalculator class can take? Below are some examples.

Scenario 1 – Primitive values
class SalaryCalculator
    {
        public double Basic { get; set; }
        public double DA { get; set; }
        public string Designation { get; set; }
 
        public double Calculate()
        {
            //Calculate and return
        }
    }
Cons

There are chances that the Basic salary is of an Accountant and the Designation is “Director” causing mismatch. There is no one way to make sure that the SalaryCalculator can work independently. Similarly, if this executes in threaded environment, it will fail.

Scenario 2 – Object as state
class SalaryCalculator
    {
        public Employee Employee { get; set; }
 
        public double Calculate()
        {
            //Calculate and return
        }
    }
Cons

If one SalaryCalculator object is shared by 2 threads and each thread is for different employee, the sequence of execution might be as follows which cause logical errors.

  • Thread 1 sets employee1 object
  • Thread 2 sets employee2 object
  • Thread 1 calls Calculate method and gets Salary for employee2

We can argue that the Employee dependency can be injected via constrictor and make the property read only. Then we need to create SalaryCalculator objects for each and every employee object. So better not to design your helper classes in this way.

Scenario 3 – No state
   class SalaryCalculator
    {
        public double Calculate(Employee input)
        {
            //Calculate and return
        }
    }

This is a near perfect situation. But here, we can argue that, if all the methods are not using any member variable what is the use of keeping it as non static class?

The second principle in SOLID principles states, “Open for extension and closed for modification.” What does it mean? When we write a class, it should be complete. There should be no reason to modify it. However, it should be extensible via sub classing and overriding. So how would our final one looks like?

interface ISalaryCalculator
    {
        double Calculate(Employee input);
    }
    class SimpleSalaryCalculator:ISalaryCalculator
    {
        public virtual double Calculate(Employee input)
        {
            return input.Basic + input.HRA;
        }
    }
    class TaxAwareSalaryCalculator : SimpleSalaryCalculator
    {
        public override double Calculate(Employee input)
        {
            return base.Calculate(input)-GetTax(input);
        }
        private double GetTax(Employee input)
        {
            //Return tax
            throw new NotImplementedException();
        }
    }

Always program to interface. In the above code snippet, I implemented implicitly. The Logic of calculation should be kept in a protected function so that the inherited classes can call that function in case required.

Below is the way how this Calculator class should be consumed.

class SalaryCalculatorFactory
    {
        internal static ISalaryCalculator GetCalculator()
        {
            // Dynamic logic to create the ISalaryCalculator object
            return new SimpleSalaryCalculator();
        }
    }
    class PaySlipGenerator
    {
        void Generate()
        {
            Employee emp = new Employee() { };
            double salary =SalaryCalculatorFactory.GetCalculator().Calculate(emp);
        }
    }

The Factory class encapsulate the logic of deciding which child class to be used. It can be static as above or dynamic using reflection. As the reason for change in this class is object creation, we are not violating the “Single responsibility principle.”

In case you are going for Hybrid class and need to invoke from the Employee.GetSalary() as below.

class Employee
    {
        public string Name { get; set; }
        public int EmpId { get; set; }
        public double Basic { get; set; }
        public double HRA { get; set; }
        
        public double Salary
        {
            //NOT RECOMMENDED 
            get{return SalaryCalculatorFactory.GetCalculator().Calculate(this);}
        }
    }

This way we ensure that, even if there is change in the SalaryCalculation logic the Employee class will not change.

Conclusion

Don’t code when we are thinking. Don’t think when we are coding.

  • Spent some time on class design before coding. Show the class diagram to 2-3 fellow programmers and get their opinions.
  • Name the class wisely. There is no hard rule. But below are some I am following
    • Entity classes should be named with nouns which represents a type of object – eg: Employee
    • Helper / Worker class names should be reflecting that its a worker. eg: SalaryCalculator, PaySlipGenerator etc…
    • Verb should never be used as class name – eg:class CalculateSalary{}

This article has been re-published from author’s personal blog. For reference – Click Here

Joy George Kunjikkuru

Joy George Kunjikkuru

Solutions Architect

Joy is a passionate software engineer holding deep expertise in Microsoft technologies stack (.Net Windows Form, ASP.NET, Silverlight, SQL Server) as well as in open web technologies including JavaScript, AngularJS, TypeScript, HTML5, NodeJS, Azure, C#, ASP.Net MVC, WPF, WCF, Linq and many more.

Joy hold a MBA degree from Bharatiar University, Coimbatore and a B.Tech degree in Computer Science from Anna University, Chennai.

Subscribe to our Blog

Get updates on new articles, webinars, whitepapers and other resources.