david david - 3 months ago 8
Java Question

How to avoid making long constructors

I have a client library in which I am making http remote calls to my rest service and then I am returning

List<DataResponse>
back to the customer who is calling our library with the response I am getting from my REST service along with any errors if there are any wrapped around
DataResponse
object.

public class DataResponse {

private final String response;
private final boolean isLink;
private final TypeOfId idType;
private final long ctime;
private final long lmd;
private final String maskInfo;

// below are for error stuff
private final ErrorCode error;
private final StatusCode status;

// constructors and getters here

}


Here is my
ErrorCode
enum class:

public enum ErrorCode {

// enum values

private final int code;
private final String status;
private final String description;

// constructors and getters

}


And here is my
StatusCode
enum class:

public enum StatusCode {
SUCCESS, FAILURE;
}


As you can see in my
DataResponse
class I have lot of fields so basis on that I have a very long constructor and everytime when I make a
DataResponse
object I have a big line with
new DataResponse(.......)
. In future I might have more fields but for now I only have these fields.

Is there any better way I can use to make a
DataResponse
object and then return back
List<DataResponse>
from my library?

Answer

Do not use the builder pattern right away. It is not for types with tons of required fields. It's for types with tons of optional fields.

Builders' required properties are specified via the constructor. You are not forced to define values using methods, which makes those values optional. This leaves potential for your object being only partially constructed. Using a builder for this would be abuse of the design.


With that said, you should decompose your type. I'm not sure what lmd or ctime is, or really what a DataResponse is supposed to represent, so I cannot tell you in which way you should decompose. But I can tell you cohesion is what determines such.

isLink, maskInfo and idType could possibly be decomposed into a DataResponseDetails object:

class DataResponseDetails {
    private boolean isLink;
    private String maskInfo;
    private TypeOfId idType;

    public DataResponseDetails(boolean isLink, String maskInfo, TypeOfId idType) {
        //...
    }
}

Now your DataResponse could be composed of DataResponseDetails:

class DataResponse {
    private DataResponseDetails details;
    private String response;
    //...

    public DataResponsw(DataResponseDetails details, String response, ...) {
        //...
    }
}

Feel your constructor requires too much still? Decompose more!