2020-03-19 12:51:33 +05:30

5.1 KiB

LLD 4

Cascader Pattern

public class Address {
    String city, state, zip, lines[];
}
  1. Validating address
    • Need to validate each part
  2. Algo(zip) < Algo(state) < Algo(city) < Algo(lines)
    • both in difficulty and time complexity
  3. Need to check combined as well
    • * < Algo(combined)
  4. Has been observed that most of the time, people make mistakes in Zip
    • Does it make sense to validate everything else?
    • No. Check zip first
  5. We provide this combined validator to our client
    public class CombinedValidator {
        private static ZipValidator z = new ZipValidator();
        private static StateValidator s = new StateValidator();
    
        bool validate(Address a) {
            return z.validate(a)
                && s.validate(a)
                && ...;
            // order is important to fail fast
        }
    }
    
  6. Fail fast - prune the bad requests
    • just like in recursion - branch and bound
  7. Can we improve upon the &&?
    • Could be more complex than &&
    • Have multiple steps for each validator
  8. Abstract it out into a loop
    • Find the repeated thing
    • Make a loop for it.
  9. But class is different each time
    • Can we make it same?
    • Code classes against an interface
      public interface Validator {
          bool validate(Address);
      }
      
      public class ZipValidator implements Validator {
          bool validate(Address a) { ... }
      }
      
  10. Make the loop (using Runtime Polumorphism)
    • What DS should we use to store the Validators?
    public class CombinedValidator {
        private List<Validator> validators;
        public CombinedValidator() {
            validators = Arrays.asList(
                new ZipValidator(),
                new StateValidator(),
                ... 
            );
        }
    
        bool validate(Address a) {
            for(Validator v: validators)
                if(!v.validate(a))
                    return false;
            return true;
        }
    }
    
  11. Could we have used a Set instead of List?
    • No. Order matters!
  12. Clients appear asking for different Combinations
    • Either expose the programming interface - clients pass their own lists
    • Many times, you onboard a client
    • Communication over email / person like "we need to validate xyz using your code"
    • You provide them with one function call for that
  13. Provide a combination for each client, associated with a client name
    • c1 neess V1, V2, V3
    • c2 needs V1, V4
    • ...
    • can use hashmap
    • should we store lists in values?
    • No, we can use CombinedValidator
  14. CombinedValidator can implement Validator
    class X {
        Map<clientName, Validator> mapping;
        public X() {
            mapping.put("order_page", CombinedValidator(Arrays.asList(
                new ZipValidator(),
                new CityValidator(),
                new LinesValidator(),
            )));
            mapping.put("KYC_check", CombinedValidator(Arrays.asList(
                new ZipValidator(),
                new CityValidator(),
            )));
        }
    }
    
  15. Lots of objects being created in constructor. Make it singleton.
  16. Convert it into a factory (+singleton)
    class ValidatorCascadeFactory {
        Map<clientName, Validator> mapping;
        private ValidatorCascadeFactory() {
            mapping.put("order_page", CombinedValidator(Arrays.asList(
                new ZipValidator(),
                new CityValidator(),
                new LinesValidator(),
            )));
            mapping.put("KYC_check", CombinedValidator(Arrays.asList(
                new ZipValidator(),
                new CityValidator(),
            )));   
        }
        public CascadeFactory getInstance() // singleton
        public Validator getValidator(String clineName) // factory
        // note: exception handle in getValidator
    }
    
    public class ValidatorCascade implements Validator {
        private List<Validator> validators;
    
        public ValidatorCascade(List<Validator> validators);
    
        bool validate(Address a) {
            for(Validator v: validators)
                if(!v.validate(a))
                    return false;
            return true;
        }
    }
    
  17. Cascade
    • staircase
    • fail: exit
    • pass: move to next step
  18. Client Code
    class ClientValidator {
        bool validate(Address a) {
            return ValidatorCascadeFactory.getInstance()
                                          .getValidator(name)
                                          .validate(a);
        }
    }
    
  19. Note that in this code, we used Cascade, Factory, Singleton
  20. Order important?
    • yes, here
    • not always
  21. Address cleaning
    • clean zip
    • clean city
    • clean State
    • clean lines
  22. Need to perform all. All are independent - don't effect one another
  23. Can use a Set instead of a List
  24. Must use List in substrategy
    • first remove ,
    • then remove space
    • then lowercase
    • ...