Top Three Strategies for Moving From a Monolith to Microservices

One of the primary problems facing enterprises is the problem of moving from monolith to microservices. The larger the enterprise, the bigger their monolithic applications become, and it gets harder to refactor them into a microservices architecture.

Everyone seems to agree on the benefits of microservices. We covered this topic at some length in this post. However, not many seem to agree on how to undertake the migration journey. Too often, the decision-making process turns into a chicken-and-egg problem. The bigger the monolith, the bigger the stakeholders’ and management’s footprint becomes. Too much management often leads to decision paralysis and, ultimately, the journey ends up as a mess.

However, many organizations have successfully managed to make this transition. Often, it is a mix of good leadership and a well-defined strategy that determines success or failure.

Good leadership is often not in the hands of an architect or developer undertaking this journey. However, a strategy is. So, let’s look at some strategies that can help in this journey:

Implement New Functionalities as Services

I know it is hard. But if you’ve decided to transition from a monolith to microservices, you have to follow this strategy. Think of the monolithic system as a hole in the ground. To get out of a hole, you don’t dig more. In other words, you don’t add to your problems.

Often, organizations miss this part completely. They think about a grand migration strategy that will take years. However, business requirements come fast. Due to the lack of budget or time, teams end up implementing those requirements into the monolithic application. The grand migration strategy never starts for whatever reason. And, each addition to the monolith makes the goal-post move further ahead.

In order to get around this, stop increasing the size of the monolith. Don’t implement new features in the monolithic code base. Every new feature or functionality should be implemented as services. This, in turn, reduces the growth rate of the monolithic application. In other words, new features implemented as services create inertia towards the migration. It also helps demonstrate the value of the approach and ensures continuous investment.

Separate Presentation Layer From the Backend

This is an extremely powerful strategy to migrate from a monolith to microservices. A typical enterprise application usually has three layers:

  • Presentation logic that consists of modules implementing the web UI. This tier of the system is responsible for handling HTTP requests and generating HTML pages. In any respectable application, this tier has a substantial amount of code.
  • Business logic that consists of modules handling the business rules. Often, this can be quite complex in an enterprise application.
  • Data access logic that consists of modules handling the persistence of data. In other words, it deals with databases.

Usually, there is a clean separation between presentation logic and business logic. The business tier exposes a set of coarse-grained APIs. Basically, these APIs form an API Layer. In other words, this layer acts as a natural border based on which you can split the monolith. This approach is also known as horizontal slicing.

If done successfully, you’ll end up with smaller applications. One application will handle the presentation. The other application will handle the business and data access logic. There are various data management patterns for microservices that can be explored.

There are advantages to this approach:

  • You can develop, deploy, and scale both applications independently. In other words, UI developers can rapidly introduce changes to the interface. They don’t have to worry about the impact on the backend.
  • You will also have a set of well-defined APIs. Also, these APIs will be remotely accessible for use in other microservices.

Extract Business Functionalities Into Services

This is the pinnacle of moving to a microservices architecture. The previous two strategies will take you only so far. Even if you successfully implement them, you’ll still have a very monolithic code base. Basically, they can act only as a spring-board to the real deal.

If you want to make a significant move towards microservices, you need to break apart the monolithic code base. The best way to do this is by breaking up the monolith based on business functionality. Each business functionality is handled by one microservice. Each of these microservices should be independently deployable and scalable. Communication between these services should be implemented using remote API calls or through message brokers.

By using this strategy, over time, the number of business functions implemented as services will grow and your monolith will gradually shrink. This approach is also known as vertical slicing. Basically, you are dividing your domain into vertical slices or functionalities.

Conclusion

Moving from a monolith to microservices is not easy. It requires significant investment and management buy-in. On top of all that, it requires incredible discipline and skill from the team actually developing it. However, the advantages are many.

Often, it is a good idea to start small on this journey. Rather than waiting for a big one-shot move, try to take incremental steps, learn from mistakes, iterate, and try again. Also, don’t try to go for a perfect design from the get-go. Instead, be willing to iterate and improve.

Lastly, remember that microservices is not a destination but a journey. A journey of continuous improvement.

Let me know your thoughts and experiences about this in the comments section below.

Reducing Boilerplate Code in Java POJOs — Eliminating Getters/Setters and Minimizing POJO Mappings

“If you want to not write or even manually auto-generate the Getters and Setters in POJOs (Plain Old Java Objects) and want to get two POJOs mapped with less code, then read on for step by step instructions. Skip to Figure 1 for visual summary of this”.

Java has faced the criticism of being verbose in its syntax from the fans of other languages, and it’s quite fair, to be honest. With time, Java has evolved particularly to reduce its syntax verbosity with milestones from advanced for-each loop in Java 5 to try-with-resources in Java 7 to lambda expressions introduced in Java 8. All of these improvements address this issue elegantly, and make Java coding a lot easier and concise. Combine this with Spring Boot and you have a coding environment that’s miles ahead of Java coding environment from just a few years back in terms of speed of coding!

Still, there are things that a Java programmer has to do over and over again just to get the code complete from language/syntax point-of-view rather than spending time on business logic, the actual task at hand. Having to write or even auto-generate Getters and Setters in POJOs is one such issue. Having to map POJOs for data transfer from one layer to another is another cumbersome task that mostly just feels like a mere overhead. For example, presentation layer sees an entity differently than the service layer which in turn has a different shape from the same entity in persistence/DB layer. A lot of times developers find themselves writing mapping of these POJOs. What is even more painful is that maybe only a few fields differ and most of the rest of the fields have same name in source and target objects but we end up having to get and set them all from one object to another.

The above two problems can be addressed quite elegantly using a behind-the-scenes code generator like Project Lombok (introduced to me by my colleague, Carter) and a POJO mapper like MapStruct. This post will go through the example of eliminating the need to write or auto-generate Getters and Setters and of more concise mapping of one POJO to another (rather than manually doing something like target.setField(source.getField())).

Fig 1 displays the summary of this post and compares traditional POJOs and mappings with tools-facilitated light weight code to achieve same functionality.

Fig 1. TL;DR — Reducing Code: Summary of What This Post Shows Step by Step Instructions For.

Lombok provides annotations that can be declared on POJOs instead of writing Getters and Setters, Constructors, Loggers, etc. MapStruct is providing an automatic way of mapping POJOs, especially the ones that have attributes with same name and type, also using annotations. This can reduce a lot of development time and developers can focus on implementing business logic.


Code Walk Through

Following is a step-by-step walk-through to achieve the results in Fig 1. The environment is Eclipse (Spring Tool Suite IDE), Gradle (for building project and running jUnit test-cases), and Java 8 (on Mac OS X, although this shouldn’t matter other than menu buttons walk-through etc.).

(The code in this post will be shared here through GitHub soon. You can then download it from there instead of going through all the steps and use these steps as reference to read through where ever you need more details.)

  1. Let’s start by creating a new project in Eclipse:

 

Fig 2. Create New Gradle Project

2. Final Settings:

3. The project should like this with a default build.gradle file:

4. Next, we’ll change the default package to our own and start adding POJOs to it as follows:

We are assuming a scenario where we have a DTO (Data Transfer Object) POJO on one hand and an Entity (can be JPA or Hibernate or some other ORM or even manual SQL entry POJO), and we need to convert and copy data from one object to the other, bidirectional.

5. Let’s add FoodSampleDTO and use Eclipse to generate Getters and Setters (we will eventually eliminate this step):

6. And Select All fields and Finish:

This is what FoodSampleDTO looks like:

7. Follow same steps to create ProductDTO, which is a sub-object of FoodSampleDTO:

8. Let’s do the same for the POJO for our (superficial) persistence layer, SampleFoodEntity, to get:

You’ll notice that most of the fields are same in these POJOs with the exception of productId, which is a direct String field in FoodSampleEntity while it’s a sub-object in FoodSampleDTO. This is just an example and in real-world the POJOs will be much larger and differences can be much greater.

So now we want some mapper class to map data between DTO and Entity POJOs. This mapper will basically get data from one object and set it into another, with any necessary transformations.

9. Add FoodSampleMapper class in …mapper package and add two methods, one to convert DTO to Entity and other to convert Entity to DTO:

This is the second place where we want to reduce the manual work. As you can see, even though most fields have same name and type, we still have to get from one object and set into the other one. This can be cumbersome (and boring!) when the POJOs are large and in large number, which is typically the case.

Before looking at how to reduce these, let’s first write and run jUnit test-cases.

10. Under the source folder ‘src/test/java’, add a package …mapper and add a class FoodSampleMapperTests. This will have two methods to test our mapper’s two methods:

As you can see, we create our source object, populate some data in it, call our mapper to convert it to the other object and assert to ensure the data got copied and matches our original test data variables.

11. Run jUnit test-cases:

This is all good and business as usual. But cumbersome and boring to write and manually auto-generate this code.

Let’s reduce some coding!

First thing we are going to reduce is Getters and Setters using Lombok. Lombok provides annotations at compile-time to identify that you need Getters and Setters and hooks into the build process to generate the code. The POJOs stay lean (for check-in, check-out and editing purposes) but get the functionality of Getters and Setters auto-generated for run-time. Let’s setup Lombok.

12. Go to https://projectlombok.org/download and get the latest version of Lombok jar. Instructions for different IDEs and Build Tools can be found under “Install” drop down menu on the top bar at Lombok’s site.

13. Execute this jar to get the installer screen:

14. Select your IDE, hit Install/Update, then Quit Installer and restart your IDE:

15. Following the instructions on Lombok’s page, we’ll add a plugin and dependencies in our build.gradle file (the top section and last two lines, remember to save the file):

16. In Eclipse, Right-click the project, select Gradle > Refresh Gradle Project. This should resolve all new dependencies added to build.gradle file and bring them to Eclipse’s dependencies list. (This is where you might need to have a Gradle plugin for Eclipse, I’ve this one: http://marketplace.eclipse.org/content/buildship-gradle-integrationinstalled through Help > Eclipse Marketplace). Alternatively, you can use command line to build Gradle projects (you don’t even need to install Gradle just use gradlew files created in the project for commands like “./gradlew clean build”).

If all goes well, you should have Lombok provided annotations available in your project.

17. Remove all Getter and Setter methods and constructors from your POJOs and just annotate the POJO with Getter and Setter annotations:

Repeat this for all POJOs. Our POJOs now look like this:

Quite slick, eh? We’ve eliminated the need to auto-generate Getters and Setters and even writing constructors. We added a @NoArgsConstructor to FoodSampleEntity as it will be needed for MapStruct to work later on. We also added a @RequiredArgsConstructor to ProductDTO and made id a required field by using @NonNull, this way we can get the one-arg constructor auto-generated for us that’s needed by our existing test-cases: ProductDTO testProduct = new ProductDTO(testProductId);

Now we need to Clean/Build the project and re-run the jUnit test-cases to ensure they pass after these changes. We’ll setup Eclipse to invoke Gradle build from inside Eclipse instead of going to terminal for command line excecution.

18. Right click the build.gradle file, select Run As > Run Configurations, Choose Gradle Project in the left pane, click ‘New’ icon on top left of this pane and configure the Gradle build as follows and click Run:

This should result in a successful Gradle build, if all goes well:

The Console View should show something like:

The test task is successfully executed, passing our test-cases. Good!

Now, it’s time to get rid of that boring getFromSomeObject and setToAnotherObject mappings and replace it with simple annotations (only if field name and type is different! otherwise no mapping needs to be written as is the case for four of our five fields in POJOs).

So let’s setup MapStruct!

19. All we have to do is add MapStruct dependencies and Refresh Gradle Project:

20. Let’s create an interface ‘FoodSampleAutoMapper’ next to our (manual) mapper ‘FoodSampleMapper’, and annotate it with @Mapper (should be available if above dependencies have been successfully resolved):

We added two (abstract) methods to this interface, one for conversion of DTO to Entity and other for Entity to DTO. This small interface definition is all that’s needed to copy all fields with same name and type from one POJO to another! Incredible!

We’ll get to the fields that don’t have same name and type (like productId in our case). We also added an INSTANCE variable that will refer to an actual implementation class that implements this interface. But we don’t have to write that class, MapStruct will auto-generate this impl class for us behind the scenes and make it available at run-time much like Lombok does its magic. We don’t have to use INSTANCE variable, we can get the impl class inline with how our project searches for classes (e.g. you can use dependency injection using Spring, the @Mapper will need to be changed to @Mapper(componentModel = “spring”) and this way the generated class will have @Component annotation for Spring’s initialization to detect and make it available for DI).

21. We can simply switch our mapper to this interface. We’ll add another test class instead of modifying existing one, just copy/paste FoodSampleMapperTest class to FoodSampleAutoMapperTest class and change one line of code, to fetch the new mapper:

//Convert the DTO to entity object

FoodSampleEntity foodSampleEntity = FoodSampleAutoMapper.INSTANCE.mapFoodSampleDTOToEntity(foodSampleDTO);

We are using our interface’s INSTANCE method which will have the implementation class searched by Mappers.getMappers… call and this mapper class will be made available for our use. We can invoke mapFoodSampleDTOToEntity and mapFoodSampleEntityToDTO methods on the INSTANCE variable.

There’s no change in our test-cases except for above line:

22. Let’s try to run unit-tests which should fail. (Just go to Gradle Executions View (use Window > View > Other > (Type) Gradle if it doesn’t show up) and just press re-run icon to execute the build again. Alternatively, right click the project, Run As > Run Configurations and select Gradle Project config created in step # previously and Click Run.

As you can see, our previous test-cases are passing but new ones failed. The console on the right is showing two warnings that there’s an unmapped target property ‘productId’ in first mapper method and ‘product’ in the other one. This is because it is the only field in our POJOs that does not have same name and type in both POJOs so mapstruct doesn’t know how to convert this and it ignores it and just prints a warning. If we didn’t need this we can ignore the warning but in our test-cases we are expecting productId to be converted as well, therefore the actual failure of our test-cases throwing NullPointerException and AssertionError in line 71 and 40 respectively of our FoodSampleAutoMapperTest class. This is expected since we didn’t tell MapStruct how to map this field.

23. Now, let’s tell MapStruct how to map fields that are not that straight forward. Let’s use the powerful @Mapping annotation with attributes source and target to tell MapStruct how to convert productId to product.id:

We are telling MapStruct that for mapFoodSampleDTOToEntity method, when you are looking for productId (which is String in FoodSampleEntity target object), simply get the value from (the source) foodSampleDTO’s product field’s id field. And vice versa in mapFoodSampleEntityToDTO. Please note that we can add as many @Mapping lines as we need to specify the differences for each method, here we only have one difference per method, therefore only one @Mapping line.

In our example, we are just showing a difference in structure but in typical scenarios you will also find difference in types etc which will need more than just source/target mapping (see MapStruct’s excellent documentation for those cases, e.g. you can use expression and provide a Java line of code which will be placed as is in the generated class, providing a concise but powerful touch to these auto-mappings). You can also use dateFormat and MapStruct will automatically write DateParsing code with handling of DateParsing Exceptions. It can also do null checks and that strategy is also customizable, again refer to MapStruct documentation.

24. Run test-cases again with above change and these should pass with flying colors:


Conclusion

So there you have it, we have successfully reduced the code from Getters and Setters and manual mapping to some mere annotations:

Please let me know in comments if you find this post helpful or not, have any questions, issues or feedback.

Happy programming!

Design Patterns

What is the design patterns?

Design Patterns in javaIn this design patterns tutorial, we will explain all type of design patterns in java with example. A design pattern is a common solution that is used to test generally repetitive problems in software development. The design does not exist as a complete program that can be transformed into an object or machine code but, as a template identify problems in the system and provide appropriate solutions. The design pattern testing is not present in normal procedural programming and is mostly adopted by developers in Object Oriented environment. These provide the interaction on Object-Oriented level involving classes and objects.It is used as an efficient programming approach where Object Oriented systems are being developed to provide robustly and error-free software generation.

Spring 5 Design Pattern Book

You could purchase my Spring 5 book that is with title name “Spring 5 Design Pattern“. This book is available on the Amazon and Packt publisher website. Learn various design patterns and best practices in Spring 5 and use them to solve common design problems. You could use author discount to purchase this book by using code- “AUTHDIS40“.
Spring-5-Design-Pattern

Need for Design Patterns

With the emerging needs of technology and the growth in the IT industry, typical software development practices, that required the completion of the entire software before testing, has also evolved. To avoid reverting to the stage of development after completion, a testing practice during development phase was introduced. It can be used to identify error conditions and problems in the code that may not be apparent at the time. The end modules that are obtained are already tested and are less error-prone.

Designing a template that can be reused on multiple codes saves time for test creation and is easy to understand by developers with prior experience working with it. The templates are code and problem independent and do not need to be specified by coders to deal with a problem

Types of Design Patterns

Design patterns are classified into four main categories and each individual design pattern in the category make up a total of 23 design patterns. The four main categories are:

observer-software-design-pattern-5-638

  1. Creational Pattern
  2. Structural Pattern
  3. Behavioral Pattern
  4. J2EE Pattern

Creational Patterns

Creational Pattern is mostly concerned with the manner involved with creating class instances. It is further characterized as class-creation and object-creation Patterns. The object creation or instantiation is done implicitly using design patterns rather than directly. Thus, for a use-case, there is flexibility involved with the object creation.

  • Abstract Factory
    In this pattern, a factory of related objects is created by an interface without specification of the class name. The factory passes the objects by following the Factory Pattern.
  • Builder
    This pattern is used for a stage by stage creation of a complex object by combining simple objects. The final object creation depends on the stages of the creative process but is independent of other objects.
  • Factory Method
    This pattern is employed mostly during development in Java. It provides implicit object instantiation through common interfaces.
  • Object Pool
    Object pooling is used to reduce object creation cost when it is high for certain process and thus improves performance. It employs the method of object caching and simply retrieves objects from the cache pool instead of having to create it. The number of objects in the pool can be restricted to keep from continual growth.
  • Prototype
    In Prototype patterns, object duplication is performed while performance is monitored. A prototype interface pattern is present to produce a copy of an object. It is used to restrict memory/database operations by keeping modification to a minimum using object copies.
  • Singleton
    This pattern involves the present of one class and restricting object creation to a single object. The presence of a single object removes the need for object instantiation for accessing.

Structural Patterns

Structural Patterns deal with the composition of classes and objects. Inheritance is employed for interface composition and methods for addition of new functionalities are introduced by object composition. A better understanding of the entity relationship is established. Abilities of independent interfaces are combined in structural patterns.

  • Adapter
    To link two interfaces that are not compatible and utilize their functionalities, Adapter pattern is used. It is used to provide a new interface covering for any existing class.
  • Bridge
    In Bridge Pattern, there is a structural alteration in the main and interface implementer classes without having any effect on each other. These two classes are made independent of each other and are only connected by using the bridge which is an interface.
  • Composite
    Composite Pattern is used group together objects as one object. The objects are composed in a tree structure form with the representation of individual tree nodes and the hierarchy as well. The objects belonging to the same groups are modified using this pattern.
  • Decorator
    Decorator pattern restricts the alteration of object structure while a new functionality is added to it. The initial class remains unaltered while a decorator class wraps around it and provides extra capabilities.
  • Façade
    Façade provides clients with access to the system but conceals the working of the system and its complexities. The pattern creates one class consisting of user functions and delegates provide calling facilities to the classes belonging to the systems.
  • Flyweight
    Flyweight pattern is used to reduce memory usage and improve performance by cutting on object creation. The pattern looks for similar objects that already exist to reuse it rather than creating new ones that are similar.
  • Private Class Data
    Some of the class attributes may be available without requirement and thus may be prone to be corrupted. To prevent that the attributes may be allowed to be manipulated only once during operation after which it becomes private and thus data is protected.
  • Proxy
    It is used to create objects that may represent functions of other classes or objects and the interface is used to access these functionalities.

Behavioral patterns

Behavioral pattern deals with the communication between class objects. They are used to sense the presence of already present communication patterns and may be able to manipulate these patterns.

  • Chain of responsibility
    A chain of objects is created to deal with the request so that no request goes back unfulfilled.
  • Command
    Command pattern deals with requests by hiding it inside an object as a command and sent to be to invoker object which then passes it to an appropriate object that can fulfill the request.
  • Interpreter
    Interpreter pattern is used for language or expression evaluation by creating an interface that tells the context for interpretation.
  • Iterator
    Iterator pattern is used to provide sequential access to a number elements present inside a collection object without any relevant information exchange.
  • Mediator
    Mediator pattern provides easy communication through its mediator class that allows communication for several classes.
  • Memento
    Memento pattern involves the working of three classes Memento, CareTaker, and Originator. Memento holds the restorable state of the object. Originator’s job is the creation and storing of state and CareTaker’s job is the restoration of memento states.
  • Null Object
    Null Object is used instead of specifying a Null value and is used to represent a particular operation that does nothing when created. It is basically a check for Null value without the presence of the value.
  • Observer
    A One-to-Many relationship calls for the need of Observer pattern to check the relative dependencies of objects.
  • State
    In State pattern, the behavior of a class varies with its state and is thus represented by the context object.
  • Strategy
    Strategy pattern deals with the change in class behavior at runtime. The objects consist of strategies and the context object judges the behavior at runtime of each strategy.
  • Template method
    It is used with components having similarity where a template of the code may be implemented to test both the components. The code can be changed with minor alterations.
  • Visitor
    A Visitor performs a set of operations on an element class and changes its behavior of execution. Thus the variance in the behavior of element class is dependent on the change in visitor class.

J2EE Patterns

J2EE stands for Java 2 Enterprise Edition currently known as Java Enterprise Edition (J EE). It consists of many APIs that provide software developers with the capabilities to write server-side code. The J2EE patterns deal with testing on the presentation tier as offered by Sun Java Center. These design patterns are specifically concerned with the following listed layers.

  • Presentation Layer
  • Business Layer
  • Integration Layer

Core J2EE Pattern Catalog

Presentation Tier

  • Intercepting Filter
    It is used to provide interception and manipulation of requests as well as response prior to and preceding the processing of the request.   readmore
  • Context Object
    Context Object is present to keep from using system information that is specific to the protocol and doesn’t coincide with its context.   readmore
  • Front Controller
    A centralized access point allows for non-duplication of the control logic needed to handle a request. Front Controller is to handle such request by acting as an initial point.   readmore
  • Application Controller
    It provides support for action reuse and code to view-management. The code is made more readable and maintainable as well as modular. Request handling is also improved and made more extensible.   readmore
  • View Helper
    It is used to provide a different view, hiding the logic present in the code. Now the logic and the view are completely independent to provide ease for developers and designers.   readmore
  • Composite View
    Small sub views can be created using the composite view. These sub views can be integrated to create a singular view.   readmore
  • Dispatcher View
    To be able to support a small amount of multitasking, dispatcher view is used. It provides handling and response generation for requests while a business processing is taking place.   readmore
  • Service to Worker
    It is used to perform handling of requests as well as processing of the business transaction and after that, the control is transferred to the View.   readmore

Business Tier

  • Business Delegate
    The business delegate pattern is one of the Java EE design patterns. It is used in order to decouple or reduce the coupling between the presentation tier and business services.   readmore
  • Service Locator
    The design pattern, service locator is an important part in software development. Looking up for a service is one of the core features of service locator. A robust abstraction layer performs this function. The design pattern uses a central registry called Service Locator.   readmore
  • Session Facade
    The session façade pattern’s core application is development of enterprise apps. You can also call it a logical extension of GoF designs. The pattern encases the interactions which are happening between the low-level components, which is Entity EJB.   readmore
  • Business Object
    Object-oriented programming makes use of the business object. It represents the parts of a business. A business object is able to represent things like event, person, business process, place, and concept. The business object can exist in certain forms like a product, an invoice, and the details of a particular part of a transaction.   readmore
  • Composite Entity
    It is one if the Java EE software-design patterns. The composite entity pattern performs modeling, managing and representing a set of interrelated persistent objects. It does not represent them as separate fine-grained entity beans. Composite entity beans are able to represent a graph of objects.   readmore
  • Transfer Object
    It is one of the Java EE design patterns. We need transfer object when we need to pass the data across various attributes in a packet to the server. Value Object is another name for transfer object. The transfer object is just a class of POJO which has a method of the getter and setter.   readmore

Integration Tier

  • Data Access Object
    The data access object in a computer software which is as an object which is responsible for providing abstract interface for communication to a specific form of database.   readmore
  • Service Activator
    The service activator design pattern is one of the Java EE patterns. It is an SI (spring integration) component. It is responsible for triggering or activating a service object or bean which is managed by the spring. A service activator searches through the message channel in order to look for messages.   readmore
  • Web Service Broker
    The web service broker uses web protocols and XML. We can use this pattern to expose and broker the services. Assume a circumstance, where multiple organizations are lined up in order to request info from a number of service providers.   readmore

Happy Design Patterns Learning with us!!!

What Does RandomAccess Mean?

RandomAccess is a marker interface, like the Serializable and Cloneable interfaces. All these marker interfaces do not define methods. Instead, they identify a class as having a particular capability. In the case of Serializable, the interface specifies that if the class is serialized using the serialization I/O classes, a NotSerializableException will not be thrown (unless the object contains some other class that cannot be serialized). Cloneable similarly indicates that the use of the Object.clone( ) method for a Cloneable class will not throw aCloneNotSupportedException.

The RandomAccess interface identifies that a particular java.util.List implementation has fast random access. (A more accurate name for the interface would have been “FastRandomAccess.”) This interface tries to define an imprecise concept: what exactly is fast? The documentation provides a simple guide: if repeated access using the List.get( ) method is faster than repeated access using the Iterator.next( ) method, then the List has fast random access. The two types of access are shown in the following code examples.

Repeated access using List.get( ):

Object o;
for (int i=0, n=list.size(  ); i < n; i++)
  o = list.get(i);

Repeated access using Iterator.next( ):

Object o;
for (Iterator itr=list.iterator(  ); itr.hasNext(  ); )
  o = itr.next(  );

A third loop combines the previous two loops to avoid the repeated Iterator.hasNext( ) test on each loop iteration:

Object o;
Iterator itr=list.iterator(  );
for (int i=0, n=list.size(  ); i < n; i++)
  o = itr.next(  );

This last loop relies on the normal situation where List objects cannot change in size while they are being iterated through without an exception of some sort occurring. So, because the loop size remains the same, you can simply count the accessed elements without testing at each iteration whether the end of the list has been reached. This last loop is generally faster than the previous loop with the Iterator.hasNext( ) test. In the context of the RandomAccess interface, the first loop using List.get( ) should be faster than both the other loops that use Iterator.next( ) for a list to implement RandomAccess.

How Is RandomAccess Used?

So now that we know what RandomAccess means, how do we use it? There are two aspects to using the other marker interfaces, Serializable and Cloneable: defining classes that implement them and using their capabilities via ObjectInput /ObjectOutput and Object.clone( ), respectively.RandomAccess is a little different. Of course, we still need to decide whether any particular class implements it, but the possible classes are severely restricted: RandomAccess should be implemented only in java.util.List classes. And most such classes are created outside of projects. The SDK provides the most frequently used implementations, and subclasses of the SDK classes do not need to implement RandomAccess because they automatically inherit the capability where appropriate.

The second aspect, using the RandomAccess capability, is also different. Whether a class is Serializable or Cloneable is automatically detected when you use ObjectInput/ObjectOutput and Object.clone( ). But RandomAccess has no such automatic support. Instead, you need to explicitly check whether a class implements RandomAccess using the instanceof operator:

if (listObject instanceof RandomAccess)
  ...

You must then explicitly choose the appropriate access method, List.get( ) or Iterator.next( ). Clearly, if we test for RandomAccess on every loop iteration, we would be making a lot of redundant calls and probably losing the benefit of RandomAccess as well. So the pattern to follow in usingRandomAccess makes the test outside the loop. The canonical pattern looks like this:

Object o;
if (listObject instanceof RandomAccess)
{
  for (int i=0, n=list.size(  ); i < n; i++)
  {
    o = list.get(i);
    //do something with object o
  }
   
}
else
{
  Iterator itr = list.iterator(  );
  for (int i=0, n=list.size(  ); i < n; i++)
  {
    o = itr.next(  );
    //do something with object o
   
  }
}

Speedup from RandomAccess

I tested the four code loops shown in this section, using the 1.4 release, separately testing the -client (default) and -server options. To test the effect of the RandomAccess interface, I used the java.util.ArrayList and java.util.LinkedList classes. ArrayList implements RandomAccess, while LinkedList does not. ArrayList has an underlying implementation consisting of an array with constant access time for any element, so using the ArrayList iterator is equivalent to using the ArrayList.get( ) method but with some additional overhead. LinkedList has an underlying implementation consisting of linked node objects with access time proportional to the shortest distance of the element from either end of the list, whereas iterating sequentially through the list can shortcut the access time by traversing one node after another.

Times shown are the average of three runs, and all times have been normalized to the first table cell, i.e., the time taken by the ArrayList to iterate the list using the List.get( ) method in client mode.

Loop type (loop test) and access method

ArrayList java -client

LinkedList java -client

ArrayList java -server

LinkedList java -server

loop counter (i<n) and List.get( )

100%

too long

77.5%

too long

iterator (Iterator.hasNext( )) and Iterator.next( )

141%

219%

109%

213%

iterator (i<n) and Iterator.next( )

121%

205%

98%

193%

RandomAccess test with loop from row 1 or 3

100%

205%

77.5%

193%

The most important results are in the last two rows. The last line shows the times obtained by making full use of the RandomAccess interface, and the line before that shows the most optimal general technique for iterating lists if RandomAccess is not available. The size of the lists I used for the test (and consequently the number of loop iterations required to access every element) was sufficiently large that the instanceof test had no measurable cost in comparison to the time taken to run the loop. Consequently, we can see that there was no cost (but also no benefit) in adding the instanceofRandomAccess test when iterating the LinkedList, whereas the ArrayList was iterated more than 20% quicker when the instanceof test was included.

Forward and Backward Compatibility

Can you use RandomAccess and maintain backward compatibility with VM versions prior to 1.4? There are three aspects to using RandomAccess:

  • You may want to include code referencing RandomAccess without moving to 1.4.

  • Many projects need their code to be able to run in any VM, so the code needs to be backward-compatible to run in VMs using releases earlier than 1.4, where RandomAccess does not exist.

  • You will want to make your code forward-compatible so that it automatically takes advantage of RandomAccess when running in a 1.4+ JVM.

Making RandomAccess available to your development environment is the first issue, and if you are using an environment prior to 1.4, this can be as simple as adding the RandomAccess interface to your classpath. Any version of the SDK can create the RandomAccess interface. The definition for RandomAccess is:

package java.util;
public interface RandomAccess {  }

We also need to handle RandomAccess in the runtime environment. For pre-1.4 environments, the test:

if (listObject instanceof RandomAccess)

generates a NoClassDefFoundError at runtime when the JVM tries to load the RandomAccess class (for the instanceof test to be evaluated, the class has to be loaded). However, we can guard the test so that it is executed only if RandomAccess is available. The simplest way to do this is to check whether RandomAccess exists, setting a boolean guard as the outcome of that test:

static boolean RandomAccessExists;
...
   
  //execute this as early as possible after the application starts
  try
  {
    Class c =  Class.forName("java.util.RandomAccess");
    RandomAccessExists = true;
  }
  catch (ClassNotFoundException e)
  {
    RandomAccessExists = false;
  }

Finally, we need to change our instanceof tests to use the RandomAccessExists variable as a guard:

if (RandomAccessExists && (listObject instanceof RandomAccess) )

With the guarded instanceof test, the code automatically reverts to the Iterator loop if RandomAccess does not exist and should avoid throwing a NoClassDefFoundError in pre-1.4 JVMs. And, of course, the guarded instanceof test also automatically uses the faster loop branch whenRandomAccess does exist and the list object implements it.

Singleton Design Pattern

Singleton is a part of Gang of Four design pattern and it is categorized under creational design patterns. In this article, we are going to take a deeper look into the usage of the Singleton pattern. It is one of the most simple design pattern in terms of the modelling but on the other hand this is one of the most controversial pattern in terms of complexity of usage.

Singleton pattern is a design pattern which restricts a class to instantiate its multiple objects. It is nothing but a way of defining a class. Class is defined in such a way that only one instance of class is created in the complete execution of program or project. It is used where only a single instance of class is required to control the action throughout the execution. A singleton class shouldn’t have multiple instances in any case and at any cost. Singleton classes are used for logging, driver objects, caching and thread pool, database connections.

create-singleon-class

Implementation of Singleton class

An implementation of singleton class should have following properties:

  1. It should have only one instance : This is done by providing instance of class from within the class. Outer classes or subclasses should be prevented to create the instance. This is done by making the constructor private in java so that no class can access the constructor and hence cannot instantiate it.
  2. Instance should be globally accessible : Instance of singleton class should be globally accessible so that each class can use it. In java it is done by making the access-specifier of instance public.
//A singleton class should have public visiblity
//so that complete application can use
public class GFG {
  
  //static instance of class globally accessible
  public static GFG instance = new GFG();
  private GFG() {
    // private constructor so that class
    //cannot be instantiated from outside
    //this class
  }
}

Detailed Article: Implementation of Singleton Design Pattern in Java

Initialization Types of Singleton

    Singleton class can be instantiated by two methods:

  1. Early initialization : In this method, class is initialized whether it is to be used or not. Main advantage of this method is its simplicity. You initiate the class at the time of class loading. Its drawback is that class is always initialized whether it is being used or not.
  2. Lazy initialization : In this method, class in initialized only when it is required. It can save you from instantiating the class when you don’t need it. Generally lazy initialization is used when we create a singleton class.

Examples of Singleton class

  1. java.lang.Runtime : Java provides a class Runtime in its lang package which is singleton in nature. Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime() method.
    An application cannot instantiate this class so multiple objects can’t be created for this class. Hence Runtime is a singleton class.
  2. java.awt.Desktop : The Desktop class allows a Java application to launch associated applications registered on the native desktop to handle a URI or a file.
    Supported operations include:

    • launching the user-default browser to show a specified URI;
      launching the user-default mail client with an optional mailto URI;
    • launching a registered application to open, edit or print a specified file.
    • This class provides methods corresponding to these operations. The methods look for the associated application registered on the current platform, and launch it to handle a URI or file. If there is no associated application or the associated application fails to be launched, an exception is thrown.
    • Each operation is an action type represented by the Desktop.Action class.

    This class also cannot be instantiated from application. Hence it is also a singleton class.

Applications of Singleton classes

There is a lot of applications of singleton pattern like cache-memory, database connection, drivers, logging. Some major of them are :-

  1. Hardware interface access: The use of singleton depends on the requirements. Singleton classes are also used to prevent concurrent access of class. Practically singleton can be used in case external hardware resource usage limitation required e.g. Hardware printers where the print spooler can be made a singleton to avoid multiple concurrent accesses and creating deadlock.
  2. Logger : Singleton classes are used in log file generations. Log files are created by logger class object. Suppose an application where the logging utility has to produce one log file based on the messages received from the users. If there is multiple client application using this logging utility class they might create multiple instances of this class and it can potentially cause issues during concurrent access to the same logger file. We can use the logger utility class as a singleton and provide a global point of reference, so that each user can use this utility and no 2 users access it at same time.
  3. Configuration File: This is another potential candidate for Singleton pattern because this has a performance benefit as it prevents multiple users to repeatedly access and read the configuration file or properties file. It creates a single instance of the configuration file which can be accessed by multiple calls concurrently as it will provide static config data loaded into in-memory objects. The application only reads from the configuration file at the first time and there after from second call onwards the client applications read the data from in-memory objects.
  4. Cache: We can use the cache as a singleton object as it can have a global point of reference and for all future calls to the cache object the client application will use the in-memory object.

Important points

  • Singleton classes can have only one instance and that instance should be globally accessible.
  • java.lang.Runtime and java.awt.Desktop are 2 singleton classes provided by JVM.
  • Singleton Design pattern is a type of creational design pattern.
  • Outer classes should be prevented to create instance of singleton class.

How to prevent Singleton Pattern from Reflection, Serialization and Cloning?

In this article, we will see that what are various concepts which can break singleton property of a class and how to avoid them. There are mainly 3 concepts which can break singleton property of a class. Let’s discuss them one by one.

  1. Reflection: Reflection can be caused to destroy singleton property of singleton class, as shown in following example:
    // Java code to explain effect of Reflection
    // on Singleton property
    import java.lang.reflect.Constructor;
    // Singleton class
    class Singleton
    {
        // public instance initialized when loading the class
        public static Singleton instance = new Singleton();
        
        private Singleton()
        {
            // private constructor
        }
    }
    public class GFG
    {
        public static void main(String[] args)
        {
            Singleton instance1 = Singleton.instance;
            Singleton instance2 = null;
            try
            {
                Constructor[] constructors =
                        Singleton.class.getDeclaredConstructors();
                for (Constructor constructor : constructors)
                {
                    // Below code will destroy the singleton pattern
                    constructor.setAccessible(true);
                    instance2 = (Singleton) constructor.newInstance();
                    break;
                }
            }
        
            catch (Exception e)
            {
                e.printStackTrace();
            }
            
        System.out.println("instance1.hashCode():- "
                                          + instance1.hashCode());
        System.out.println("instance2.hashCode():- "
                                          + instance2.hashCode());
        }
    }
    Output:-
    instance1.hashCode():- 366712642
    instance2.hashCode():- 1829164700
    

    After running this class, you will see that hashCodes are different that means, 2 objects of same class are created and singleton pattern has been destroyed.

    Overcome reflection issue: To overcome issue raised by reflection, enums are used because java ensures internally that enum value is instantiated only once. Since java Enums are globally accessible, they can be used for singletons. Its only drawback is that it is not flexible i.e it does not allow lazy initialization.

    //Java program for Enum type singleton
    public enum GFG
    {
      INSTANCE;
    }

    As enums don’t have any constructor so it is not possible for Reflection to utilize it. Enums have their by-default constructor, we can’t invoke them by ourself. JVM handles the creation and invocation of enum constructors internally. As enums don’t give their constructor definition to the program, it is not possible for us to access them by Reflection also. Hence, reflection can’t break singleton property in case of enums.

  2. Serialization:- Serialization can also cause breakage of singleton property of singleton classes. Serialization is used to convert an object of byte stream and save in a file or send over a network. Suppose you serialize an object of a singleton class. Then if you de-serialize that object it will create a new instance and hence break the singleton pattern.
    // Java code to explain effect of
    // Serilization on singleton classes
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInput;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutput;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    class Singleton implements Serializable
    {
        // public instance initialized when loading the class
        public static Singleton instance = new Singleton();
        
        private Singleton()
        {
            // private constructor
        }
    }
    public class GFG
    {
        public static void main(String[] args)
        {
            try
            {
                Singleton instance1 = Singleton.instance;
                ObjectOutput out
                    = new ObjectOutputStream(new FileOutputStream("file.text"));
                out.writeObject(instance1);
                out.close();
        
                // deserailize from file to object
                ObjectInput in
                    = new ObjectInputStream(new FileInputStream("file.text"));
                
                Singleton instance2 = (Singleton) in.readObject();
                in.close();
        
                System.out.println("instance1 hashCode:- "
                                                     + instance1.hashCode());
                System.out.println("instance2 hashCode:- "
                                                     + instance2.hashCode());
            }
            
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    Output:- 
    instance1 hashCode:- 1550089733
    instance2 hashCode:- 865113938
    

    As you can see, hashCode of both instances is different, hence there are 2 objects of a singleton class. Thus, the class is no more singleton.

    Overcome serialization issue:- To overcome this issue, we have to implement method readResolve() method.

    // Java code to remove the effect of
    // Serialization on singleton classes
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInput;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutput;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    class Singleton implements Serializable
    {
        // public instance initialized when loading the class
        public static Singleton instance = new Singleton();
        
        private Singleton()
        {
            // private constructor
        }
        
        // implement readResolve method
        protected Object readResolve()
        {
            return instance;
        }
    }
    public class GFG
    {
        public static void main(String[] args)
        {
            try
            {
                Singleton instance1 = Singleton.instance;
                ObjectOutput out
                    = new ObjectOutputStream(new FileOutputStream("file.text"));
                out.writeObject(instance1);
                out.close();
            
                // deserailize from file to object
                ObjectInput in
                    = new ObjectInputStream(new FileInputStream("file.text"));
                Singleton instance2 = (Singleton) in.readObject();
                in.close();
            
                System.out.println("instance1 hashCode:- "
                                               + instance1.hashCode());
                System.out.println("instance2 hashCode:- "
                                               + instance2.hashCode());
            }
            
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    Output:- 
    instance1 hashCode:- 1550089733
    instance2 hashCode:- 1550089733
    

    Above both hashcodes are same hence no other instance is created.

  3. Cloning: Cloning is a concept to create duplicate objects. Using clone we can create copy of object. Suppose, we ceate clone of a singleton object, then it wil create a copy that is there are two instances of a singleton class, hence the class is no more singleton.
    // JAVA code to explain cloning
    // issue with singleton
    class SuperClass implements Cloneable
    {
      int i = 10;
      @Override
      protected Object clone() throws CloneNotSupportedException
      {
        return super.clone();
      }
    }
    // Singleton class
    class Singleton extends SuperClass
    {
      // public instance initialized when loading the class
      public static Singleton instance = new Singleton();
      private Singleton()
      {
        // private constructor
      }
    }
    public class GFG
    {
      public static void main(String[] args) throws CloneNotSupportedException
      {
        Singleton instance1 = Singleton.instance;
        Singleton instance2 = (Singleton) instance1.clone();
        System.out.println("instance1 hashCode:- "
                               + instance1.hashCode());
        System.out.println("instance2 hashCode:- "
                               + instance2.hashCode());
      }
    }
    Output :- 
    instance1 hashCode:- 366712642
    instance2 hashCode:- 1829164700
    

    Two different hashCode means there are 2 different objects of singleton class.

    Overcome Cloning issue:- To overcome this issue, override clone() method and throw an exception from clone method that is CloneNotSupportedException. Now whenever user will try to create clone of singleton object, it will throw exception and hence our class remains singleton.

    // JAVA code to explain overcome
    // cloning issue with singleton
    class SuperClass implements Cloneable
    {
      int i = 10;
      @Override
      protected Object clone() throws CloneNotSupportedException
      {
        return super.clone();
      }
    }
    // Singleton class
    class Singleton extends SuperClass
    {
      // public instance initialized when loading the class
      public static Singleton instance = new Singleton();
      private Singleton()
      {
        // private constructor
      }
      @Override
      protected Object clone() throws CloneNotSupportedException
      {
        throw new CloneNotSupportedException();
      }
    }
    public class GFG
    {
      public static void main(String[] args) throws CloneNotSupportedException
      {
        Singleton instance1 = Singleton.instance;
        Singleton instance2 = (Singleton) instance1.clone();
        System.out.println("instance1 hashCode:- "
                             + instance1.hashCode());
        System.out.println("instance2 hashCode:- "
                             + instance2.hashCode());
      }
    }
    Output:-
    Exception in thread "main" java.lang.CloneNotSupportedException
    	at GFG.Singleton.clone(GFG.java:29)
    	at GFG.GFG.main(GFG.java:38)
    

    Now we have stopped user to create clone of singleton class. If you don;t want to throw exception you can also return the same instance from clone method.

    // JAVA code to explain overcome
    // cloning issue with singleton
    class SuperClass implements Cloneable
    {
      int i = 10;
      @Override
      protected Object clone() throws CloneNotSupportedException
      {
        return super.clone();
      }
    }
    // Singleton class
    class Singleton extends SuperClass
    {
      // public instance initialized when loading the class
      public static Singleton instance = new Singleton();
      private Singleton()
      {
        // private constructor
      }
      @Override
      protected Object clone() throws CloneNotSupportedException
      {
        return instance;
      }
    }
    public class GFG
    {
      public static void main(String[] args) throws CloneNotSupportedException
      {
        Singleton instance1 = Singleton.instance;
        Singleton instance2 = (Singleton) instance1.clone();
        System.out.println("instance1 hashCode:- "
                               + instance1.hashCode());
        System.out.println("instance2 hashCode:- "
                               + instance2.hashCode());
      }
    }
    Output:-
    instance1 hashCode:- 366712642
    instance2 hashCode:- 366712642
    

    Now, as hashcode of both the instances is same that means they represent a single instance.

10 Object Oriented Design Principles Java Programmer should know

Object Oriented Design Principles are core of OOP programming, but I have seen most of the Java programmers chasing design patterns like Singleton pattern, Decorator pattern or Observer pattern, and not putting enough attention on learning Object oriented analysis and design. It’s important to learn basics of Object oriented programming like Abstraction, Encapsulation, Polymorphism and Inheritance. But, at the same time, it’s equally important to know object oriented design principles, to create clean and modular design. I have regularly seen Java programmers and developers of various experience level, who either doesn’t heard about these OOP and SOLID design principle, or simply doesn’t know what benefits a particular design principle offers, or how to apply these design principle in coding.

Bottom line is, always strive for highly cohesive and loosely couple solution, code or design. Looking open source code from Apache and Sun are good examples of learning Java and OOPS design principles. They show us,  how design principles should be used in coding and Java programs. Java Development Kit follows several design principle like Factory Pattern in BorderFactory class,  Singleton pattern in Runtime class, Decorator pattern on various java.io classes. By the way if you really interested more on Java coding practices then read Effective Java by Joshua Bloch , a gem by the guy who wrote Java Collection API.

If you are interested in learning object oriented principles and patterns, then you can look at my another personal favorite Head First Object Oriented Analysis and Design. This an excellent book and probably the best material available in object oriented analysis and design, but it often shadowed by its more popular cousin Head First Design Pattern by Eric Freeman. Later is more about how these principle comes together to create pattern you can use directly to solve known problems. These books helps a lot to write better code, taking full advantage of various Object oriented and SOLID design principles.

Though best way of learning any design principle or pattern is real world example and understanding the consequences of violating that design principle, subject of this article is Introducing Object oriented design principles for Java Programmers, who are either not exposed to it or in learning phase. I personally think each of these OOPS and SOLID design principle need an article to explain them clearly, and I will definitely try to do that here, but for now just get yourself ready for quick bike ride on design principle town 🙂

DRY (Don’t repeat yourself)

Our first object oriented design principle is DRY, as name suggest DRY (don’t repeat yourself) means don’t write duplicate code, instead use Abstraction to abstract common things in one place. If you have block of code in more than two place consider making it a separate method, or if you use a hard-coded value more than one time make them public final constant. Benefit of this Object oriented design principle is in maintenance. It’s important  not to abuse it, duplication is not for code, but for functionality . It means, if you used common code to validate OrderID and SSN it doesn’t mean they are same or they will remain same in future. By using common code for two different functionality or thing you closely couple them forever and when your OrderID changes its format , your SSN validation code will break. So beware of such coupling and just don’t combine anything which uses similar code but are not related.

Encapsulate What Changes

Only one thing is constant in software field and that is “Change”, So encapsulate the code you expect or suspect to be changed in future. Benefit of this OOPS Design principle is that Its easy to test and maintain proper encapsulated code. If you are coding in Java then follow principle of making variable and methods private by default and increasing access step by step e.g. from private to protected and not public. Several of design pattern in Java uses Encapsulation, Factory design pattern is one example of Encapsulation which encapsulate object creation code and provides flexibility to introduce new product later with no impact on existing code.

Open Closed Design Principle

Classes, methods or functions should be Open for extension (new functionality) and Closed for modification. This is another beautiful SOLID design principle, which prevents some-one from changing already tried and tested code. Ideally if you are adding new functionality only than your code should be tested and that’s the goal of Open Closed Design principle. By the way, Open Closed principle is “O” from SOLID acronym.

Single Responsibility Principle (SRP)

Single Responsibility Principle is another SOLID design principle, and represent  “S” on SOLID acronym. As per SRP, there should not be more than one reason for a class to change, or a class should always handle single functionality. If you put more than one functionality in one Class in Java  it introduce coupling between two functionality and even if you change one functionality there is chance you broke coupled functionality,  which require another round of testing to avoid any surprise on production environment.

Dependency Injection or Inversion principle

Don’t ask for dependency it will be provided to you by framework. This has been very well implemented in Spring framework, beauty of this design principle is that any class which is injected by DI framework is easy to test with mock object and easier to maintain because object creation code is centralized in framework and client code is not littered with that.There are multiple ways to  implemented Dependency injection like using  byte code instrumentation which some AOP (Aspect Oriented programming) framework like AspectJ does or by using proxies just like used in Spring. See this example of IOC and DI design pattern to learn more about this SOLID design principle. It represent “D” on SOLID acronym.

Favor Composition over Inheritance

Always favor composition over inheritance ,if possible. Some of you may argue this, but I found that Composition is lot more flexible than Inheritance. Composition allows to change behavior of a class at run-time by setting property during run-time and by using Interfaces to compose a class we use polymorphism which provides flexibility of to replace with better implementation any time. Even Effective Java advise to favor composition over inheritance. See here to learn more about why you Composition is better than Inheritance for reusing code and functionality.

Liskov Substitution Principle (LSP)

According to Liskov Substitution Principle, Subtypes must be substitutable for super type i.e. methods or functions which uses super class type must be able to work with object of sub class without any issue”. LSP is closely related to Single responsibility principle and Interface Segregation Principle. If a class has more functionality than subclass might not support some of the functionality ,and does violated LSP. In order to follow LSP SOLID design principle, derived class or sub class must enhance functionality, but not reduce them. LSP represent  “L” on SOLID acronym.

Interface Segregation principle (ISP)

Interface Segregation Principle stats that, a client should not implement an interface, if it doesn’t use that. This happens mostly when one interface contains more than one functionality, and client only need one functionality and not other.Interface design is tricky job because once you release your interface you can not change it without breaking all implementation. Another benefit of this design principle in Java is, interface has disadvantage to implement all method before any class can use it so having single functionality means less method to implement.

 

Programming for Interface not implementation

Always program for interface and not for implementation this will lead to flexible code which can work with any new implementation of interface. So use interface type on variables, return types of method or argument type of methods in Java. This has been advised by many Java programmer including in Effective Java and Head First design pattern book.

Delegation principle

Don’t do all stuff  by yourself,  delegate it to respective class. Classical example of delegation design principle is equals() and hashCode() method in Java. In order to compare two object for equality we ask class itself to do comparison instead of Client class doing that check. Benefit of this design principle is no duplication of code and pretty easy to modify behavior.
Here is nice summary of all these OOP design principles :

All these object oriented design principle helps you write flexible and better code by striving high cohesion and low coupling. Theory is first step, but what is most important is to develop ability to find out when to apply these design principle. Find out, whether we are violating any design principle and compromising flexibility of code, but again as nothing is perfect in this world, don’t always try to solve problem with design patterns and design principle they are mostly for large enterprise project which has longer maintenance cycle.