3

I am building an extensible system which have following requirements:

  1. Each request will have 2 attributes: type, region
  2. Based on the values of type and region, different configs will be selected
  3. There are over 20+ classes which need to select configs based on type+region.
  4. Business logic involves calling 30+ functions in 20+ classes, so passing region and type is not possible. The business logic has multiple branches based on the product type and status. A master class contains the business logic and calls individual functions inside different classes to complete the business logic. Please refer to below code to get an idea about business logic.

One method to implement this is to create a class with two fields: type and region. At the entry point, create an object of this class and pass it along to every function call. Based on the type+region value from that passed object, select appropriate config.

Instead of passing type+region object in every function, is there any elegant solution? Like extending an object dynamically? Or set an object at entry point and then reuse it by extending any particular class. I am new to system design and inheritance, so I cannot think of an elegant solution.

E.g.: Following gives an overview of the business logic. There are over 20 Helpers in the MainLogic class and each of those helpers have 5+ data stores. I am looking for an elegant solution which doesn't involve passing region+type across all functions.

@AllArgsConstructor
class MainLogic {
    BillingInfoHelper billingInfoHelper;
    ..........

    public Boolean executeRequest(RequestInput requestInput){
        final String region = requestInput.getRegion();
        final String type = requestInput.getType();

        final BillingInfo billingInfo = billingInfoHelper.get(region, type);
        ..............
    }
}

@AllArgsConstructor
class BillingInfoHelper {
    AccountIdDataStore accIdDataStore;
    BankNameDataStore bankNameDataStore;
    AddressDataStore addressDataStore;
    ........

    public BillingInfo get(String region, String type){
        String accountNumber = accIdDataStore.get(region, type);
        String bankName = bankNameDataStore.get(region, type);
        String address = addressDataStore.get(region, type);
        return new BillingInfo(accountNumber, bankName, address);
    }
}


@AllArgsConstructor
class AccountIdDataStore {
    Config configStore

    public String get(String region, String type) {
        configStore.getAccountNumber(region, type)
    }
}

Rony Singh
  • 39
  • 4
  • 3
    More information would be nice (especially with the 20+ classes you mentioned), but it is sounding like you may benefit from dependency injection – smac89 Jul 15 '19 at 07:43
  • Can you explain how can DI help? DI objects will be instantiated at service startup and then reused. How can I set its value at runtime when the request comes in? – Rony Singh Jul 16 '19 at 00:20
  • 1
    It's really hard to say beyond this point how DI will help because you have not provided enough information about your configs (are they files?) and how they relate to your attributes. Also how do those 20+ classes interact with your configs and attributes? How does a combination of request + attribute + config affect the class you choose? Do you need to instantiate a new instance of each class for each request or can you get away with just a single instance? You need to provide more information, maybe give an example of what you are looking to accomplish. – smac89 Jul 16 '19 at 00:31
  • 1
    I think you are focusing too much on mutating your objects rather than composition, i.e. taking a functional programming approach. Maybe you can think of a way of writing your request handler as a function that given a certain request, it returns a function that expects a config, which in turn returns a function that expects one of your 20+ classes and then calls the appropriate method on the class? I think there are many ways to do this, but without more information, I'm just shooting blanks at this point – smac89 Jul 16 '19 at 00:35
  • Thanks a lot @smac89 for providing your inputs. Sorry for the late reply. I got occupied with something else. I have added sample code to the question that gives more idea about my code. – Rony Singh Jul 23 '19 at 02:10
  • Even though I am instantiating DataStore objects using DI and AllArgsConstructor, I have to still pass region and type to each function. Can you please guide me how can I make it more elegant? – Rony Singh Jul 23 '19 at 02:16
  • Are the contents of `ConfigStore` mutated at runtime or are they known in advance? – smac89 Jul 23 '19 at 17:41
  • `ConfigStore` contents are known in advance in most cases but they can be updated in the backend without restarting the service which is using them. Also, ConfigStore is an external dependency. – Rony Singh Jul 24 '19 at 00:57

1 Answers1

0

You can make the two different variables of type and region and make them static in java.

class ClassName{
    public static String type = "some_value";
    public static String region = "some_value";
}

Later on you can use these variables in any other class by using ClassName.type

Vivek Singh
  • 1,142
  • 14
  • 32