dburyak

DI and loose coupling

Aug 24th, 2021 (edited)
407
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 12.13 KB | None | 0 0
  1. /**
  2.  * This version is:
  3.  *  - not using DI, generator and formatter are created **inside the EventSender**
  4.  *  - has tight coupling with "RandomGenerator" and "JsonFormatter" specific classes
  5.  */
  6. public class TightCoupling {
  7.  
  8.     public static void main(String[] args) throws ExecutionException, InterruptedException {
  9.         var eventSender = new EventSender();
  10.         eventSender.send().get();
  11.     }
  12.  
  13.     @Data
  14.     public static class Event {
  15.         private final String id;
  16.         private final BigDecimal value;
  17.     }
  18.  
  19.     public static class EventSender {
  20.         private final RandomGenerator generator;
  21.         private final JsonFormatter formatter;
  22.  
  23.         public EventSender() {
  24.             generator = new RandomGenerator();
  25.             formatter = new JsonFormatter();
  26.         }
  27.  
  28.         public CompletableFuture send() {
  29.             var event = generator.generate();
  30.             var serialForm = formatter.format(event);
  31.             // send bytes
  32.         }
  33.     }
  34.  
  35.     public static class RandomGenerator {
  36.         public Event generate() {
  37.             // generate event with random id and value
  38.         }
  39.     }
  40.  
  41.     public static class JsonFormatter {
  42.         public byte[] format(Event event) {
  43.             // format "event" into json string
  44.         }
  45.     }
  46. }
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55. /**
  56.  * This version is:
  57.  *  - using DI, all the collaborators/dependencies are **created outside the EventSender** and injected
  58.  *  - has tight coupling with "RandomGenerator" and "JsonFormatter" specific classes
  59.  */
  60. public class TightCouplingWithDI {
  61.     public static void main(String[] args) throws ExecutionException, InterruptedException {
  62.         // this part of work is done by DI framework if any such is used (spring DI, micronaut DI, guice, etc.)
  63.         // but may be done manually just like here, when no DI framework is used and DI is done manually
  64.         var generator = new RandomGenerator();
  65.         var formatter = new JsonFormatter();
  66.         var eventSender = new EventSender(generator, formatter);
  67.         // ---------------------------------------------
  68.  
  69.  
  70.         eventSender.send().get();
  71.     }
  72.  
  73.     @Data
  74.     public static class Event {
  75.         private final String id;
  76.         private final BigDecimal value;
  77.     }
  78.  
  79.     public static class EventSender {
  80.         private final RandomGenerator generator;
  81.         private final JsonFormatter formatter;
  82.  
  83.         public EventSender(RandomGenerator generator, JsonFormatter formatter) {
  84.             // when DI is applied, then components never create their collaborators, instead all the collaborators are
  85.             // managed outside and are passed either as constructor params or via setters
  86.             this.generator = generator;
  87.             this.formatter = formatter;
  88.         }
  89.  
  90.         public CompletableFuture send() {
  91.             var event = generator.generate();
  92.             var serialForm = formatter.format(event);
  93.             // send bytes
  94.         }
  95.     }
  96.  
  97.     public static class RandomGenerator {
  98.         public Event generate() {
  99.             // generate event with random id and value
  100.         }
  101.     }
  102.  
  103.     public static class JsonFormatter {
  104.         public byte[] format(Event event) {
  105.             // format "event" into json string
  106.         }
  107.     }
  108. }
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123. /**
  124.  * This version is:
  125.  * - not using DI, generator and formatter are created **inside the EventSender**
  126.  * - components are loosely coupled
  127.  */
  128. public class LooseCouplingWithoutDI {
  129.     public static void main(String[] args) throws ExecutionException, InterruptedException {
  130.         var eventSender = EventSenderFactory.getInstance().create();
  131.         eventSender.send().get();
  132.     }
  133.  
  134.     @Data
  135.     public static class Event {
  136.         private final String id;
  137.         private final BigDecimal value;
  138.     }
  139.  
  140.     public interface EventSender {
  141.         CompletableFuture send();
  142.     }
  143.  
  144.     public interface Generator {
  145.         Event generate();
  146.     }
  147.  
  148.     public interface Formatter {
  149.         byte[] format(Event event);
  150.     }
  151.  
  152.     public static class EventSenderFactory {
  153.         private static final EventSenderFactory INSTANCE = new EventSenderFactory();
  154.  
  155.         private EventSenderFactory() {
  156.         }
  157.  
  158.         public static EventSenderFactory getInstance() {
  159.             return INSTANCE;
  160.         }
  161.  
  162.         public EventSender create() {
  163.             // here we decide which impl to use - based on configuration or any other factors
  164.             if (config.get("sender.type").equals("http")) {
  165.                 return new HttpSender();
  166.             } else {
  167.                 // ......
  168.             }
  169.         }
  170.     }
  171.  
  172.     public static class GeneratorFactory {
  173.         private static final GeneratorFactory INSTANCE = new GeneratorFactory();
  174.  
  175.         private GeneratorFactory() {
  176.         }
  177.  
  178.         public static GeneratorFactory getInstance() {
  179.             return INSTANCE;
  180.         }
  181.  
  182.         public Generator create() {
  183.             // similar to EventSenderFactory.create() method
  184.             if (config.get("generator.type").equals("random")) {
  185.                 return new RandomGenerator();
  186.             } else if (config.get("generator.type").equals("sine")) {
  187.                 return new SineGenerator();
  188.             } else {
  189.                 // etc.......
  190.             }
  191.         }
  192.     }
  193.  
  194.     public static class FormatterFactory {
  195.         private static final FormatterFactory INSTANCE = new FormatterFactory();
  196.  
  197.         private FormatterFactory() {
  198.         }
  199.  
  200.         public static FormatterFactory getInstance() {
  201.             return INSTANCE;
  202.         }
  203.  
  204.         public Formatter create() {
  205.             // similar to previous factories
  206.         }
  207.     }
  208.  
  209.     public static class HttpSender implements EventSender {
  210.         private final Generator generator;
  211.         private final Formatter formatter;
  212.  
  213.         public HttpSender() {
  214.             // here we're NOT tightly coupled with exact implementations
  215.             // however we're NOT using DI, but instead HttpSender performs collaborators creation
  216.             this.generator = GeneratorFactory.getInstance().create();
  217.             this.formatter = FormatterFactory.getInstance().create();
  218.         }
  219.  
  220.         public CompletableFuture send() {
  221.             var event = generator.generate();
  222.             var serialForm = formatter.format(event);
  223.             // send bytes over http
  224.         }
  225.     }
  226.  
  227.     public static class KafkaSender implements EventSender {
  228.         private final Generator generator;
  229.         private final Formatter formatter;
  230.  
  231.         public HttpSender() {
  232.             // here we're NOT tightly coupled with exact implementations
  233.             // however we're NOT using DI, but instead KafkaSender performs collaborators creation
  234.             this.generator = GeneratorFactory.getInstance().create();
  235.             this.formatter = FormatterFactory.getInstance().create();
  236.         }
  237.  
  238.         @Override
  239.         public CompletableFuture send() {
  240.             var event = generator.generate();
  241.             var serialForm = formatter.format(event);
  242.             // send bytes to kafka topic
  243.         }
  244.     }
  245.  
  246.     public static class RandomGenerator implements Generator {
  247.  
  248.         @Override
  249.         public Event generate() {
  250.             // generate event with random id and value
  251.         }
  252.     }
  253.  
  254.     public static class SineGenerator implements Generator {
  255.  
  256.         @Override
  257.         public Event generate() {
  258.             // generate event by sine wave
  259.         }
  260.     }
  261.  
  262.     public static class JsonFormatter implements Formatter {
  263.  
  264.         @Override
  265.         public byte[] format(Event event) {
  266.             // format "event" into json string
  267.         }
  268.     }
  269.  
  270.     public static class KryoFormatter implements Formatter {
  271.  
  272.         @Override
  273.         public byte[] format(Event event) {
  274.             // serialize event using Kryo
  275.         }
  276.     }
  277. }
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297. /**
  298.  * This version is:
  299.  * - using DI, all the collaborators/dependencies are **created outside the EventSender** and injected
  300.  * - components are loosely coupled
  301.  */
  302. public class LooseCouplingWithDI {
  303.  
  304.     public static void main(String[] args) throws ExecutionException, InterruptedException {
  305.         // this part of work is done by DI framework if any such is used (spring DI, micronaut DI, guice, etc.)
  306.         // but may be done manually just like here, when no DI framework is used and DI is done manually
  307.         Generator generator;
  308.         switch (config.get("generator.type")) {
  309.             case "random":
  310.                 generator = new RandomGenerator();
  311.                 break;
  312.             case "sine":
  313.                 generator = new SineGenerator();
  314.                 break;
  315.             default:
  316.                 throw new ConfigurationException();
  317.         }
  318.         Formatter formatter;
  319.         switch (config.get("formatter.type")) {
  320.             case "json":
  321.                 formatter = new JsonFormatter();
  322.                 break;
  323.             case "kryo":
  324.                 formatter = new KryoFormatter();
  325.                 break;
  326.             default:
  327.                 throw new ConfigurationException();
  328.         }
  329.         EventSender eventSender;
  330.         switch (config.get("sender.type")) {
  331.             case "http":
  332.                 eventSender = new HttpSender();
  333.                 break;
  334.             case "kafka":
  335.                 eventSender = new KafkaSender();
  336.                 break;
  337.             default:
  338.                 throw new ConfigurationException();
  339.         }
  340.         // ---------------------------------------------------------------------
  341.  
  342.  
  343.         eventSender.send().get();
  344.     }
  345.  
  346.     @Data
  347.     public static class Event {
  348.         private final String id;
  349.         private final BigDecimal value;
  350.     }
  351.  
  352.     public interface EventSender {
  353.         CompletableFuture send();
  354.     }
  355.  
  356.     public interface Generator {
  357.         Event generate();
  358.     }
  359.  
  360.     public interface Formatter {
  361.         byte[] format(Event event);
  362.     }
  363.  
  364.     public static class HttpSender implements EventSender {
  365.         private final Generator generator;
  366.         private final Formatter formatter;
  367.  
  368.         public HttpSender(Generator generator, Formatter formatter) {
  369.             // when DI is applied, then components never create their collaborators, instead all the collaborators are
  370.             // managed outside and are passed either as constructor params or via setters
  371.             this.generator = generator;
  372.             this.formatter = formatter;
  373.         }
  374.  
  375.         public CompletableFuture send() {
  376.             var event = generator.generate();
  377.             var serialForm = formatter.format(event);
  378.             // send bytes over http
  379.         }
  380.     }
  381.  
  382.     public static class KafkaSender implements EventSender {
  383.         private final Generator generator;
  384.         private final Formatter formatter;
  385.  
  386.         public KafkaSender(Generator generator, Formatter formatter) {
  387.             // when DI is applied, then components never create their collaborators, instead all the collaborators are
  388.             // managed outside and are passed either as constructor params or via setters
  389.             this.generator = generator;
  390.             this.formatter = formatter;
  391.         }
  392.  
  393.         @Override
  394.         public CompletableFuture send() {
  395.             var event = generator.generate();
  396.             var serialForm = formatter.format(event);
  397.             // send bytes to kafka topic
  398.         }
  399.     }
  400.  
  401.     public static class RandomGenerator implements Generator {
  402.  
  403.         @Override
  404.         public Event generate() {
  405.             // generate event with random id and value
  406.         }
  407.     }
  408.  
  409.     public static class SineGenerator implements Generator {
  410.  
  411.         @Override
  412.         public Event generate() {
  413.             // generate event by sine wave
  414.         }
  415.     }
  416.  
  417.     public static class JsonFormatter implements Formatter {
  418.  
  419.         @Override
  420.         public byte[] format(Event event) {
  421.             // format "event" into json string
  422.         }
  423.     }
  424.  
  425.     public static class KryoFormatter implements Formatter {
  426.  
  427.         @Override
  428.         public byte[] format(Event event) {
  429.             // serialize event using Kryo
  430.         }
  431.     }
  432. }
  433.  
Add Comment
Please, Sign In to add comment