Thursday, 19 May 2016

I did pair programming with my colleague, do I need a peer code review?

In my opinion the short answer is: yes

Pair Programming is a tool to aid production of an artefact, be it code, a user document, an email, a presentation or some other artefact.

Peer Review is a quality assurance tool or checkpoint in our process. We are checking the output of the production process. Lack of knowledge of the production process is a benefit for Peer Review, however you must understand the problem being solved. It is a clean set of eyes over the problem and the proposed solution.

Pairing and peer review are therefore complimentary and neither one depends on doing the other. It’s a good idea to do both. We know that pairing during production produces less defects. We know that peer review helps catch defects before the customer gets the product.

What pairing means for peer reviews is that we should find less issues and for those issues we find, their solution should be less time consuming. There should be less "returning to the drawing board". But pairing doesn’t mean we should no longer do peer reviews. A good quality process demands a quality checkpoint.

Updated 15th August, 2016

Tuesday, 3 May 2016

Email communication

The single biggest problem in communication is the illusion that it has taken place. George Bernard Shaw

In this post, I propose that email amplifies the illusion of communication and it should be avoided on most occasions.

Reliable communication is one of the biggest challenges of the human race, not alone the software development workplace. Effective communication is as equally dependent on the receiver, as it is on the sender or initiator of the communication.

There are a significant proportion of our engineering fraternity who demand and insist we use email because it's become an integral tool in the office place in the last 25 years. However, contrary to popular opinion, I would like to propose that it has to be one of the worst communication mediums.

In agile we favour Individuals and Interactions over processes and tools, so at an academic level we agree that email is terrible (it's a tool!), but practically day to day, we don't live it.

I see at least the following short comings of email as a medium for communication.

Problems

Feedback: The first problem with email communication is the lack of feedback on the message we deliver. Unless a receiver actually replies, we can only assume they read the message and that they understood it. Generally you only get a swift response to an email when you made an obvious mistake or the receiver strongly disagrees with you!

No tone: Communication is not just what you say, it's also how you say it. The same words said in a certain tone, have completely the opposite meaning (sarcasm). It's very difficult for the reader to detect the tone in an email. All we have is the literal words. However, often the email sender will compose the message as if they are saying it to the receiver, in their head - tone and all.

Mistakes: We easily make mistakes in what we write or type and it's nearly impossible for us to spot our own mistakes.

  • Grammer matters, for intent. A comma missing or inserted incorrectly changes the meaning of a sentence.
  • We can easily leave out a word - this can invert the meaning
  • Fundamentally many of us can't proofread our own mails (Pair email writing?)

Temporal aspect: We can't control when the reader reads the information. With the spoken word we have instant receipt - we can watch the facial reactions of the receiver. With email we assume the reader reads our mail pretty soon after we sent it.

Speed reading: We don't read every word because we quickly read email and loose out on critical detail. Or worse we click on the mail in their mail tool and think they have already read it, but didn't at all.

Volume = Noise: In my experience, the sheer volume of email I receive daily, makes it easy for me to miss important events and information. Some tools help by filtering mails - so you need to know who's "more equal than others" and focus your time reading just those mails. But the large volume magnifies the lack of feedback, the temporal aspect and the need to speed read.

Have you anything good to say about email? It's a great historical record. Most email tools have powerful search facilities. Sometimes this is useful.

Conclusion

If it's important to land your message and it usually is; first talk to some one directly or by phone. Use normal human communication to reach a conclusion and agreement easily and quickly. Then you can follow up with a short email with the decision you agreed so that they can search for it later!

Thursday, 28 April 2016

Agile Gluttony

if you want to bring in Agile Software Development to your organisation because of:

  1. you want to go faster
  2. do more
  3. do better
  4. to save money
  5. any combination of or all of the above
then you and your organisation is suffering from a serious case of Agile Gluttony.

If your primary motivation is any of the above you should really consider incremental process improvement in your current processes. I have seen on a few occasions, the first attempts at agile means a complete tearing up of the current process and the cutting out of nearly everything, except coding.

Unfortunately you can't go faster or save money by cutting corners. You can't do more by diverting everyone to coding tasks. You can't do better by delivering more code. When inevitably the organisation fails to meet the expectations the customer puts on it, there is great disappointment everywhere. The valley of despair for everyone, including the engineers, management and the customer, is a deep one.

There is only one reason to adopt agile software development processes. That is to satisfy your customers needs by the frequent delivery of working software. You care that your customer gets value. When you adopt agile for that reason, in the long term you succeed and reap the benefits. However the costs of putting in the necessary infrastructure and around your application and the coaching around your development teams that enable rapid and frequent deliveries will cost you a significant sum.

When you are able to frequently deliver working software to your customer; you don't need to go faster because you are perceived as responsive to their needs. You typically actually do less, harnessing benefits the old 80:20 rule1. You will definitely do better because you deliver less change per release and your automated test suits catch bugs the customer had before. And you will save money by not doing the features the customer doesn't want or need.


1. The 80:20 rule states that 80% of the time a user will use 20% of an application features. The features in this 20% set, are the most important features and need to work well all the time. However we need to be aware they may not be the most valuable features. The most valuable features are the ones a customer is willing to pay us for.

Thursday, 7 January 2016

Happy new year 2016

Welcome to 2016

It's a brand new year!

Recap

2015 was a great blogging year for me. I got to put down some of my thoughts on lots of things from Java, unit-tests, test coverage and aspects of teams. I set a target to write at least one article per month and I managed to achieve that. Just like 2014, I haven't published anything in November and December, but I have been gathering ideas...

Plan

So the plan for 2016 is more of the same. I want to continue to blog about software development. I'm currently in a management role, so my topics are going to swing more towards topics on managing and leading software development teams, with a small sprinkle of technical stuff, just to keep it interesting (for me!). The target, once again, is one blog entry per month. I'll definitely expand into topics such as code review and pair programming.

Wednesday, 21 October 2015

Java interview questions - level intermediate

This is the second in a series of articles on Java interview questions. These questions start to go into the details and differences of various parts of the language. Knowledge of them demonstrates a greater level of knowledge or experience than with the basics.
  1. Are static variables inherited by subclasses?
    Static variables are inherited by sub classes. However are at class level instead of object level and there is just one.
  2. Are static methods overridden by subclasses?
    That depends. If the reference used to store the object is of the super type, the super types static method is invoked. This is because static is at class level.
  3. What is the difference between a Set and a List?
    In a set an object can only exist once. In a List the same object can be added many times.
  4. Why should we use the @Override annotation?
    We should use this to ensure compile time checking that the contract of a subclass is not broken by changes to the superclass.
  5. What is the main difference between Callable interface and Runnable interface?
    The main difference is that the call method on callable can return a typed result, that can be queried in the future. Callable also throws an exception.
  6. Whats a covariant return?
    A covariant return is allowed since Java 1.5 and means that a method can return a sub classed object of the return type. In Java 1.4 and earlier the return type had to match exactly.
  7. What is an instance initialisation block? An instance initialisation block is run once after a new object is created. There can be as many of them in the class as you like, but they run in order declared from top to bottom in the class.
  8. Does an instance initialisation block run before or after the constructor?
    They run after the call to super, but before the rest of the constructor.
  9. What is auto boxing?
    It's the ability in Java to automatically switch between the primitive type and the object, without a call to a converter method.
  10. What is widening?
    It's the ability of Java to find a method with the smallest, closest java type. For example if one method takes a long and another takes an int, if I pass a short - java will automatically "widen" the short and select the method that taken an int.
  11. What is the difference between "&&" and "&"?
    && is a short circuit logical AND, this means that if the LHS evaluates to false, the RHS will not be evaluated. In & both the left and right sides are evaluate every time. For || only if the LHS equates to false, then the RHS side evaluated. When | is used, both the LHS and RHS are always evaluated.
  12. Dzone 20 things you should know about strings
  13. What’s the difference between shallow and deep cloning
Update:25/04/2016

Wednesday, 2 September 2015

Software Oxymorons

An oxymoron is a construct that makes no sense because it joins together two terms that contradict one another. In this post we'll look at some you might come across in development projects. I'll grow this article over time. If you have any suggestions, please feel free to message me!

Oxymorons

  • Refactoring Story - A story adds customer value, something tangible that the customer can appreciate. Refactoring is changing the implementation of a software system without the knowledge of the users or customers. So we can be either doing a story or refactoring.
  • Refactoring Interfaces - An interface is part of the contract our software components and applications provide. Refactoring is changing the implementation without the knowledge of the users or customers. So if we change the contract, the users know about it. We can change interfaces or we can provide new interfaces but its not possible to refactor them.
  • Object Oriented Database - these are a niche area of database theory that haven't really caught on in wider industry and they are also an oxymoron. Databases typically need to know a lot about our classes data structures in order to persist the data in a way that facilitates efficient storage and retrieval. Because of need to know the classes data structure, OODBMS break encapsulation, a key principle of object orientation. This places change restrictions and limitations on our software - something OO is supposed to help avoid

Definitions:

  • Refactoring - Changing the implementation of a software system, without the knowledge of the users/components that depend on the software system.
  • Story - Something that adds tangible customer value.
  • Interface - The point of entry to a software system. Could be programatically ie like an Application Program Interface. It could be via the command line or via a Graphical system.
  • Object Oriented - Objects are programming entities that exhibit the principles of abstraction, encapsulation, polymorphism and inheritance.
  • Database - a software system that allows us to persist data to survive application restart, typically in tables, columns and rows. Columns are generally typed and can be indexed to facilitate faster querying.

Friday, 28 August 2015

Java interview questions - level easy

This is the first of a series of three articles I want to put together around some Interview questions that could be used for interviewing Java developers. In this first article, we will look at easier, basic concepts that should be covered in any introduction to Java programming. So many of the questions will deal with concepts around defining and declaring classes

  1. What is the difference between an interface and an abstract class?
    An interface is just a contract with no implementation. All methods in an interface are public and abstract. An abstract class can have some state and implementation.
  2. What are the main differences between Java and C++?
    Java is compiled to platform independent byte code that is interpreted in a virtual machine. C++ is compiled into native binaries that are not portable. Java gives automatic memory management. C++ memory management is handled by the programmer.
  3. What is the difference between a while statement and a do statement?
    A while statement may not execute, a do statement is guaranteed to execute at least once.
  4. Explain the main() method in a java program?
    What is passed to it and what is its return type? The main method is the starting point for a java application. The return type is void and the arguments to the java application are passed in an array of Strings to the main method.
  5. What's the first thing that happens in a constructor?
    The first call of every constructor must be a call to super() or this(), but never both in the same constructor. If you call this(), eventually super() must be called.
  6. What access can classes have?
    public or default. protected and private are also only allowed on methods and instance variables.
  7. What modifiers can classes have? abstract, final or strictfp
  8. What types are allowed to be in a case statement?
    byte, char, short, int and enum. In java 7 we can also switch on String
  9. Interfaces allow inheritance so can an interface have protected methods?
    No, an interface can only have public abstract methods. Update for Java 8, interfaces can now have default method implementations.
  10. Java concept of the day 25 basic questions
  11. Java concept of the day

Monday, 10 August 2015

Object Oriented Design

This short article revisits the first principles of Object Oriented Design

  1. Why is OO design better than normal procedural coding languages like Bash or C? There are a few reasons. Application code structure and naming should map more readily to real world concepts. Object Oriented design lends itself to more naturally cohesive components (related data and methods are collocated). Thanks to encapsulation, we can reduce coupling. Through the concepts of polymorphism and inheritance we can promote reuse.
  2. Explain encapsulation? The state of an object should be hidden and only manipulated by methods. The advantage here is that it allows the implementation with in the object to be changed over time without impacting components that depend on this component.
  3. What is inheritance? Classes can automatically obtain the functionality and state of a parent class. This is also known as sub classing. Inheritance is usually applied for "is a" type relationships. For example if the base class is Car, Corolla is a type of car so Corolla extends Car and automatically gets it's methods and state.
  4. What is polymorphism? This means where a parent class is used we can easily interchange objects of a sub class. For example if if we have a container that holds objects of type Car, then instances of Corolla and Golf can be added to the container. Polymorphism works best when you understand the Liskov Substitution Principle.
  5. Explain the concept of dependency? Dependency means that a relationship exists between one or more components. Dependency can be explicit or direct, for example an import statement at the top of a Java class definition. Or Dependency can be implicit or indirect for example two components know the format of an XML document. Generally we favour components that have a lower number of dependencies on other components. And we favour explicit dependencies that are loosely coupled. Coupling is used to classify the strength of the dependency.
  6. Explain the concept of Coupling? Coupling is the measure of the dependency relationship between two components. Coupling can be tight, where a change in a class has a knock on change in another class. For example Where a component depends on the internal data fields of another component. Loose coupling means that a component depends on behaviour of another component.
  7. Should software components be tightly or loosely coupled? Good software components should favour loose coupling. In loose coupling, components depend on methods of other components. This means the internals of a component can be changed in isolation - once the contract on the interface is maintained. Tight coupling means that data fields or structure can't be changed in isolation of other components.
  8. Explain cohesion? Cohesion is how logically related are software elements that are contained with in a software component. Highly cohesive components are better. Low cohesive components should be split into further components to promote reuse and reduce coupling.
  9. Are getters and setters "evil"? Short answer yes. Because it breaks encapsulation. Breaking encapsulation means your class is less maintainable in the future. Exposing state to other classes means other classes can contain logic that manipulates the state. Go here for a good exploration of this concept. Systems that use getters and setters are object based, but not object oriented.
Original article 10th August, 2015.
Updated 22nd October, 2015 - clarified coupling, added a statement on dependency. Updated 13th November, 2018 - Spelling mistake corrections

Monday, 13 July 2015

The test first attitude

Problem statement:

I want to ensure a number is between the range of 5 and 9, inclusive.

Thinking in Test first. 

I can produce 5 test cases for this very simple problem.

A test of a number less than 5. 2. Returns false
A test of the left bound. 5. Returns true
A test of a number in the middle of the range. 7. Returns true.
A test of the right bound. 9. Returns true
A test of a number greater than 9. 15. returns false



Taking a step back, we want to be really thorough we could write the following tests as well.
A test just outside the left bound. 4. False
A test just inside the left bound. 6. True

A test just inside the right bound. 8. True
A test just outside the right bound. 10. False



I define an interface to the method.

public boolean ensureNumberIsIn5To9Range(int numberToTest);

First I code up the 9 tests against the specified interface.

Execute all tests. They fail.

Now I start the solution code... I'm done when all tests pass.

I come up with a pretty standard if statement, using logical And and two return statements. The tests all pass.



However now I realise I could make this more concise and prettier for the reader. So I refactor the code to just use logical AND and simply return what it evaluated to the caller. Tests all pass.



Happy days.

Now I check the code coverage, just to be sure it meets targets. 100%. I'm done. Check the whole lot in.

Thinking in solution first approach

I'm going to promise to do some tests to get us code coverage, with a code coverage metric target of 80%. Management love code with a coverage of 80%.

I will just code up a if statement, with two boundary clauses anded together. Simple. Will then write a test that triggers the boundary clause. And another test that doesn't trigger the boundary condition so happy out.

Next I'll have a think about the interface, it's gonna be pretty simple in this case.

Open up my IDE. Fire in the interface, the algorithm and now I'll think about tests.



So looking at my code, I can see the branch (if statement). The first test I write, just takes any number outside the boundary condition. So I trigger the method with 15, expecting false. I run it, its passes and I get 75% code coverage. Wow I'm nearly there with just one test!

If I trigger the boundary condition on the if statement, then I can increase this figure. So I'll write one more test. This time I'm going to pass 7. Right in the middle of the boundary condition, I am really expecting it to pass.



I execute it. It passes. 100%!!!!!!! Happy days. Check the whole lot in. Home time.

But wait...
Did you spot the bug in the solution first approach? The upper boundary has been incorrectly coded... values of 10 will return true. It's a good thing this code wasn't used to control an auto mobile safety system, an aircraft or a train!

So I've got 100% coverage, but I'm still leaking bugs. Why?

The set of useful unit tests

We explored the set of useful tests in another article. In this simple example we see the set of useful tests consists of 9 tests. I should implement these 9 tests to ensure correctness of the code. The set of tests that gives 100% code coverage is just 2 tests. This is a significant minority of the tests I actually need to ensure correctness. Hence when reality throws in something we didn't test for, we find bugs, although I have 100% code coverage. You can see there is a large scope for bugs, even in this simple application when you test for coverage.

Spending time writing more automated tests around your top 20% of all uses cases that your users use, will give you a much greater bug count reduction in future releases. Spending any time increasing code coverage when you haven't got that 20% of your code base well tested, is waste.

Tuesday, 7 July 2015

Defining a good Unit Test suite

I measure test suites under 6 main criteria. The criteria are pretty hard and fast and there are key indicators to measure them. There is also an AND relationship between them. So if you can tick 5 out of the 6, the other one should be addressed.

  1. Trust. Tests pass when the component is ok.
  2. Comprehensiveness Majority of the ways of use for the component are covered by the tests
  3. Correct level of abstraction. Tests should be written to a stable, well defined interface. Unit tests faciliate refactoring.
  4. Language Tests should match the language of the problem
  5. Reliability. Tests fail only when the code is not ok.
  6. Independent Tests should be independent of other tests, methods and classes, in a pragmatic way. ie each test should only use methods that are "well used" in the public domain. This does not include data driven approaches.
  7. Libraries Don't test well used and independently verified libraries.

What defines a useful test suite is:

  1. A developer can be pretty sure, once the unit test suite passes, that no other functional issues will be found. We are happy to release the product after the automated suite passes.
  2. Majority of the problems are found at the unit-test level. For this our Fault Slip-through Analysis of our bugs indicates that the majority of bugs are found in the right level of test.
  3. The unit tests are a vital tool to help refactoring. I can do multiple run-test - refactor - run-test cycles, without making a change to the tests. The unit-tests are written towards the "thing" wrapped in an interface, and not just any method or any class.
  4. They reflect the language of the problem definition re using terminology the customer used. Ideally Customers should be able to understand the tests.
  5. When a test case fails, it points to an actual problem in the component
  6. Test cases shouldn't change when we change or extend the system, therefore I can trust them. Test cases are the guarantee that what worked yesterday, still works today. If we have common methods and utility classes referenced in our tests, that are changed as the system grows then we cannot depend on our tests. In other words, if I change my test code, who will test my tests?
  7. Libraries such as the extensive set of libraries in the JDK, databases like MySql, NEO4J etc are published by competent organisations and are heavily re-used in a lot of software settings. You can trust that their functionally works. Don't write tests that extensively test CRUD of database operations. You can trust that the Collections framework works. You may need to make an exception if you are using pre-release libraries or if they are libraries from your own organisation that you can't trust (i.e. it's your code that is really testing them).

What "smells" to measure that a unit test suite is useless:

  1. Developers don't trust the unit tests to verify the component. This means, more or less, that a developer isn't that confident to release the component based on unit test alone. We require a manual test before we are confident to release the product.
  2. Majority of problems are being found in later stages of testing. Our fault slip through Analysis is showing large numbers of bugs appearing in later phases of test, that could have been found in earlier phases.
  3. The unit tests are written at too low a level and now hinder refactoring. I change the internals of a component and several unit tests no longer compile, never mind that the don't run. Every method of every class has at least one unit test associated with it. Worse still, methods that should be private are public to enable testing!
  4. They reflect the terminology of the code - we see language of the solution in the tests. For example things like factories or other design patterns start appearing in the tests.
  5. Test cases regularly fail at random times during various runs. Failures are "false" because they were caused by some environmental or platform problem. For example a database service we needed wasn't started or the disk was full.
  6. All my tests depend on a test utility method I wrote a good while back and this utility method needs to be regularly changed when we add new features. Most times I add new tests, I have to change the utility method, causing a subtle change in all my tests.
  7. Lots and lots of tests that test POJO (Plain old java objects), lots and lots of tests that test whether data entry into the database was successful. Often tests are written due to inexperience and a need for coverage metrics. It may be fine to have one test that tests the connection to the database and ensures read/write works, but any more than that is overkill. For POJO's I recommend excluding them from code coverage altogether - there's no logic in there and test cases for the getters/setters are noise.


Updated 26th May, 2016

Updated 3rd June, 2016

Updated 23rd August, 2016

Updated 4th September, 2017

Updated 26th October, 2017

Updated 27th October, 2017

Updated 24th February, 2020