TDD: Clean Code That Works
Test Drive
Kaprekar Number
Kaprekar number is a non-negative integer, the representation of whose square can be split into two parts that add up to the original number.
Write a function that determines if a given number is a Kaprekar number or not.
Questions?
Predicted Questions
- Can you explain what is Kaprekar number again, in an easily understandable language please?
- Can you give me an example of its input?
- What kind of output do you want me to print? Is it "true" or "false" value? Or is it "kaprekar" or "not kaprekar" value?
With No Tests
def kaprekar?(k)
result = false
power = k ** 2
power_str = power.to_s
for i in 0..(power_str.size - 1)
num1 = power_str[0,i].to_i
num2 = power_str[i,power_str.size-1].to_i
if k == num1 + num2
result = true
break
end
end
result
end
puts "Is kaprekar 9: #{kaprekar?(9)}"
puts "Is kaprekar 45: #{kaprekar?(45)}"
puts "Is kaprekar 7777: #{kaprekar?(7777)}"
puts "Is kaprekar -9: #{kaprekar?(-9)}"
puts "Is kaprekar 33: #{kaprekar?(33)}"
Self-Testing Code
What is Self-Testing Code?
- Code that have built-in tests
- which serve as a binding contract
- and can be run arbitrarily
Install RSpec
source 'https://rubygems.org'
gem 'rspec'
Gemfile
bundle install
Execute command:
Change Directory Structure
.
├── Gemfile
├── Gemfile.lock
├── lib
│ └── kaprekar.rb
└── spec
Setup your directory structure to look like this:
Create Unit Tests
require "kaprekar"
describe 'Kaprekar' do
it 'should return true when the input is 9 because 9 * 9 is 81 and 8 + 1 is 9' do
expect(kaprekar?(9)).to eq(true)
end
it 'should return false when the input is 8 because 8 * 8 is 64 and 6 + 4 is not 8' do
expect(kaprekar?(8)).to eq(false)
end
it 'should return false when the input is a negative integer' do
expect(kaprekar?(-9)).to eq(false)
end
end
spec/kaprekar_spec.rb
rspec -fd
Run:
The Parallels (1)
Remember the points in our questions earlier?
- easily understandable
- example input
- expected output
The Parallels (2)
require "kaprekar"
describe 'Kaprekar' do
it 'should return true when the input is 9 because 9 * 9 is 81 and 8 + 1 is 9' do
expect(kaprekar?(9)).to eq(true)
end
it 'should return false when the input is 8 because 8 * 8 is 64 and 6 + 4 is not 8' do
expect(kaprekar?(8)).to eq(false)
end
it 'should return false when the input is a negative integer' do
expect(kaprekar?(-9)).to eq(false)
end
end
easily understandable description
example input
expected output
Test Driven Development
The goal of test driven development is to produce clean code that works
- Ron Jeffries, founders of Extreme Programming
Steps
- Write a test
- Run the test and see it fails
- Write just enough code to make it pass
- Run the test and see it passes
- Refactor
- Run the test to ensure it still passes
FIRST Principle
- Fast
- Independent
- Repeatable
- Self-checking
- Timely
But How? And Why?
Throughout the day, we are going to teach you how to write clean code that works while discovering why it matters.
Preparation
Non-Negotiable Ettiquette
- Indentation and spacing between code constructs (classes/methods/specs) must be consistent
- Use only spaces (no tabs) for indentation
- Follow accepted naming conventions for Ruby
- Follow accepted naming file and directory structure for Ruby
- Use namespaces
- No comments/unused code must ever be checked in
- Use .gitignore
-
Ensure there is a README.md that includes
- Problem Description
- Dev environment setup
- Build instructions
- Run instructions
- TDD (this should show in clear pattern in the commit log)
rm -rf
Failure to comply with non-negotiable etiquette will result in rm -rf to your code.
Group Responsibility
- Ensure conventions
- indentation and spaces
- naming
- file and directory structure
- Write a script that automate project structure to follow the conventions
Problem Sets
Problem Set #1
As a fan of geometry,
I want to model a line based on points consisting of (x, y) co-ordinates using the cartesian system,
So that I can calculate its length.
Problem Set #2
As a fan of geometry,
I want to compare two lines for equality based on the end points,
So that I know when two lines are the equal.
Problem Set #3
As a fan of geometry,
I want to model a rectangle with sides of lengths a and b,
So that I can calculate its perimeter.
Lessons Learned
Concepts
- Express intent
- Simple English modeling
- Baby steps
- YAGNI
- DRY
- KISS
- SRP
- Job of class
- Tell, don't ask
- Law of Demeter
Clean code is not written by following a set of rules. You don’t become a software craftsman by learning a list of heuristics. Professionalism and craftsmanship come from values that drive disciplines.
- Robert C. Martin, author of Clean Code
TDD: Clean Code That Works
By qblfrb
TDD: Clean Code That Works
- 419