code thoughts
and
other stuff

I've no idea what I'm doing

quick break down...


  • being a professional
  • thinking about your code
  • code design principles
  • code smells
  • design patterns
  • tests

being a professional


Key points


  • take responsibility
  • know your field
  • collaborate
  • mentoring
  • learn to say no
  • managing your time
  • estimations

take responsibility


  • QA should find nothing
  • Aim for tests to have 90%+ code coverage
  • Ensure software is easily changeable (S.O.L.I.D)

know your field


  • Design Patterns (Gang of Four's 24 patterns)
  • Design Principles (S.O.L.I.D, DRY)
  • Methodologies (Agile, Scrum, Kanban, Waterfall)
  • Disciplines (TDD, BDD & a million other things)
  • Artifacts (UML)

collaborate


Plan, design and write code together...

  • Share knowledge between teams
  • Promotes alternative solutions
  • Potentially fewer errors

mentoring


  • Quickly realise holes in your understanding
  • Long forgotten reasons why to ignore
    certain techniques
  • Look after juniors. Give direction

learn to say "no"


  • Don't compromise quality or stability
  • Don't agree to 'try'
  • When saying 'no', offer compromises
  • Help educate management

managing your time

The only person responsible for managing your time is you


  • Only go to meetings that actually need you

  • Leave a meeting if it becomes a waste of your time

  • Discussions that last longer than 5mins requires data

  • Avoid 'blind alleys' & 'messes' - they're a time black hole
  • Keep stand-ups short and focused! (yesterday, today, blockers)

estimations


  • Don't estimate a job by yourself

  • Team members recognise different
    problem areas

  • Break tasks up into smaller sub tasks
    and estimate each individual task.
    Total time will likely end up greater.

thinking about your code

UML (Unified Modeling Language)


UML gives you...


  • Clear and concise architecture
  • Up-front design decisions
  • Less errors and more efficiency
  • Clarity for new team members

class diagrams

Describes Classes and their relationship to each other
---------------           ---------------
| ClassName | | ClassName |--------------- ---------------
| Properties | --------> | Properties |--------------- ---------------
| Methods | | Methods |--------------- ---------------
Different arrowheads describe different relationships
(inheritance - white, composition - diamond, association - black)

object diagrams

Useful for exploring "real world" examples of
objects and the relationships between them
 

sequence diagrams

John Cleveley's MVCP (Presenter) design


failing that...

Just get your pen and paper out...

wasn't that fun!



code design principles

S.O.L.I.D

  • Single Responsibility Principle
  • Open/Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

Not always attainable, but it's worth aiming high

single responsibility

Fairly self-explanatory

  • Objects (methods too) should
    have one responsibility (promotes testability)


  • Objects gain
    'high cohesion' (better method relation)

Probably the single best/easiest way to improve your code!
http://csswizardry.com/2012/04/the-single-responsibility-principle-applied-to-css/

open/closed


  • open for extension, closed for modification
  • avoid editing a base class (except to fix errors)
  • but never add new functionality to a base class
  • should be easy to extend a base class rules
  • utilise polymorphism (via interface contracts)



Liskov Substitution


  • parent object replaceable by subtype
  • promotes a more flexible system
  • exposes a real IS-A relationship
  • extend the base but don't modify base

LSP states: when overriding a method in a subclass:
  • Signature must match parent
  • what to accept must be the same or weaker
  • what to expect must be the same or stronger
  • Exceptions thrown must match parent

Interface Segregation


Clients should not be forced to depend on methods that they do not use.

  • avoid generic interfaces
  • specific interfaces increases cohesion
  • avoids side-effects caused by changes

dependency inversion


  • components should depend upon
    abstractions instead of implementations

  • relies on interfaces and polymorphism
    (similar to Open/Closed principle)

  • inject dependencies and
    use injection containers**

**injection container


  • aka Pimple (see also this blog post)

  • dependencies are clearly defined
    in one place

  • objects don't have to worry about
    dependencies of the objects they use

dont repeat yourself (dry)


This is a bonus slide \0/

If you're using/creating/referencing something 
more than twice: 
cache it

If you notice duplicated code/logic:
abstract it

CODE SMELLS


sass


  • over engineered!
  • need to keep things simple
  • use Sass but don't abuse it

we need a new CSS strategy! one that doesn't include a ton of...
 @if $core or $tablet
...or at the very least keeps it encapsulated

CSS


  • Undoing styles (reverses purpose of cascade)
  • Magic numbers  (they just work?)
  • Qualified selectors  (div.blah)
  • Generic selectors (div)
  • line-height units (trick question: no unit!)
  • Brute forcing styles ()
  • IDs
  • Generic class names (.card or .credit-card ?)

javascript/jquery


  • write 'plain vanilla' where possible
  • follow the GUTS guidelines
  • don't re-wrap jQuery objects in jQuery
  • dont wrap elements in jQuery unnecessarily
  • recognise other jQuery smells (see GUTS)
  • be wary of overuse...

 $(this).attr('id') => this.id

remember the asset controller?

TOO much info already! 

Have a read over this instead then...
  • interrogate your classes (post-opt)
  • transform complex data structures
  • well named methods negate a need for code comments
  • reduce object context (what it knows) to ensure flexibility


example patterns


  • Proxy
  • Strategy
  • Decorator
  • Factory
  • Composite
  • Command

a whirl wind tour...



Proxy


  • place object in-between user 
    and requested object
  • many different types of proxies:
    'protection' (controls access)
    'remote' (cross domain data transfer)
    'virtual' (performance)

strategy

Encapsulates an algorithm inside a class separating the selection from the implementation

  • Mix of composition and delegation
  • 'context' gets passed multiple 'strategies'
  • 'context' delegates to appropriate 'strategy'

decorator


  • Alter functionality of existing object
  • Leaving existing object un-modified
  • Different to a Facade in that the API
    doesn't change (i.e. Facade creates new API)

factory

  • Provides simple interface to
    create 
    new object instances
  • Allows easy change between
    objects from within the Factory
    (e.g. changing from object X to Y)

composite

The Composite Pattern describes a group of objects that can be treated in the same way as a single instance of an object may be.
Made up of the following pieces...
  • Component class (a task's base class)
  • Composite class (container of sub tasks)
  • Leaf class(es) (individual tasks)

command


Accumulate a number of operations
over time and execute them all at once

acceptance tests


"unit tests ensure you build the thing right, while acceptance tests ensure you build the right thing"


Most of my notes for 'unit tests'
applies to acceptance tests
so I'll keep this bit short...

things to watch out for...

  • Scenarios should be concise and focused
  • Avoid writing too many steps
  • Step Definitions shouldn't hold application code
  • Utilise Helpers to keep code maintainable
  • Scenario Outlines should be 'representative'
    note 'exhaustive' (you may other wise be
    testing code better suited for unit tests)


unit tests


Unit Tests should be written
F.I.R.S.T 
(Fast, Independent, Repeatable, Self Validating, Timely)

Fast


  • Should run fast
  • Should be run frequently

...this should all be obvious...

independent


  • Tests should not depend on other tests
  • Should be able to run tests isolated
  • Avoid leaky application state

repeatable


  • Tests should be able to run in any environment
  • This means without an internet connection
  • Tests should be reliable

Otherwise you'll always have an excuse for failing tests

self-validating


  • Tests should provide clear feedback
  • You shouldn't have to read a log file to find out
    why the test failed
  • This will avoid long manual evaluation

timely


  • Tests should be written first (TDD)
  • TDD avoids difficult to test code
  • TDD avoids poorly designed code


jasmine


  • Jasmine is a BDD unit-testing framework
  • Much more expressive (and stable) than QUnit
  • Standard features such as setUp/tearDowns
  • Can write your own matchers
  • No native AMD support though :-(

terminology


// Test Suite (i.e. group of related tests)describe('Acme widget', function(){    // Spec (i.e. individual test)    it('should ...do something', function(){        // Matcher (i.e. assertion API)        expect(true).toBeTruthy();    });});

jasmine matchers

expect(x).toBe(y);
expect(x).toBeDefined();
expect(x).toBeTruthy();
expect(x).toContain(y)
expect(x).toBeLessThan(y);

...many more...
...also can 'reverse' matchers...
expect(x).not.toBe(y);
expect(x).not.toBeDefined();
expect(x).not.toBeTruthy();
expect(x).not.toContain(y)
expect(x).not.toBeLessThan(y);

jasmine custom matchers

 beforeEach(function(){
    this.addMatchers({
        toBeArray: function (expected) {
            return Object.prototype.toString.call(this.actual) === '[object Array]' ? true : false;
        }
    });

    this.addMatchers({
        toBeNumber: function (expected) {
            return /\d+/.test(this.actual);
        }
    });

    this.addMatchers({
        toBeNaN: function (expected) {
            return isNaN(this.actual);
        }
    });

    this.addMatchers({
        toBeSameElementAs: function (expected) {
            return expected.isEqualNode(this.actual);
        }
    });
});



sinon

He pretended to have deserted the Greeks and, as a Trojan captive, told the Trojans that the giant wooden horse the Greeks had left behind was intended as a gift to the gods to ensure their safe voyage home.

spies


  • Track application use of methods
  • Call count
  • Arguments passed
  • Execution order with other Spies
  • Exceptions thrown
  • Return values

stubs


  • Pre-programmed methods
  • Canned return values
  • Are just 'fillers' 
  • Don't "directly" cause test to fail
  • Actual object under test gets the 
    data it needs to be tested
  • Sinon.js Stub implementation 
    inherits Spy functionality

mocks


  • Similar to Stubs in that they
    have pre-programmed responses
  • Mocks have expectations of what 
    methods should be called on them
  • If expectations aren't met then test will fail
  • Sinon.js Stub implementation inherits
    Spy functionality

sinon.js fake timers


  • Overwrites global setTimeout/setInterval
  • Makes them synchronous
  • Allows you to flattern timer with `tick()`

function doSomething(x){ console.log(x); }
window.setTimeout(doSomething, 1000, 'xyz');
this.clock = sinon.useFakeTimers();this.clock.tick(1000); // trigger code that would've run after 1 sec
this.clock.restore();

SINON.JS FAKE XHR


  • Overwrites global XMLHttpRequest (i.e. AJAX)
  • Makes them synchronous
  • Provides both fake XHR API and a high-level
    fake server for multiple XHR requests

this.server = sinon.fakeServer.create();this.server.respondWith('POST', '/success.json', [200, {}, JSON.stringify({reply: 'success', body: 'test'})]);
this.server.restore();

sinon.js adapter

Extra matchers to make Sinon.js more expressive

// instead of...expect(spy.calledWith('foo')).toBeTruthy();

// you can use...expect(spy).toHaveBeenCalledWith('foo');

expect(spy).toHaveBeenCalled()expect(spy).toHaveBeenCalledWith()expect(spy).toHaveBeenCalledOnce()
expect(spy).toHaveBeenCalledTwice()expect(spy).toHaveReturned()
...and more...

that's it, you can go...



Code thoughts and other stuff

By Mark McDonnell

Code thoughts and other stuff

Presentation on different code design concepts and patterns as well as some best practices related to writing code and tests.

  • 4,238