Professional Development, 7/20 through 7/26/2015

Career

Software Development

Process

Psychology

Advertisements

Professional Development 7/13 through 7/19/2015

Career

Software Development

Craftsmanship

Notes on Tara Nicholson’s Talk, “The Quality Of Things,” From CodeStock 2015

This year at CodeStock I attended a talk by Tara Nicholson on the subject of quality assurance. Several of my colleagues wanted access to my notes on the talk and I thought this would be the best forum for those notes. The slides from Tara’s presentation can be found here.

The following are my notes:

“Software Quality is the degree to which written code meets product requirements, has value, and is maintainable.”

Where do bugs come from?

  • Things change.
  • Ambiguity
  • Lack of understanding of requirements. (Tara stated that she thinks that this is the #1 source of bugs in software)

Think about software quality early. The cost at each stage of the development process increases exponentially.

  • The agile testing quadrants. (Source: Lisa Crispin – http://lisacrispin.com/2011/11/08/using-the-agile-testing-quadrants/)
  • How? Create habits that routinely draw out things you have not thought of.
    • Make use of quick cards – a card each member of the development team carries that has a list of the elements, integrations, and dependancies to think about related to QA during the development process.
    • The “Grocery List” – A list of all features and requirements that were agreed upon by the business, development team, and QA team have agreed on. Note: some may not make it to production.
  • Do you need a dedicated test team? It may not always be feasible, but it certainly is optimal.

Load and Performance Monitoring

  • Server vs Page performance – can the server handle the load vs is the app performant from the users point of view
  • Tools used at scripts
    • Load Runner – runs load tests on the server in a virtual(non-production) environment.
    • jMeter – back-end profiler
    • Webpagetest – opensource front-end profiler.
    • Speedcurve – for pay app from Webpagetest that digests the report from Webpagetest and make optimization suggestions.
    • NewRelic – Infrastructure performance tester.

Compatibility

  • What are the costs of supporting compatibility (what does it cost to run on IE8?)
  • Must consider the platform (Win7, linux), carrier (Verison, AT&T), and client (Firefox, IE)
  • Who owns the decision on compatibility? Do we have to support IE8 because the CEO’s son won’t use anything else?
  • Plan early for compatibility and create a strategy to support it.
  • If you decide not to support something, highly consider partial support. (i.e. works in IE8, but not optimally)
  • Know your traffic/demographics – there is no reason to support Opera if no one visits your site using it.

Automation

  • Automate tests – Scripps uses JBehave for BDD
    • Small tests – unit tests that rarely change. <- most tests here.
    • Medium tests – integration tests that change occasionally.
    • Large tests – UI/Integration tests that change frequently. (i.e. user authentication works) <- fewest tests here
  • Release Automation – Continuous integration, nuff said.
    • Jenkins
    • CloudBees
    • CruiseControl
  • Infrastructure Automation
    • Automate content updates.

Resources

Extension Dilema

I was just working on a little Open Source project I have where I need an un-directed graph to represent relationships between people who have and have not met. I have also been working on a little open source project that supplies basic graph algorithms (which can be found here). I figured the best course of action would be to import the library and extend the node class to represent a person. Then I could add my own AddNeighbor and RemoveNeighbor methods. Everything went well until time to run unit tests and I found something peculiar.

The original implementation of Node is very generic and is as follows:

 public class Node<T> 
    {
        public List<Node<T>> Neighbors { get; private set; }

        public T Data { get; private set; }

        public Node(T data)
        {
            if (data == null) throw new ArgumentNullException("data");
            Data = data;
            Neighbors = new List<Node<T>>();
        }

        public void AddNeighbor(Node<T> node)
        {
            if (node == null) throw new ArgumentNullException("node");
            if (!Neighbors.Contains(node))
            {
                Neighbors.Add(node);
            }
        }
    }

The implementation was as easy as adding a RemoveNeighbor method to the Node class:

public void RemoveNeighbor(Node<T> node)
        {
            if (node == null) throw new ArgumentNullException("node");
            if (Neighbors.Contains(node))
            {
                Neighbors.Remove(node);
            }
        }

At this point I could extend Node and write my own add and remove neighbor methods:

public class Person : Node<int>
    {
        public Person(int data) : base (data){}

        public void RemoveNeighbor(Person person1, Person person2)
        {
            person1.RemoveNeighbor(person2);
            person2.RemoveNeighbor(person1);
        }

        public void AddNeighbor(Person person1, Person person2)
        {
            person1.AddNeighbor(person2);
            person2.AddNeighbor(person1);
        }
    }

For a first try I was very pleased with my efforts, but when I went to implement other functionality in the application, I noticed that the method signatures were clunky. I wanted to do something like this:

person1.AddNeighbor(person2);
person1.RemoveNeighbor(person2);

So to implement that, I added two extension methods that looked like the following:

        public static void RemoveNeighbor(this Person person1, Person person2)
        {
            person1.RemoveNeighbor(person2);
            person2.RemoveNeighbor(person1);
        }

        public static void AddNeighbor(this Person person1, Person person2)
        {
            person1.AddNeighbor(person2);
            person2.AddNeighbor(person1);
        }

If you already can see what is going to happen, this compiles just fine. These are valid overloads of the methods. Unfortunately, the compiler assumes that I want the Node’s implementation when I use it as demonstrated as above, since the signatures in the consumer are equivalent, even though I know I want to use the extension methods, so unit tests start failing.

The only way I can see around this is for me to name my extension methods differently. I would be interested to hear from someone who knows how to specify which method to use on the consumers side given that the method signatures are equivalent.
 

Professional Development 6/29 through 7/5/2015

Process

Career