Notes from Socrates 2019

My notes from the 2019 Conference for Software Craft and Testing

My notes from some of the sessions I attended, from hallway conversations and the schedule.

Refactoring legacy code

The refactoring session introduced me to a good heuristic on how to check what code is doing, while adding test coverage, and what parts of the code to refactor when the coverage is high enough.

When starting out with legacy code with nested control structures and method calls, you start with the leftmost code, i.e. the code that is the least indented in the method you test (assuming the indentation reflects the actual branching and looping). Ideally, you also start with the code that is closest to the assert, meaning you start from bottom (where the method has a return) to top. After each test, check your coverage and see which parts of the code are still uncovered by your tests. When your tests provide enough coverage, check your test names and content to see if they reflect the business logic contained in the system under test (SUT).

With enough coverage, you can start refactoring. For the refactoring, you start with the rightmost code, i.e. the code that is most indented in the production code. This code is the one has does the least amount of work and is the least “risky” to extract it into methods or child classes.

Someone brought up the question, if there is a refactoring counterpart to Robert C. Martins “Transformation Priority Premise” (TPP). The premise is that when you change the behavior of your code in the Test-Driven-Development cycle (to make a red test green), you make the transformation (code change) that is least complex. Martin gives a prioritized list of transformations. The question remains, if possible refactorings also have a prioritized list or if the available refactorings are purely context-dependent.

The Git data model and git reset

The “advanced” Git session enlightened me, what git reset really means. In the version control system Subversion (SVN), which I used before Git, svn reset had the semantics of “dismiss all changes and go back to the last commit”. When switching to Git, I learned that the commands git checkout . and git reset --hard have a similar effect, but never thought about the different modes of git reset.

In this session I learned about the data model of Git: Individual commits form a “chain of commits”. A commit can have a label and that commit together with the chain of all its previous commits is then called a branch. A commit can have one or more labels, i.e. branches pointing to the same commit. The “special branch name” HEAD always points to the last commit in the working directory (internally, HEAD is probably not a branch label, but for the sake of explanation it makes sense to consider it one). git reset moves both the label for the current branch and HEAD to a specific commit. If you don’t provide a commit ID, Git uses the last commit id - HEAD. reset has three modes that affect how it treats your working directory and the changes of commits that come after the specified commit. The modes are --soft, --hard and --mixed, with --mixed being the default:

  • reset --soft takes the changes of the intermediate commits and puts them in the index (the staging area). This is useful if you want to “squash” more than one commit into one and change the commit message, without using git rebase --interactive.
  • reset --mixed takes the changes of the intermediate commits and leaves them uncommitted in the workspace. This is useful if you want to commit changes in a different order.
  • reset --hard removes the changes from the intermediate commits and resets the workspace.

Covariance and Contravariance

In a coding kata that worked entirely in the compiler, where the type checks took the place of unit test, I learned about covariance and contravariance: They are the constrains that govern how functions and higher-order-types (also known as “generics” in languages like Typescript and Java) behave when substituting a type with its sub-type or super-type. The kata itself was about applying the “Producer Extends, Consumer super” (PECS) rules in Java. Since then, I’ve read about covariance and contravariance in Typescript and covariance and contravariance coming to PHP in version 7.4.

Other ideas and resources