At a client, last week I’ve organized an internal training, in the form of a discussion about this article: Testing is hard - just do it
Our thoughts
When a bug is found, prove it exists with a test
This immediately reduces defect rate: the same regression cannot be introduced again
fix a bug a second time
If fixing a bug (having defects in your code) was ‘waste’, as defined by lean methodologies, it also is wast fixing it for the following times
testing requires discipline
Agree. See quote by Larry Wall (this same article)
[Three requirements for a good test suite]:
- The tests need to be easier to write
- The test suite must run, and pass, before any code is allowed out the door
- Support from the project’s leadership
Agree.
Programming is like drawing water from a well
Good analogy
I’m going to assume you are smarter than me […]
This is related to ‘doing clever things’: when I write ‘clever code’, that has neither comments, nor it is massaged to be Clean Code, it will cost me many times more to modify / understand in the future vs massage it a little bit.
For me, an example of clever code are certain bitwise operations. Even though these operations are publicly available on websites and books, you must know about them before understanding the code.
Another example of clever code is taking assumptions, even if they are valid. Example: always return the second element because the first one is the header
private String select(List<String> elements){
return elements.get(2);
}
vs
private String selectFirstValidLine(List<String> elements){
List<String> validElements = skipHeader(elements);
return validElements.get(1);
}
Open questions / other ideas
- There are tests that are more important than others. Is there a tool to assign them weights and inform about which preponderation of the codebase is broken? The same (i.e., more importance) can happen for production code.
- Is SCRUM apt for junior developers? In the sense of the increased autonomy, more decisions, more required technical skills / values, etc
- We discussed what differentiates a project with a shorter deadline from one with a longer deadline. The consensus was: you should do tests for any kind of project, the shorter deadline project won’t allow as much time for refactoring
- Tests iff (i.e., if and only if) working code
- Tests do not guarantee lack of defects
- Bijectiveness between tests and features (production code)
I have seen this video: [Nothing is something][video] by [Sandi Metz][sandimetz], as I saw it recommended [here][recommendation]
In the video, she talks programming in this fashion: (it is a stack, not an unordered list)
- Abstraction seeking
- Message centric
- Condition Averse
- Smalltalk Infected
Not here to change the language but change you
This is a pattern I’ve also heard from [Alvaro Videla][old_sound], where he said that other, more powerful languages can change your mind and help you bring some of those concepts to your own language. He was talking about Haskell, she, about Smalltalk.
She shows how to smell the null object pattern
(that she independently discovered herself too - can be improved studying the classics), also called active nothing
. Decorates the Animal
with a wrapper, to call it GuaranteedAnimal
Later on, shows how to code an example on a ‘tail’, extending behaviour with inheritance and how to get rid of it: prefer composition versus inheritance. The importance of roles.
Inheritance is for specialization, not for sharing code
Steps to convert inheritance into composition:
- Isolate the difference
- Name the concept
- Define the role
- Inject the players
This is a trick I discovered here: when you don’t know what name put here, create a spreadsheet and ask yourself what name the row should have. There is an example [at this minute][video-showing-the-spreadsheet]
At a client, today I’ve done an internal training on angular js: we’ve prepared some slides and a live demo.
The repository with all the information can be found here.
Apparently, the training has been a success, given that most of the talent in the team is backend focused (as opposed to full-stack) and changing from java to javascript is not straight-forward.
Note: this post has been created a posteriori, dated with the correct training timestamp.
In the prologue of the book, while thanking everyone that has made the book possible:
[…], none of the people mentioned here would be responsible for any inaccuracy that might exist in the book, as this responsibility is exclusively mine
Mihaly Csikszentmihalyi (translated), prologue of “Flow”
(More posts on this same book, here)
This connects with what Dan North said in the Craft Conf about this idea of the “I’m the only one in the company producing good quality work, the rest are not doing the same”. Of course, he was quoting greedy, selfish people who think this instead of attributing the success to the whole team.
Regarding the whole team, if I recall correctly, it was Sven Peters who explained that “[…] either the team wins or looses. There are no individual wins […]”
In this sense, Csikszentmihalyi assumes all responsibility when quoting and reflecting on other’s works. It was his idea to develop on top of others, so any imperfection is his.
This is similar as when approving a pull request: you make sure that the code works and you stand by it. It is no longer the original owner’s cause, but yours too, as you have signed this request. On the pull request, though, the code ownership is already distributed among the whole team, but approvals ensures the presence of the guardian of the source
At the Craft Conf 2015 I saw someone with the book Apprenticeship Patterns by Dave Hoover and Adewale Oshineye and asked them about the book. After praising the contents, they asked me how to approach the book.
I recalled reading it non-sequentially, and explained it to them:
- Read the introduction, preface, etc first
- When you get to the patterns, pick one at random
10
: Read it and navigate through the see also
.
- If there are unread chapters from the
see also
, goto 10
- Find the remaining unread chapters and read them, try to apply the same algorithm
- Read the appendices and finishing words
Reading a connected chapter after the first one made me connect the dots and understand it much better than reading them sequentially.
PS: This post was extracted from this one: here
When I went to the Jason Gorman’s TDD workshop (experience report here), he said something interesting regarding refactor and TDD:
In job offers / advertisements, TDD is much more in demand than refactor. But the latter is included in the former as an integral part.
Jason Gorman
I agree with the second thought: you cannot properly do TDD without refactoring, as it is an integral part; also the third phase.
For me, sometimes refactoring is the difference between code and “Clean Code” (as defined in the book by the same title). If I cannot find the (algorithmic) pattern for the software I’m writing, I try to introduce scaffolds to keep investigating until I can find a viable, general solution (if the problem requires it.)
Even after doing the refactor replace algorithm
, the code might not have the responsibilities in the right place, the methods might be long, value objects not extracted yet, etc. This is where further refactor is needed to introduce all those qualities in the piece of software.
I believe that we programmers have done a bad job of communicating with the rest of the organization what refactoring is about. It has nothing to do with beauty, style or design (in the visual sense) but is related to maintainability, coupling, defects and quality. Money, in the long run, as its objective is to make it cheaper to change in the future, a better investment and ROI. This is the common language that the rest of the company understands.