36

In my years of programming I've often made classes that simply group a few variables with their setters and getters. I've seen these types of objects referred to as value objects, domain objects or model objects depending on the context in which they are used. The most fitting term for generic usage seems to be Data Transfer Object (DTO). This describes a POJO that only contains accessors and mutators.

I've just written one such object that contains about fifty fields used to set theme parameters on a chart. Now I'm wondering if instead of generating a hundred getters and setters I should just declare these fields as public. Doing so goes against everything my programming instincts tell me yet I can't deny that it would greatly increase my code's legibility and reduce the amount of boilerplate code in the class.

The only reason I can see not to use public fields would be if I needed to perform any sort of validation on these fields. If we assume that type validation is sufficient for my purposes, is using public fields in this scenario an acceptable break from object-oriented design? Will a public DTO perform better in large batch operations?

Lilienthal
  • 4,327
  • 13
  • 52
  • 88
  • 1
    Possible duplicate - http://stackoverflow.com/questions/1568091/why-use-getters-and-setters – sanbhat May 14 '13 at 09:19
  • Getters and setters are required if you try to use `DI` frameworks like `Spring` or something like `jsp:useBean` etc !!! – AllTooSir May 14 '13 at 09:22
  • @sanbhat: some of the reasons given in the accepted answer to that question apply here but not all. A DTO's scope and behaviour is different from a generic class so I was wondering if different "rules" would apply here. – Lilienthal May 14 '13 at 10:40

4 Answers4

41

Most programmers will default to private fields with getters/setters without thinking about it. But like any cargo-cult thing, it's better to make a conscious decision.

The main reason for using a getter/setter combination instead of a public field is that you can change the definition. So, if your DTO is part of an interface between components, best to use getters. If you change the inner workings, you can adapt the getter to mimic the old behaviour and maintain compatibility.

Another reason is that you can make read-only fields. Often for DTOs, read-only and immutable is a good choice.

A third reason could be that your DTO needs to be a javabean because you intend to use it in some tool that requires it.

If none of these properties go for you, there's no reason not to use public fields.

Don't expect much of a performance difference though :)

Joeri Hendrickx
  • 16,947
  • 4
  • 41
  • 53
  • 1
    Just what I needed to know. If I summarise it seems like the decision on whether or not to use public fields would depend on the scope of the project, whether or not it will be reused or interfaced and the likelihood of change. I also had not considered that non-primitive `final` fields would not be immutable. If I wanted to make such a field read-only I'd have to convert the entire class to maintain uniform access. – Lilienthal May 14 '13 at 10:48
  • 2
    Plus one for the immutibility. Also consider rather than using setters if you can use the Builder pattern. Then most of your access would be through getters, allowing you to return immutables or safe copies of items you don't want indirectly influencing through side-effects. – Jeff Watkins May 14 '13 at 11:16
8

There is a difference between DataStructure and Object.

Data structure should expose its innards and not behavior.

An Object should not expose its innards but it should expose its behavior, which is also known as the Law of Demeter

so, DTOs are basically Data structures. They should only expose their data, they don't need Getter and Setters. Validation is the behavior, it should not be part of DTO. It must have a different Object i.e. Validation object.

Inspired by Clean Code by Robert C. Martin(Uncle Bob)

aditya lath
  • 410
  • 7
  • 6
5

I do not think it terribly bad practice to have a 'settings' or 'theme' or 'style' class with public attributes.

Modern IDEs with refactoring tools make it trivial to promote an attribute to getter/setter if you want to do any complicated calculations or checks on values at set-time.

Often in your 'setTheme' or whatever function that consumes these settings classes is a good clean place to do validation.

When setting settings like this it is usually appropriate to do a deep copied object rather than retaining a reference to a mutable class.

Will
  • 73,905
  • 40
  • 169
  • 246
5

A data structure is a class that exposes data, without any business logic e.g.:

class Name {
   public String firstName;
   public String lastName;
}

This data structure:

  • doesn't have any getters/setters.
  • is not immutable.

An immutable data structure:

  • is a class that exposes data also.
  • has an all argument constructor.
  • has all final fields.
  • exposes its data through getters.
  • has no setters.

e.g.:

class Name {
    private final String firstName;
    private final String lastName;

    public Name(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return this.firstName;
    }

    public String getLastName() {
        return this.lastName;
    }   
}

A Data Transfer Object:

  • is used for transferring data.
  • is a pattern for saving round trips to a server.
  • contain serialisation/deserialisation info. This information is normally taken from javax.validation library.
  • normally is composed of 2 different objects.
  • doesn't contain any business logic.

e.g.:

import javax.validation.Valid;

class UserDto {

    @Valid
    Name userName;
    @Valid
    Address userAddress;

    public UserDto(Name userName, Address userAddress) {
        this.userName = userName;
        this.userAddress = userAddress;
    }   
}

So now that I have clarified each of the terms Data Structure, Immutable Data Structure & DTO, I can summarise.

A DTO is used to transfer data.
The data shouldn't be changed in transit.
So DTO's should be immutable. e.g.

import javax.validation.Valid;

class UserDto {

    @Valid
    private final Name userName;
    @Valid
    private final Address userAddress;

    public UserDto(Name userName, Address userAddress) {
        this.userName = userName;
        this.userAddress = userAddress;
    }

    public Name getUserName() {
        return this.userName;
    }

    public Address getUserAddress() {
        return this.userAddress;
    }
}

Just a note about non-primitives like Integer, String, Boolean, etc. these are all immutable classes.
Once they are constructed they cannot be mutated.
So if you make these fields final their references cannot be updated to point to different object and their values cannot be mutated using the Java API.

William Walsh
  • 51
  • 1
  • 3