Question

My domain space is Java + RxJava but I think this applies to any reactive framework

I have a stack that looks like the diagram below. Just for examples sake I'm describing a login flow but any UI --> web request --> UI flow would be the same.

+-----------------+                             
|                 |                             
|       UI        |                             
|                 |                             
+-----------------+                             
         |              wasSuccessful (boolean) 
         |              name                    
+-----------------+                             
|                 |                             
|   DataManager   |                             
|                 |                             
+-----------------+     response code           
         |              userID                  
         |              name                    
+-----------------+                             
|                 |                             
|   ApiManager    |                             
|                 |                             
+-----------------+     response code (i.e. 200)
         |              {                       
         |                 "user_id":123,       
+-----------------+        "name":"Bob",        
|                 |        "auth_token":"asdf"  
|    web client   |     }                       
|                 |                             
+-----------------+        
  1. UI layer makes a call to the DataManager to login a user
  2. DataManager calls the ApiManager to make a web request to login user
  3. ApiManager calls the web client to login user
  4. web client returns user as json
  5. ApiManager deserializes json, keeps the auth token (since DataManager layer doesn't need to know about auth), and passes response code, userId, and user name to the DataManager
  6. DataManager keeps userId (since UI doesn't need to know about userId), and passes user name and a boolean (representing successful request) to the UI layer
  7. UI layer either displays error if request failed or displays user name

I'm using a reactive stream to accomplish all of this: each layer talks to the ones above and below it with observables. Each layer only knows about the layers on either side of it to have a good separation of concerns.

Part of RxJava framework is that the stream can only emit single objects. So I have to bundle all this data into classes:

class WebClientLogin {
    int responseCode;
    String userId;
    String name;
    String authToken;
}

class ApiLogin {
    int responseCode;
    String userId;
    String name;
}

class Login {
    boolean wasSuccessful;
    String name;
}

The problem is that I'm creating all of the little classes that are just used to group disparate data together. They don't translate to meaningful abstractions like a User class.

I also don't have a good naming convention for them either. If another developer were to come along later they wouldn't know what an ApiLogin was or how/why/where to use it. They would have to go see where it was currently used to get any idea of what it was supposed to do. Compare this with a class called PizzaToppingIterator which describe what it is and when you might want to use it.

Is there any better way to achieve this? Or any better way to organize this structure?

I thought maybe making Login, ApiLogin, and WebClientLogin as static inner classes in the larger object that created them: DataManager.Login, ApiManager.Login, WebClient.Login so that it was more clear when they'd be used. But this still doesn't feel right. DataManager, ApiManager, and WebClient would end up with lots of these inner classes.

I definitely want to keep the layer divisions (really helpful elsewhere and for testing) and I really want to keep the reactive streams between layers.

Was it helpful?

Solution

Allow me to play devil's advocate for a moment.

The problem is that I'm creating all of the little classes that are just used to group disparate data together. They don't translate to meaningful abstractions like a User class.

That's because these little classes are Data Transfer Objects (DTO's), a perfectly valid technique.

I also don't have a good naming convention for them either.

I beg to differ. I understood your naming choices instantly.

I thought maybe making Login, ApiLogin, and WebClientLogin as static inner classes ...

Blegh. Too complicated, for too little benefit.

So far, your bundle of DTO's seems like the best solution.

Licensed under: CC-BY-SA with attribution
scroll top