Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Be good to yourself. Write testable code.

Adora Nwodo
November 16, 2019

Be good to yourself. Write testable code.

Adora Nwodo

November 16, 2019
Tweet

More Decks by Adora Nwodo

Other Decks in Programming

Transcript

  1. Hi, I’m Adora! Software Engineer, Microsoft Mixed Reality Writer &

    Youtuber, AdoraHack Twitter: @theadoranwodo
  2. This means we should learn to write code so that

    we can test each unit of software @theadoranwodo
  3. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle @theadoranwodo
  4. 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); } }
  5. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle @theadoranwodo
  6. 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
  7. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle @theadoranwodo
  8. 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.
  9. Question: How do we write testable code? Answer: SOLID Principles

    Single Responsibility Principle Open/Closed Principle Liskov Substitution Principle Interface Segregation Principle @theadoranwodo
  10. 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
  11. 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
  12. 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
  13. 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
  14. 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
  15. @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
  16. What else can we do to make sure our code

    is testable? @theadoranwodo
  17. @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
  18. @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.
  19. @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
  20. @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
  21. @theadoranwodo Less static methods Avoid static methods as much as

    possible: - They are hard to test. - They are hard to mock.
  22. 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
  23. 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
  24. 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
  25. 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
  26. class Foo { public Bar getBar(int barId) { Rabbit rabbit

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

    = new Rabbit(); Animal animal = new Animal(); Bar bar = animal.doSomething (barId, rabbit); return bar; } } @theadoranwodo
  28. 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
  29. 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