1

I am looking out for a general design strategy or pattern designing various components in my client application. Here are high level details:

  1. The data is accessed my making a RestAPI call. The data returned by making a single RestAPI call is called a entity. This entity is de-normalized data meaning, if there is a User entity, which is accessed through and exposed API: /rest/User then the returned information for User is gathered from all various components( lets say different tables for now) that has the User information.
  2. Now, how should I design such entities at my client application?
  3. If I have a separate POJO class for each respective entity, then how should I design different queries that are required to fetch the data. Queries would mean adding different filters in the URL for accessing specific entities.
  4. Is the Repository Pattern recommended for this or the classic DAO pattern?
  5. If the client application needs information from different entities to be clubbed together, which layer should have the clubbing logic?
  6. How should I design the different services. Should the services be designed on the different operations supported at the client or they should correspond to the entity.

To elaborate this, let us say there is an operation to get the User and his respective permissions then what should be my classes like? For ex:

  1. Should I have UserService that first gets the users and then internally call the PermissionsService that will get the permissions for the User? OR
  2. It makes sense to have a service called GetUserService which internally calls the UserService and UserRepo to get the user and then the same for PermissionsService and then have other *mapping details in the GetUserService*?

1 Answer 1

4

Since the question is too broad, my answer might sound too simplistic or naive. Or why not, too broad too. Excuse me in advance if the answer doesn't meet your expectations but I honestly think that it might help you out to find a starting point.

I think, what you are striving to conceptualize is something that most of the REST API out there don't have. An API Client. This is the general design strategy I would recommend.

Think, for example, in Google client libraries or Amazon AWS Tools. These web service providers have solved for us how to consume their APIs in the most akind way to the programming language in use.

GeoApiContext context = new GeoApiContext.Builder()
    .apiKey("AIza...")
    .build();
GeocodingResult[] results =  GeocodingApi.geocode(context,
    "1600 Amphitheatre Parkway Mountain View, CA 94043").await();

No service, no repositories, no DAOs. Just parametrizable and configurable components you can program with.

DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
                .dynamoDbClient(ddb)
                .build();

You want to build an app which business happens to rely on a certain remote API and you want this dependency/integration to be the most seamless possible. But most importantly, you want to solve both things separately.

Regarding the design of API Clients, you will find similarities among them. For example, they often use builders and static factory method patterns to build or set up the components required to perform the operations (calls to the remote service). They use the same patterns to build the operations as well.

Operations are modelled and arranged around domain concepts. UserApi does user operations and the CustomerAPI does customer operations upon UserAPI data, which comes to say that UserAPI needs to be consumed first. Think about how you want the API client to be consumed. What "hard" things do under the hood to make the developer's life easier.

The outer layer of the API client acts as a root compositor from which, given some inputs, it builds the internal dependency graph needed to, ultimately, make the request to the server, handle the response and map it to the corresponding data model, apply security and access control rules, etc.

Domain operations, in the end, are translated into HTTP calls which are performed by rest templates. These are, essentially, abstractions that ease the implementation of HTTP requests, the HTTP response (and error) handling, and the mapping of the responses to the domain data model which can be exactly the same as the remote API or a different representation. The model exposed by the API client doesn't have to be exactly the same exposed by the REST API and you will find this to be very appropriate.

The key point here is, to narrow down the focus. If you think about the REST API integration as part of the app client design, it's likely you will interpret the needs of layering and abstraction of the application and your API client to be similar if not the same, and apply the same strategies to solve both things. That's one way to end up with a Golden Hammers.

Implementing the app client and the REST API Client are different concerns, with different levels of complexity which solutions will be at different levels of complexity too. The level of abstraction involved in designing an enterprise application is quite higher than the one required to implement an API client.

Note that, whether you implement DAOs, facades, repositories, or any other pattern is a decision driven by the needs of the API client. You will implement as many patterns and abstractions as you deem appropriate and only when need it. No more no less. Bear in mind that the solution should never be more complicated than the problem it solves or it becomes an unaffordable solution in the long run. And remember that your focus and efforts should be most of the time on solving a business rather than reinventing the wheel.

I know all of this is very naive to say, I would suggest looking for some of the most popular API clients like the ones I mentioned at the beginning. Look into their source code (it use to be on Github). I'm sure you will find, regardless of the domain and the implementation details, similarities among them. They all, at some point, went through the same process you are right now. Similar doubts and concerns.

Choose one API Client and put the focus on the overall design, the guidelines that describe the solution. Zoom it out. Ignore the details by now. Adapt the guidelines you have seen to your own context. Make it simple at the beginning because it will (if it ever) become more complex over time.

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.