DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • How To Check for JSON Insecure Deserialization (JID) Attacks With Java
  • JVM Memory Architecture and GC Algorithm Basics
  • High-Performance Java Serialization to Different Formats
  • All You Need To Know About Garbage Collection in Java

Trending

  • How Trustworthy Is Big Data?
  • Doris: Unifying SQL Dialects for a Seamless Data Query Ecosystem
  • Stateless vs Stateful Stream Processing With Kafka Streams and Apache Flink
  • Issue and Present Verifiable Credentials With Spring Boot and Android
  1. DZone
  2. Coding
  3. Languages
  4. Refactoring Java Application: Object-Oriented And Functional Approaches

Refactoring Java Application: Object-Oriented And Functional Approaches

Learn how you can achieve better design using object-oriented and functional approaches. This post includes examples with inheritance and functional interfaces.

By 
Dmitry Egorov user avatar
Dmitry Egorov
DZone Core CORE ·
Updated May. 11, 22 · Tutorial
Likes (21)
Comment
Save
Tweet
Share
23.5K Views

Join the DZone community and get the full member experience.

Join For Free

Java Refactoring Approaches

Refactoring in Java has many aspects, but among all of them, there are two fundamentals: object-oriented and functional. Object-oriented existed almost from the first Java version, whereas functional appeared only with Java 1.8 (March 2014).

Object-Oriented (OO) and Functional Approaches

Java is a classical object-oriented language and allows the creation of flexible object structures. After Java 1.8 received functional features, it became capable to operate not only with objects or methods but with lambdas (which is executable code itself). In the functional world, you can operate with functions as with objects in the OO world.

OO vs Functional Graphic

Refactoring Code Using OO Approach

Playing with interfaces and classes using inheritance or composition, you can create reusable generic solutions that can reduce the code amount and increase readability. Classes can be united in the same common structure if they:

  • Have similar fields and recognized as the same entity
  • Have relations parent/children
  • Have similar purpose methods

Refactoring Code Using Functional Approach

Unlike the OO approach, this one extracts the code that has the same behavior. For example, we can recognize similarities in the next examples:

  • Implementation has the same return type
  • Implementation has the same functionality

Refactoring Example Using Both Approaches

Let's assume we have a small application that makes payments to permanent and contract employees. After each payment, we print a report about Employee and show the in data different formats (JSON and XML for permanent and contractor).Refactoring Example Using Both Approaches

Now let's take a look at the default structure:

Default structure

Refactoring Classes Structure

It is pretty visible that Contractor can be a child of Employee class. makePayment can be overridden (also we might create a Payable interface and extract makePayment method, but let's keep it simple). So after refactoring, we might have some fields in common together with reused constructors.

Refactoring Classes Structure

Refactoring Functional Aspects

Now we can review and find similarities from a functional perspective:

Refactoring Functional Aspects

As you can see from the printing report, we process it in the same way: we pass an object and return a string. So we can extract that code as a reusable function and use it dynamically for this business logic or even outside of it.

Creating Function Interface

In order to decide the right functional interface (e.g., Predicate, Consumer, Function, etc.), we need to check our inputs and outputs. In our case, we get an Object and convert it to a String. 

Creating Function Interface

Such an interface is provided by function, but in order to make it more clear, we create our own Converter interface with method serialize. In that case, it would be easily readable:

Create Converter Interface with Method Serialize

Creating Lambdas: Converter Functional Interface

Now having a functional interface we create two Converters: json and xml. Both of them will match the defined signature (object input and string output).

Now let's use them in our code:

Using Converters in Code

Encapsulating Converters Inside Employee Class

As in the last step, we can encapsulate this function right inside the parent Employer class and use them inside the internal function:

Encapsulating Converters Inside Employee Class

Reviewing the Final Version

As in the last step, we initialize both employers and iterate through them executing payment and printing methods. Initialize both employers and iterate through them executing payment and printing methods

So what do we have at the end? 

  • Commons fields and methods from parent Employer class are now reused in Contractor
  • Extracted functions converters can be replenished in the future without changing the Employer class
  • Extracted functions can be reused outside of the Employer class

Criticism

Criticism graphic

The shown example is not perfect and can be improved. For example, we can hide the Employee/Contractors class behind the interface, and it's good practice! I tried to write a simple example and decided to show just some OO and Functional features.

The functions I've created are not pure functions and some developers insist it's much better to have only pure functions in Java. It's a big discussion outside of this article.

My Personal Criticism About Functions

One of the purposes of this article was to make readers more confident with a functional approach; but at the same time, I'm a person who prefers methods or static methods over functions. Why? Because the old method approach allows you to read code line by line from top to bottom and you can easily see the logic. With a functional approach, you have to return back (or memorize) the function content when the function is called. So, as I think about extracting the same functionality code into methods/static methods - personally, I think it might be better.

Final Message

Final Message graphic

The main message of this article is:

  • Use the object-oriented approach in order to unite similar-by-nature objects in one structure 
  • Use a functional approach to unite similar-by-functionality code. Together they make code significantly more readable and maintainable. The code used in this article is available here.
application Java (programming language) Object (computer science)

Opinions expressed by DZone contributors are their own.

Related

  • How To Check for JSON Insecure Deserialization (JID) Attacks With Java
  • JVM Memory Architecture and GC Algorithm Basics
  • High-Performance Java Serialization to Different Formats
  • All You Need To Know About Garbage Collection in Java

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!