Be good to yourself. Write testable code.

Be good to yourself. Write testable code.

Fbe54abf4094d19f1548783d072a7fa7?s=128

Nenne (Adora) Nwodo

November 16, 2019
Tweet

Transcript

  1. Be good to yourself. Write testable code.

  2. None
  3. SUaaS Suffering as a Service

  4. None
  5. None
  6. Hi, I’m Adora! Software Engineer, Microsoft Mixed Reality Writer &

    Youtuber, AdoraHack Twitter: @theadoranwodo
  7. Unit tests run against an individual unit of software @theadoranwodo

  8. This means we should learn to write code so that

    we can test each unit of software @theadoranwodo
  9. How do we write testable code? @theadoranwodo

  10. Question: How do we write testable code? Answer: SOLID Principles

    @theadoranwodo
  11. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle @theadoranwodo
  12. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle @theadoranwodo interface Input { Data fetch(); } interface Output { DataObject convertToObject (String result); } interface ProcessManager { String process(Data data); } class ProcessJob { // ... ProcessJob (Input input, Output output, ProcessManager processManager ) { this.input = input; this.output = output; this.processManager = processManager; } DataOutput process() { Data data = this.input.get(); String result = this.processManager .process(data); return this.output.convertToObject(result); } }
  13. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle @theadoranwodo
  14. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle @theadoranwodo Open to extensions and closed to modifications _______________________________ Practice coding to abstractions, rather than core implementations
  15. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle @theadoranwodo
  16. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle @theadoranwodo Functions that use references to base classes must be able to use objects of derived classes without knowing it.
  17. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle @theadoranwodo
  18. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle @theadoranwodo Don’t make clients depend on methods they don’t use
  19. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle @theadoranwodo interface Vehicle { void brake(); void truttle(); void clutchDown (); } class MyPrado implements Vehicle{ void brake(){ // code here } void clutchDown (){ /* I don’t need this method but I have to implement it by force so I’d just throw an exception here */ throw new UnsupportedException(); } void truttle(){ // code here } } Don’t do this
  20. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle @theadoranwodo interface Vehicle { void brake(); void truttle (); } interface Manual { void clutchDown (); } class MyPrado implements Vehicle { void brake(){ // code here } void truttle (){ // code here } } class MyMaserati implements Vehicle, Manual { void brake(){ // code here } void clutchDown (){ // code here } void truttle (){ // code here } } Do this
  21. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle @theadoranwodo
  22. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle @theadoranwodo High level modules should not depend on low level modules, both should depend on abstractions. ________________________________________ Abstractions should not depend on details but details should depend on abstractions
  23. @theadoranwodo interface Input { Data fetch(); } interface Output {

    DataObject convert(String result); } interface ProcessManager { String process(Data data); } class ProcessJob { // ... ProcessJob (Input input, Output output, ProcessManager processManager ) { this.input = input; this.output = output; this.processManager = processManager; } DataOutput process() { Data data = this.input.get(); String result = this.processManager .process(data); return this.output.convert(result); } } ProcessJob Input ProcessManager Output DatabaseInput CustomProcessManager JSONOutput Interface Interface Interface Implementation Implementation Implementation uses uses uses implements implements implements
  24. What else can we do to make sure our code

    is testable? @theadoranwodo
  25. @theadoranwodo Dependency Injection. - Loosely coupled code - Ask for

    what you need, don’t look or try to create. - Each unit should have limited knowledge about other units
  26. @theadoranwodo Make sure object creation logic & app logic are

    different Your application should have two types of classes: - Factories for creating new objects. - Application classes that contain the business logic for your app.
  27. @theadoranwodo Respect your constructors Don’t do work in your constructors

    class Person{ private int buildCode; Person(BuilderHelper helper, int seed){ buildCode = helper.getCodeBuilder () . generateCode (seed) . build(); } } Don’t do this
  28. @theadoranwodo Respect your constructors Don’t do work in your constructors

    class Person{ private int buildCode; Person(int buildCode){ this.buildCode = buildCode; } } Do this instead
  29. @theadoranwodo Less static methods Avoid static methods as much as

    possible: - They are hard to test. - They are hard to mock.
  30. Code samples @theadoranwodo

  31. Let’s see a common bad real life example @theadoranwodo

  32. class Hotel { public Room getRoom(int roomId) { RoomDbClient client

    = RoomDbClientProvider .getClient(); Room room = null; try { room = client.getRoomRecord(roomId); } catch(DatabaseException ex){ ex.printStackTrace (); } } } class RoomDbClient implements DbClient { // more code above … public Room getRoomRecord(int id) { DbHelper helper = new DbHelper(“room”); //... Room room = helper.read(id); return room; //... } } @theadoranwodo
  33. class Hotel { public Room getRoom(int roomId) { RoomDbClient client

    = RoomDbClientProvider .getClient(); Room room = null; try { room = client.getRoomRecord(roomId); } catch(DatabaseException ex){ ex.printStackTrace (); } } } class RoomDbClient implements DbClient { // more code above … public Room getRoomRecord(int id) { DbHelper helper = new DbHelper(“room”); //... Room room = helper.read(id); return room; //... } } @theadoranwodo
  34. class Hotel { public Room getRoom(int roomId) { RoomDbClient client

    = RoomDbClientProvider .getClient(); Room room = null; try { room = client.getRoomRecord(roomId); } catch(DatabaseException ex){ ex.printStackTrace (); } } } class RoomDbClient implements DbClient { // more code above … public Room getRoomRecord(int id) { DbHelper helper = new DbHelper(“room”); //... Room room = helper.read(id); return room; //... } } @theadoranwodo
  35. class Hotel { public Room getRoom(int roomId) { RoomDbClient client

    = RoomDbClientProvider .getClient(); Room room = null; try { room = client.getRoomRecord(roomId); } catch(DatabaseException ex){ ex.printStackTrace (); } } } class RoomDbClient implements DbClient { // more code above … public Room getRoomRecord(int id) { DbHelper helper = new DbHelper(“room”); //... Room room = helper.read(id); return room; //... } } @theadoranwodo
  36. Now, let’s see a basic foobar example @theadoranwodo

  37. class Foo { public Bar getBar(int barId) { Rabbit rabbit

    = new Rabbit(); Animal animal = new Animal(); Bar bar = animal.doSomething (barId, rabbit); return bar; } } @theadoranwodo
  38. class Foo { public Bar getBar(int barId) { Rabbit rabbit

    = new Rabbit(); Animal animal = new Animal(); Bar bar = animal.doSomething (barId, rabbit); return bar; } } @theadoranwodo
  39. class Foo { private final Rabbit rabbit; private final Animal

    animal; public Foo(RabbitFactory rabbitFactory, AnimalFactory animalFactory ){ this.rabbit = rabbitFactory .Create(); this.animal = animalFactory .Create(); } // more code … public Bar getBar(int barId) { Bar bar = animal.doSomething (barId, rabbit ); return bar; } } @theadoranwodo
  40. This is Jennifer. Jennifer writes testable code. Her team members

    love her because it’s easy to understand and test her code. Jennifer is a great Engineer. Be like Jennifer. @theadoranwodo
  41. Thank you! www.adoranwodo.com @theadoranwodo