Search code examples
javainheritancedtocode-duplication

How can I avoid DTOs duplication without inheritance?


I am connecting with many social networks for login in my application. I have one DTO for each social network response.

public class GoogleUserInfo {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    private AgeRange ageRange;
    // more specific fields
}

public class FacebookUserInfo {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    private String picture;
    // more specific fields
}

public class AppleUserInfo {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    private Boolean emailVerified;
    // more specific fields
}

In each social network connector, I make similar steps to fetch the information, so I thought I could go with some DTO as follows:

public class SocialNetworkInfo {
    protected String id;
    protected String firstName;
    protected String lastName;
    protected String email;
}

Social networks DTOs could extend this to obtain the common fields. Then I could use this generic DTO to implement an abstract connector that deals with all the duplicate logic between connectors (make request, parse response, etc...):

abstract class AbstractConnector {
    abstract SocialNetworkInfo fetchUserInfo(String networkId);
    ...
}

But I realized that above, in my service layer, I would need those specific fields to make some changes and operations.

SocialNetworkInfo networkUserInfo = facebookConnector.fetchUserInfo(facebookId);
facebookService.updatePicture(networkUserInfo.getPicture()); // can't access this specific field

What do you think that's the best way to go through this situation without casting and avoiding logic or DTO duplication?

Would love to hear your thoughts.

Thanks!


Solution

  • If you don't want to use inheritance, I'd suggest to consider composition. The code can look as follows:

    public class SocialNetworkInfo {
        private String id;
        private String firstName;
        private String lastName;
        private String email;
    }
    
    public class GoogleUserInfo {
        private SocialNetworkInfo socialNetworkInfo;
        private AgeRange ageRange;
        // more specific fields
    }
    
    public class FacebookUserInfo {
        private SocialNetworkInfo socialNetworkInfo;
        private String picture;
        // more specific fields
    }
    
    public class AppleUserInfo {
        private SocialNetworkInfo socialNetworkInfo;
        private Boolean emailVerified;
        // more specific fields
    }