2

Almost every software has a number of internal data structures that we don't want to expose externally (through APIs for example).

Let's say we have a few classes representing 1:1 database tables - User, UserGroup, GroupPermission, etc.

Then we can have an external class ExternalUser that will be exposed on an API, exposing some user details and user group details.

We have two options for what the properties of ExternalUser can be:

  1. Copying properties - ExternalUser has a copy of a subset of properties or derived properties from User and UserGroup

    1.1. ExternalUser can have for example username, fullName, userGroups, etc. as properties.

    1.2 All those properties will be populated on object creation and copied from the internal User and UserGroups

  2. Wrapping Object - ExternalUser has a references to User and UserGroup.

    2.1 ExternalUser will have a private user and userGroup that will hold reference to the internal models.

    2.2 Methods like getName will delegate to the internal user.getName, etc.

I can see pros and cons of both in terms of leaking data, memory use and session management if you are dealing with transactions.

Is there any pattern / standard or a reason why one option is much better than the other?

3 Answers 3

4

If I understand you correctly, by copying properties, you mean to not use encapsulation and simply set the individual fields to an instance of ExternalUser, am I correct?

By copying properties, you're basically trying to make your program more robust. A POJO class such as ExternalUser with no sophisticated types encapsulated within would be a very good way of detaching the actual implementation of your program with the one who uses it. The user calling your API would presumably receive instances of ExternalUser and there would be no complications of any kind. The data is present, and it can be conveniently serialized if desired.

By encapsulating instances of your inner classes, the ExternalUser class becomes far more dependent upon your implementation. This isn't necessarily a bad thing, since changing the methods of User and UserGroup is likely going to cause further changes in your program anyway, regardless of whether this logic is directly in ExternalUser or somewhere else. However you should be careful to hide all internal implementations if you do it this way. ExternalUser should be a dedicated class for this, and therefore any and all public methods and yes, private methods too, should not return a User or UserGroup instance. Why also private methods? Because you can still access private methods through reflection.

While you're not favoring robustness, you're following DRY principle, which makes your program more flexible and easier to maintain in general.

My personal preference is to keep the interface straightforward and robust, so I would use a POJO class for ExternalUser. If you wish to follow DRY principle as much as possible, simply avoid using ExternalUser until you wish to return the data to the caller. ExternalUser should be a strictly external class at this point. However, this may even be a bit of an overkill for a small project, so ultimately it depends on your personal preference.

0

In the case of an api you needn't do either.

You require the ExternalUser object to use in the Api's client library, so you need one of those.

You require the API to emit a string, which contains only the data for the fields in External user. But you don't need to serialise an ExternalUser object to achieve that.

You only need to configure your serialiser to include only the properties you want from the User object.

0

There are two cases

1. REST APIs and other IO channels

Typically, you won't need extra objects. Why? Because when serializing the output, you can typically use annotations like @Ignore or @Expose to selectively serialize your data into JSON/XML.

2. Packaged as a code library

Then you should copy your properties into an ExternalUser for example. Why? Because it would probably be possible to inspect the content of private members through reflection.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.