Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Apex Design Patterns

You're reading from   Apex Design Patterns Harness the power of Apex design patterns to build robust and scalable code architectures on the Force.com platform

Arrow left icon
Product type Paperback
Published in Apr 2016
Publisher
ISBN-13 9781782173656
Length 256 pages
Edition 1st Edition
Languages
Arrow right icon
Authors (2):
Arrow left icon
Jitendra Zaa Jitendra Zaa
Author Profile Icon Jitendra Zaa
Jitendra Zaa
Anshul Verma Anshul Verma
Author Profile Icon Anshul Verma
Anshul Verma
Arrow right icon
View More author details
Toc

The SOLID principle

SOLID is short for basic five principles of OOP, which was introduced in the early 2000s and adopted widely in the software industry. When these principles are combined together, a programmer can create an application that will be easy to maintain and can be extended over time.

The SOLID abbreviation is defined as follows:

  • S: Single responsibility principle
  • O: Open closed principle
  • L: Liskov substitution principle
  • I: Interface segregation principle
  • D: Dependency inversion principle

The single responsibility principle (SRP)

This states that a class should have only one reason to change it, and this means, it should have a single job.

If we can write code for multiple functionalities in a class, it doesn't mean that we should. Smaller classes and smaller methods will give us more flexibility, and we don't have to write a lot of extra code. It saves us from over complicating classes and helps in achieving high cohesion.

For example, the Person class has the code to show the available balance and deduct it from Account. This is a clear violation of SRP. This class has two reasons to change: if any attribute of Person changes or any information about Account changes.

The advantages of SRP are as follows:

  • It makes code as easy as possible to reuse
  • Small classes can be changed easily
  • Small classes are more readable

Splitting classes is a way to implement SRP. Another example of the SRP violation is God classes, which we will discuss in the next chapter.

The open closed principle (OCP)

This states that entities of software, such as classes and methods, should be open for extension but closed for modification. This means that classes and methods should be allowed to be extended without modification.

For example, a class returns report data in the string and XML formats. In future, we may want to return data in the JSON or CSV format. We should not modify the existing class as it may have an impact on all the other classes using it. It would be a violation of OCP.

The importance of OCP lies in the following scenarios:

  • Any changes made in any existing code can potentially impact the entire system
  • In some conditions, we cannot change code (the managed package in Apex), so OCP is implied

We can implement OCP using design patterns, such as the strategy pattern. In the preceding scenario, we can create an interface of the ReportData type and different classes implementing that interface to return different report formats. We will discuss this in more detail in the upcoming chapters.

The Liskov substitution principle (LSP)

This states that if class B is a child of class A, then A can be replaced by B, without changing anything in a program. In other words, the LSP principle states that you should not encounter unexpected results if child (derived) classes are used instead of parent classes.

This principle is also known as Substitutability and was introduced by Barbara Liskov in 1987. This is one of the most widely used principles in programming. You might be already using this, but may not know that it is called LSP.

For example, let's say that we have a  Customer_Ticket class defined to close a case using the close() method. A  Customet_Ticket_Escalated child class is defined as well to handle an escalated case; however, it cannot close a case by a normal process because the customer was not happy. If we substitute a parent class by this child class and call the close() method, it will throw an exception, which is a clear violation of LSP.

The following code snippet explains this scenario:

public virual class Customer_Ticket{ 
    String status ; 
     
    public virtual void close(){ 
        status = 'close'; 
    } 
    //other code 
} 
 
public class Customet_Ticket_Escalated extends Customer_Ticket{ 
    public override void close(){ 
        throw new Exception('As this is escalated case therefore 
          cannot be closed by normal process'); 
    } 
    //other code 
} 

The anonymous Apex code for testing is as follows:

Customer_Ticket issue = new Customet_Ticket_Escalated(); 
issue.close();//runtime exception, violation of LSP 

To implement LSP, a proper use of inheritance with a protected access specifier is needed, and a parent class should not have any attributes, which may not apply to every child class.

The interface segregation principle (ISP)

This states that do not force a child class to depend on a method that is not used for them. This principle suggests that you break interfaces into smaller ones so that a client can only implement an interface that is of interest. This principle is very similar to the high cohesive principle, as discussed earlier.

One way to identify the ISP violation is if we implement any interface or derive a base class where we need to throw an exception for an unsupported operation.

The ISP are as follows:

  • It enforces the single responsibility principle for interfaces and base classes
  • Any changes made in the interface may affect child classes even though they are not using unused methods

For example, Product is an interface and contains the Name and Author attributes. Two child classes named Movie and Book are derived from Product. However, Movie is a Product but does not have an author, and therefore a runtime exception would be thrown if it's used.

The following example shows the valid and invalid code according to the ISP:

Violation of ISP

Adheres ISP

Public interface Product{
  Public String getName();
  Public String getAuthor();
}

Public Class Movie implements Product{
  private String movieName;
  private String author;

  Public String getName(){
    return movieName;
  }

  Public String getAuthor(){
    return new CustomException('Method not Supported');
  }
} 

Anonymous apex code for testing is as follows:

Product m = new Movie();
m.getAuthor();//runtime exception

Public interface Product{
  Public String getName();
  Public String getAuthor();
}

Public Class Book  implements Product{
  private String bookName;
  private String author;
  Public String getName(){
    return bookName;
  }

  Public String getAuthor(){
    return author;
  }
}

Anonymous apex code for testing is as follows:

Product p = new Book();
p.getAuthor(); //works

The dependency inversion principle (DIP)

This states that modules should not depend on each other directly and should depend via an interface (abstraction).

In other words, two classes should not be tightly coupled. Tightly coupled classes cannot work independently of each other, and if a change is required, then it creates a wave of changes throughout the application.

One way to identify a DIP violation is the use of a new keyword in the same class. If we are using a new keyword, then this means that we are trying to instantiate a class directly. We can create a container class to delegate the creation of a new object. This class will know how to instantiate another class on the basis of the interface type. This approach is also known as dependency injection or Inversion of Control (IoC). If you know about the trigger factory pattern that is widely used in Apex, then you may be able to relate with it, else we will discuss this in the upcoming chapters.

For example, in the real world you would not want to solder a lamp directly to the electrical wiring; we would rather use a plug so that the lamp can be used in any electric outlet. In this case, the lamp and electric outlet are the class and the plug is the interface.

Class A should not know any details about how class B is implemented. An interface should be used for communication. As discussed earlier, if needed we can always create a new child class from the interface and use it as per the LSP principle.

The following screenshot shows a scenario before and after DIP. In the first case, the Apex scheduler directly uses classes to calculate sharing and assigns a record to the user. All three classes are tightly coupled in this case. As per DIP, we need to introduce interfaces between them so that classes do not depend on implementation, but they will depend on the abstraction (interface).

The dependency inversion principle (DIP)

Tip

Downloading the example code

You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

You can download the code files by following these steps:

  1. Log in or register to our website using your e-mail address and password.
  2. Hover the mouse pointer on the SUPPORT tab at the top.
  3. Click on Code Downloads & Errata.
  4. Enter the name of the book in the Search box.
  5. Select the book for which you're looking to download the code files.
  6. Choose from the drop-down menu where you purchased this book from.
  7. Click on Code Download.

You can also download the code files by clicking on the Code Files button on the book's webpage at the Packt Publishing website. This page can be accessed by entering the book's name in the Search box. Please note that you need to be logged in to your Packt account.

Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:

  • WinRAR / 7-Zip for Windows
  • Zipeg / iZip / UnRarX for Mac
  • 7-Zip / PeaZip for Linux

The advantages of DIP are as follows:

  • Tight coupling is bad and everyone knows this
  • It's harder to write test classes as implementation details need to be known for other dependent classes
  • If DIP is followed, fake test records can be supplied to classes directly without knowing the implementation details
You have been reading a chapter from
Apex Design Patterns
Published in: Apr 2016
Publisher:
ISBN-13: 9781782173656
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image