Ruby Collections and Enumerables

A Guide to Ruby Collections, Part I: Arrays

Note: Java Coding Guidelines

This book has nothing to do with coding style guide. It offers advices of writing secure, reliable, high quality Java by looking at both coding and design aspects of building Java project.

Chapter 1: Security
I’d say most content on Security and Privilege management is not familiar to ordinary Java coders. Although we are not going to use those classes and configuration directly for the majority of Java projects on the planet, it is beneficial to know how Java manages security context in the face of many daily operations: file I/O, LDAP look up, loading classes, etc. A few practical lessons are learned:

  • Literally limit the lifetime of sensitive data – “around” validate code only and erase completely afterwards with no buffering and trace what so ever.
  • Use cookie without sensitive data and perform validate with secret on server side.
  • Wrap sensitive mutable class with immutable wrapper – embrace immutability.
  • Validate anything from inside and outside, and format generated content before output.
  • Do not trust equals, clone and all the overridable methods from untrusted code. Make your class final to avoid this.
  • Use hash with salt to store password

Chapter 2: Defensive Programming

  • Limit the scope of variable and @SuppressWarnings and accessibility of classes/methods
  • Always let methods provide feed back from return values and exceptions
  • Identify file using multiple attributes instead of just path, e.g. time
  • Beware of numeric promotion!
  • Public final fields are cached in compiled file, change in later version may not be seen by library users

Chapter 3: Reliability

Reliability – the capacity to maintain a level of performance when used under specified conditions. The faults in requirement, design and implementation introduce failures. A few lessons learned:

Encode relationship between constant definitions

Use try-with-resources

Handle runtime error gracefully instead of using assertions

Do not serialise handles to system resource – use transient

Direct buffer creation is expensive. Use direct buffer for long lived, frequently used objects.

Remove short-lived objects from long-lived containers – null them or reference to a special singleton NULL object

Good Practice: Git Commit Message, PR, Versioning and Code Review

How to write Git Commit Message
Good “git commit message” serves as a log that tells WHY and WHEN we made changes. Whilst diff shows only WHAT. A useful message is comprised of:
Concise (50 chars) imperative subject with reference to issue/change #
One blank line between subject and body
Body explains WHAT WHY HOW and wraps at 72 chars.

[KERNEL-003] Update Network Module to Support Wifi

Nowadays people use WIFI. For this reason, it is unacceptable for kernel not
to support Wifi.

Add a new subcomponent for network module that provides the following features:
 - listen to Wifi driver
 - save logs

One liner is acceptable if the change is simple and straightforward
Reference

Pull Request
In shared repository model, PR triggers automatic test and build on CI and review request. The guideline to writing good commit message also applies to writing good PR title and body.

Semantic Versioning
Major.Minor.Patch[-build]
Bump Major when API changes
Bump Minor when adding new functionality without breaking API
Bump Path for bug fixes.

Code review
Review commit message as well as the actual code.
Don’t forget to praise
If in doubt Question rather than Judge
Look at the whole design and code surrounding the change, not just the change itself
There are many ways to have things done – respect the author

Read file from Resource folder in Maven

I’d like to read file from resource folder for my unit test.

    @Before
    public void setUp() throws Exception {

        String resourceName = "config.file";
        String filePath = getClass().getClassLoader().getResource(resourceName).getFile();
        String tmp2 = Resources.getResource(resourceName).getFile();
        configurationFile  = new File(filePath);

        assertTrue(configurationFile.exists());
    }

Note: Pragmatic Unit Testing in Java 8 with JUnit

I read the first version when I was in college. It introduced TDD and Junit to me just fine. I’d like to read the latest version to refresh my memory. In contrast to a decade ago, TDD and Java 8 are really hot nowadays.

— Part I: Foundation —

Determine What Tests to Write

Look at loops, if branches and complex conditions. Think about data variants, side effects. Think about a path of execution.

3 Step Test Method Construction

Arrange -> Act -> Assert

Tests with Exception

Use @Rule annotation with ExpectedException object. Do not wrap checked exception with try/catch. Instead rethrow the exception ” @Test public void method() throws Exception {}”. In this way, JUnit can report an error instead of a failure.

Organise Tests

Test behaviour rather than methods.

Physically separate tests from production code.

Exposing private behavior is worse than exposing private data. This means redesign is needed.

One test for one case with descriptive naming.

Tests are documents

Do not use comments to clarify test purpose. Instead, improve test name, local-variable name, use constants, hamcrest asserstion, and split tests.

Tests Naming

doOpsGneratesResult | someResultCooursWhenCondition

WhenDoBehaviorThenResult (short for given when then) – BDD

Before and After

The order of executing multiple before is unknown. After will execute even after “fail”.

Slow Tests

Annotate slow tests with category annotation.

Not run all the tests – caution though.

— Part II: Advanced —

FIRST: Characteristics of quality tests

  1. Fast and First (TDD)
  2. Isolated
  3. Repeatable – Java provides “fixed clock” Clock.fixed(Instant, zone) besides the “real clock” Clock.systemUTC()
  4. Self-validating – Assertion and CI tool
  5. Timely – Test more frequently.

Right-BICEP: what kinds of tests to write

  1. Right results: adapt unit tests to the latest requirements. test “happy path” here aiming for right answer.
  2. Boundary conditions
  3. Inverse relationships – sqrt(25) * sqrt(25) == 25
  4. Cross-check results – check with complement cases
  5. force Error conditions – write test that forces error to happen, this includes system load, network error, etc
  6. Performance within bounds – JMeter JUnitPerf

CORRECT: boundary conditions

  1. Conform to an expected format
  2. Ordered / unorderd
  3. Range
  4. Reference – anything external under no direct control. Behave gracefully when preconditions and postconditions are not met.
  5. Existence
  6. Cardinality – enough values. “0-1-n( 1 < x < N case + N case )” rule.
  7. Time – order, timing

— Part III: Refactor, Design and Mock —

JUnit helps with refactoring, which yields more maintainable clean code.

Single method serves single purpose. Command-Query Separation: a method either executes a command or answers a query, not both.

Single class serves single purpose. Map class to concept not concrete notions. “Profile and MatchProfile” example shows how to delegate the matching procedure to a MatchProfile class.

SOLID Class-design

  • Single Responsibility
  • Open-closed Principle – open for extension but closed for modification.
  • Liskov Substitution – overrided methods do not break functionality
  • Interface segregation – Split large interface into smaller interfaceS.
  • Dependency inversion – high level modules do Not depend on low level modules. Instead, both depend on abstractions. Details depend on abstraction.

Mock

Methods to inject dependency: new constructor, setter method, override factory, abstract factories, use tools such as Google Guice or Spring.

While speeding up tests, Mock introduces a gap between tests and production code. Hence write integration tests to cover these gaps.

Test cleanupRefactoring Tests besides refactoring production code.

Make clean test code – organised, short and simple.

  • Unnecessary Test Code: let test method throws exception instead of wrapping using try/catch
  • Missing Abstractions: write customised matcher that extends TypeSafeMatcher
  • Irrelevant Information: eliminate unnecessary data and use good naming
  • Multiple assertions: use multiple assertions only if they have to be used all together to complete a single behaviour. Only single purpose test is allowed.
  • Irrelevant Details in Test: Move irrelevant “to test” code to @before and @after.
  • Misleading organization: organise as arrange/act/assert AAA.
  • Implicit Meaning: make text and names explicit.

— Part IV: TDD, Test Threads and Persistence, CI —

– TDD  – Test often while making SMALL steps. Refactor often. Split Tests to multiple TestClasses even if I am testing the same class. This will make the methods’ name shorter. Test names serve as documentation. Naming is of great importance.

– Testing Threads and Persistence –

Quote: A> “rework the design to better support testing by separating concerns”; B> “Break dependencies using stubs and mocks”

– Testing on a Project 

Code coverage and CI. 70% coverage is usually a guideline. Use CI to improve code quality of the whole team.