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

How tests simplify code

martinsson
November 15, 2018

How tests simplify code

Our tests are sometimes giving us pain. But if we listen carefully and have enough design options up our sleeve they can point us in the direction of production code simplification. Links to cognitive psychology.

martinsson

November 15, 2018
Tweet

More Decks by martinsson

Other Decks in Technology

Transcript

  1. Exceptions! exceptionalMethod(userId, data) { try { let isOwner try {

    isOwner = this.authservice.isOwnerOf(userId, data.id) } catch (e) { this.logger.error('got http exception while invoking authService') } if (isOwner) { this.dao.update(data.id, data) } } catch (daoException) { this.logger.error('exception caught') } } nonExceptionalMethod(userId, data) { let isOwner = this.authservice.isOwnerOf(userId, data.id) if (isOwner) { this.dao.update(data.id, data) } }
  2. l’angoisse de null function printItemNames(data) { if (data.prop) { if

    (data.prop.cart) { if (data.prop.cart.getList() !== null && data.prop.cart.getList() !== undefined) { for (let listItem of data.prop.cart.getList()) { if (listItem.description) { if (listItem.description.name) { console.debug('Phew, finally here!') // actual business logic console.log('And the item name is... ' + listItem.description.name) } } } } } } } function printItemNames(data) { for (let listItem of data.prop.cart.getList()) { console.debug('Phew, finally here!') // actual business logic console.log('And the item name is... ' + listItem.description.name) } }
  3. Conditions function conditionalMethod(data) { if (data.something === 'val') { doSomething()

    if (data.age <= 40 || 'toto' !== data.something) { doAThirdThing() } else { doSomethingAdditional() } } }
  4. Conditions, quand on aime … function conditionalCode(data) { if (data.prop)

    { if (data.prop.service) { if (data.prop.service.getList() === null && data.prop.service.getList().size > 0) { return 'processed ' + data.prop.service.getList().length + ' results' } else { let defaultResult = 'waiting' return defaultResult; } } } }
  5. Duplication registerEmail(person) { if (person.age < 13) { throw new

    Error('too young') } if (person.name === null) { throw new Error('person must have name') } if (person.email.indexOf('@') <= 0) { throw new Error('invalid email') } console.log('do some stuff') this.dao.insertPerson(person) } registerMobile(person) { if (person.age < 13) { throw new Error('too young') } if (person.name === null) { throw new Error('person must have name') } if (this.hasNonDigits(person.phoneNumber)) { new Error('invalid phone number') } console.log('do some stuff') this.dao.insertPerson(person) } hasNonDigits(phoneNumber) { return /[^\d]+/.test(phoneNumber) }
  6. Arguments indirects updateCartItems() { let httpSession = HttpSession.getInstance() let rawCart

    = httpSession.getCookie().getValue('cart') let cart = new Cart(rawCart) if (cart.lastModificationDate < Date.now() - 24 * 60 * 60 * 1000) { cart.removeAllItems(); } // etc ... // heavy logic to make sure availability is still ok, // that prices haven't changed // that items in the cart haven't expired etc }
  7. Service injection, injection, injection … "Chaque nouvelle dépendance doit être

    passée sur toute la callstack" NOT Injection par constructeur - un seul endroit
  8. Code inspectable function hardToTest() { let data = getStuffFromWebservice() //

    // pure logic // pure logic // pure logic // pure logic // pure logic // pure logic // pure logic // pure logic // pure logic // let result let saveResult = saveToDatabase(result) } function easyToTest() { let data = getStuffFromWebservice() let result = easyToTestPureFunction(data) let saveResult = saveToDatabase(result) } function easyToTestPureFunction(data) { // // pure logic // pure logic // pure logic // pure logic // pure logic // pure logic // pure logic // pure logic // pure logic // }
  9. “Sometimes we find it difficult to write a test …

    this usually means that our design can be improved” - S. Freeman, N. Pryce “The tests are a canary in coal mining revealing by their distress the presence of evil design vapors” - Kent Beck
  10. Notre cerveau a besoin de Blocs de 4-5 éléments noms

    cohésion assembler plutôt que modifier
  11. Notre code de prod a besoin de peu de duplication

    peux de couplage morceaux à assembler BugsZero
  12. Laissons les tests nous aider dans la quête du bon

    design Ayons zéro tolérance pour des mauvais tests