samedi 6 février 2021

Best way to implement builder pattern with a lot of conditionals

I have to transform a APIGatewayProxyRequestEvent into an object that is already defined in the codebase I'm working with.

The object has a lot of attributes that should be set or left as null depending on whether the APIGatewayProxyRequestEvent contains or doesn't contain certain values.

So for instance, I have a Person class:

public class Person {
    private String firstName;
    private String phone;
    private Address address;
    // other properties ...
}

And an APIGatewayProxyRequestEvent with the following:

{
    "resource": "/v1/people",
    "httpMethod": "GET"
    "headers": "headerName": "headerValue",
    "body": {"Person":{"firstName":"John"}
}

Now, given the amount of attributes and the fact that most of them are optional, I want to create a builder class for Person, but how do I do this in a way that allows the code to be easily readable and testable? If I have this builder:

public class PersonBuilder {

    private String firstName;
    private Address address;

    public PersonBuilder (String firstName, Address address) {
        this.firstName = firstName;
        this.address = address;
    }

    public PersonBuilder setFirstName(String firstName) {
        this.firstName = firstName;
        return this;
    }

    public PersonBuilder setAddress(Address address) {
        this.address = address;
        return this;
    }
}

Should I then have a separate class with individual methods for each attribute that might need to be set? For example:

public class PersonRequestAdapter {

    public Person createPerson(APIGatewayProxyRequestEvent request) {
        Person person = new PersonBuilder()
                                  .firstName("John")
                                  .address(checkIfAddressPresent(request.body()))
                                  .build();
    }

    public String checkIfAddressPresent(String requestBody) {
        if (requestbody.contains("Address") {
            // using objectMapper here to map it to an Address class and return that
        } else {
            return null;
        }
    }
}

There are quite a lot of conditions for about a dozen different attributes, where I need to check if headers are present, which headers, as well as query/path parameters, etc. So essentially every attribute would be set by a method similar to this checkIfAddressPresent. Does this sound like a good approach to write testable code while using the builder pattern? Or am I completely off? Thanks!

Aucun commentaire:

Enregistrer un commentaire