570 likes | 1.94k Views
Presented at JavaZone (9th September 2015) <br>Video available at https://vimeo.com/138863968 <br><br>The three-act play, the given–when–then BDD triptych, the three steps of the Feynman problem-solving algorithm... a surprising number of things appear to come in threes. This talk walks through — and has some fun with — a number of triples that affect and are found in software development.
E N D
three @ @KevlinHenney KevlinHenney
Veni Vidi Vici
Sex & Drugs & Rock'n'Roll
There's nothing long-winded about Liberté · Égalité · Fraternité Maurice Saatchi
Rien n'est plus dangereux qu'une idée, quand on n'a qu'une idée. Émile-Auguste Chartier
Nothing is more dangerous than an idea, when you have only one idea. Émile-Auguste Chartier
Nothing is more dangerous than an IDE, when you have only one IDE.
public static String fizzbuzz(int n) { String result = ""; if (n % 3 == 0) { result += "Fizz"; } if (n % 5 == 0) { result += "Buzz"; } if (result.isEmpty()) { result += n; } return result; }
FizzBuzz was invented to avoid the awkwardness of realising that nobody in the room can binary search an array. https://twitter.com/richardadalton/status/591534529086693376
fizzbuzz = ( lambda n: 'Fizz' * (n % 3 == 0) + 'Buzz' * (n % 5 == 0) + str(n) * (n % 3 != 0 and n % 5 != 0))
fizzes = cycle ["", "", "Fizz"] buzzes = cycle ["", "", "", "", "Buzz"] words = zipWith (++) fizzes buzzes numbers = map show [1..] fizzbuzz = zipWith max words numbers
Nothing is more dangerous than an idea, when you have only one idea. Émile-Auguste Chartier
When a design decision can reasonably go one of two ways, an architect needs to take a step back. Instead of trying to decide between options A and B, the question becomes "How do I design so that the choice between A and B is less significant?" The most interesting thing is not actually the choice between A and B, but the fact that there is a choice between A and B. Kevlin Henney "Use Uncertainty As a Driver"
To have one choice is no choice; to have two choices is a dilemma; and to have three choices offers new possibilities. Virginia Satir
The Rule of Three If you can’t think of three things that might go wrong with your plans, then there’s something wrong with your thinking. Jerry Weinberg
If you want to reduce your test mass, the number one thing you should do is look at the tests that have never failed in a year and consider throwing them away. They are producing no information for you — or at least very little information. James O Coplien "Why Most Unit Testing Is Waste"
1. Your tests are not failing because the code they are testing has not changed. 2. Your tests are not failing because they are not running. 3. Your tests are not failing because, yes, you are that good.
The Rule of Three Here's a guideline Don Roberts gave me...
The first time you do something, you just do it. The second time you do something similar, you wince at the duplication, but you do the duplicate thing anyway. The third time you do something similar, you refactor.
Identity Identity State State Behaviour Behaviour
Encapsulation Encapsulation Inheritance Inheritance Polymorphism Polymorphism
Encapsulation Encapsulation Polymorphism Polymorphism Inheritance Inheritance
Encapsulation Encapsulation Polymorphism Polymorphism Inheritance Inheritance
Ignorance Ignorance Apathy Apathy Selfishness Selfishness
S-Programs P-Programs E-Programs Meir M Lehman "Programs, Life Cycles, and Laws of Software Evolution"
S-Programs Programs whose function is formally defined by and derivable from a specification. Meir M Lehman "Programs, Life Cycles, and Laws of Software Evolution"
P-Programs Despite the fact that the problem to be solved can be precisely defined, the acceptability of a solution is determined by the environment in which it is embedded. Meir M Lehman "Programs, Life Cycles, and Laws of Software Evolution"
E-Programs Programs that mechanize a human or societal activity. The program has become a part of the world it models, it is embedded in it. Meir M Lehman "Programs, Life Cycles, and Laws of Software Evolution"
We know that every pattern is an instruction of the general form: context conflicting forces configuration So we say that a pattern is good, whenever we can show that it meets the following two empirical conditions: 1. The problem is real. This means that we can express the problem as a conflict among forces which really do occur within the stated context, and cannot normally be resolved within that context. This is an empirical question. 2. The configuration solves the problem. This means that when the stated arrangement of parts is present in the stated context, the conflict can be resolved, without any side effects. This is an empirical question.
context context conflicting forces conflicting forces configuration configuration consequences
Write down the problem. Think real hard. Write down the solution. The Feynman Problem-Solving Algorithm
Write down the problem. Think real hard. Write down the solution. Check it.
Do Carry out plan Plan Establish hypothesis, goal or work tasks Study Review what has been done against plan (a.k.a. Check) Act Revise approach or artefacts based on study Deming's PDSA Cycle
Test early. Test often. Test automatically. Andrew Hunt and David Thomas The Pragmatic Programmer
So who should you be writing the tests for? For the person trying to understand your code. Good tests act as documentation for the code they are testing. They describe how the code works. For each usage scenario, the test(s): Describe the context, starting point, or preconditions that must be satisfied Illustrate how the software is invoked Describe the expected results or postconditions to be verified Different usage scenarios will have slightly different versions of each of these. Gerard Meszaros "Write Tests for People"
So who should you be writing the tests for? For the person trying to understand your code. Good tests act as documentation for the code they are testing. They describe how the code works. For each usage scenario, the test(s): Describe the context, starting point, or preconditions that must be satisfied Illustrate how the software is invoked Describe the expected results or postconditions to be verified Assert Arrange Act Different usage scenarios will have slightly different versions of each of these. Gerard Meszaros "Write Tests for People"
So who should you be writing the tests for? For the person trying to understand your code. Good tests act as documentation for the code they are testing. They describe how the code works. For each usage scenario, the test(s): Describe the context, starting point, or preconditions that must be satisfied Illustrate how the software is invoked Describe the expected results or postconditions to be verified Then Given When Different usage scenarios will have slightly different versions of each of these. Gerard Meszaros "Write Tests for People"
assert fizzbuzz(1) == 1 assert fizzbuzz(2) == 2 assert fizzbuzz(3) == 'Fizz' assert fizzbuzz(4) == 4 assert fizzbuzz(5) == 'Buzz' assert fizzbuzz(6) == 'Fizz' assert fizzbuzz(7) == 7 assert fizzbuzz(8) == 8 assert fizzbuzz(9) == 'Fizz' assert fizzbuzz(10) == 'Buzz' assert fizzbuzz(11) == 11 assert fizzbuzz(12) == 'Fizz' assert fizzbuzz(13) == 13 assert fizzbuzz(14) == 14 assert fizzbuzz(15) == 'FizzBuzz' ... assert fizzbuzz(98) == 98 assert fizzbuzz(99) == 'Fizz' assert fizzbuzz(100) == 'Buzz' def fizzbuzz(n): if n == 1: return 1 if n == 2: return 2 if n == 3: return 'Fizz' if n == 4: return 4 if n == 5: return 'Buzz' if n == 6: return 'Fizz' if n == 7: return 7 if n == 8: return 8 if n == 9: return 'Fizz' if n == 10: return 'Buzz' if n == 11: return 11 if n == 12: return 'Fizz' if n == 13: return 13 if n == 14: return 14 if n == 15: return 'FizzBuzz' ... if n == 98: return 98 if n == 99: return 'Fizz' if n == 100: return 'Buzz'
Green Write enough code to pass the test Red Write a failing test for a new feature Refactor Refine code and tests Test-First Cycle