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
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
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
Partner Zones AWS Cloud
by AWS Developer Relations
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
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Languages
  4. Lazy Loading Is a Code Smell

Lazy Loading Is a Code Smell

Lazy loading can benefit performance, but relying on it too much can bite you. In general, avoid lazy loading unless you know the context inside and out.

Sebastian Malaca user avatar by
Sebastian Malaca
·
Jan. 11, 17 · Opinion
Like (45)
Save
Tweet
Share
50.27K Views

Join the DZone community and get the full member experience.

Join For Free

Have you ever seen those huge objects with many attributes? These domain objects where we are using lazy loading because we do not want to retrieve too much information from the database? I bet you’ve had this dubious pleasure.

Today, I want to share my impressions about them: using lazy loading should be treated as a code smell!

Let me explain myself:

  • Lazy loading means that sometimes you won’t need some attributes of an object. Those attributes will be necessary in a different context. Doesn’t it mean that you are building different objects depending on context?
  • The functionality that is using this object knows definitely too much. It knows the API of the object and this API contains also the methods that require attributes which were not loaded. Great, isn’t it?
  • You have to remember what is needed in each place and what is not needed …
  • … and, what is even worse, you have to remember what you may use and what methods are not supported in a particular place.

In case it is not enough for you, let me elaborate.

How Lazy Loading Works

In short, lazy loading allows you to NOT load children when loading the parent. It loads them only when you explicitly ask for it.

How does it work? Let’s take a look at a simple example:

class User {
    private final Name name;

    @OneToMany(fetch = FetchType.LAZY)
    private List<Role> roles;

    @OneToMany(fetch = FetchType.LAZY)
    private List<Subscription> subscriptions;

    // Some more attributes and methods
}


What does the definition of this class tell you? What does FetchType.LAZY mean to us? This gives us information that lists which contain user’s roles and subscriptions won’t be filled with data until we explicitly ask for such data.

What Is Bounded Context?

Bounded Context is one of the main patterns in Domain-Driven Development. It helps you work with large domain models by dividing them into different contexts. Thanks to this your domain’s objects become smaller and business logic of your application becomes easier to understand.

Code Smell? But…

In one of the previous paragraphs, I wrote what the definition of the User class tells us. Until now, it’s been all about the mechanism. Now we may go further.

Let’s take another look at our class:

class User {
    private final Name name;

    @OneToMany(fetch = FetchType.LAZY)
    private List<Role> roles;

    @OneToMany(fetch = FetchType.LAZY)
    private List<Subscription> subscriptions;

    // Some more attributes and methods
}


Can you tell me anything more about this object except the things that were already mentioned?

We know that we are working with the class whose objects are used in places where roles may be needed, but don’t have to be. Where subscriptions may be needed, but don’t have to be. The name is always required.

We know that there are functionalities/places in our application/situation where those attributes are required and there are somewhere those attributes are useless.

But… we have to go through the code to find those places. It takes time and effort. Unfortunately, there’s also a chance that we will miss some places.

The Things We Know (And the Things We Don't)

Wouldn’t it be better to know where and what is required? Of course it would! The question is: How do we achieve it?

Let’s do a short analysis of our example:

class User {
    private final Name name;

    @OneToMany(fetch = FetchType.LAZY)
    private List<Role> roles;

    @OneToMany(fetch = FetchType.LAZY)
    private List<Subscription> subscriptions;

    // Some more attributes and methods
}


We already know a few things:

  • The name is always required.
  • Sometimes we need roles.
  • Sometimes we need subscriptions.

Based on this information, we can add one more thing — we know that we do not always need to have all this information. Maybe it sounds like something trivial, but it is also important. 

That’s all about information. Now is time for the unknowns:

  • Is there any place where we need both roles and subscriptions?
  • Are roles and subscriptions needed in different places?
  • Is there any place where we don’t need either?
  • Does it depend on the context what attributes will be needed?

The problem with unknowns is that we have to go through the code to find answers to them. But that’s not the end of the problems. When you finally find those places, there is no method or variable or anything to rename to NOT lose this information within a time. Next time, you will have to repeat the effort.

Let’s Improve the Code

Because of the unknowns listed in the previous paragraph, it is not so easy to change the existing code, the real one, the one we are working with. That’s why I suggest that you make this change just after the moment when you think about lazy loading. That’s the right time when the improvement is cheapest.

Ok, but how could we improve the code from the example?

The first thing to do is to find answers to the unknowns. Without those answers, we cannot move forward. In our case I will assume that we recognized three different contexts:

  • Authentication and authorization are the places where we need user’s name and its roles.
  • We need user’s name and its subscriptions in the place where we handling with report sending.
  • In other areas of our application, we don’t need roles or subscriptions.

Now we can refactor the User class and split it into something easier to understand:

class AuthUser {
    private final Name name;
    private List<Role> roles;

    // Some more attributes and methods
}

class ReportUser {
    private final Name name;
    private List<Subscription> subscriptions;

    // Some more attributes and methods
}

class ApplicationUser {
    private final Name name;

    // Some more attributes and methods
}


Now we have got three classes instead of one, but we also have more information in our code. We won’t need to go through the code to find out what and where is needed. It would be just enough to open the definition of the class

What’s Next?

Unfortunately, to achieve the presented state in your domain, you have to invest a lot of effort. Why? Mostly because of unknowns. The bigger the application, the harder it will be to get all information. That’s why I encourage you to split your classes just after you think about lazy loading as a solution.

If you already have lazy-loaded references in your domain, you should refactor only the part you already working with. You will minimize both the risk of the change and the effort needed to make it. And the code will become more descriptive anyway.

Good luck!

Lazy loading Code smell Object (computer science)

Published at DZone with permission of Sebastian Malaca, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Journey to Event Driven, Part 1: Why Event-First Programming Changes Everything
  • Create a CLI Chatbot With the ChatGPT API and Node.js
  • How Elasticsearch Works
  • Create Spider Chart With ReactJS

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

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

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: