Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Safety Nets: How to check your code? (in Ruby)

Safety Nets: How to check your code? (in Ruby)

Programming gives you a great power...

But as the saying goes, "With great power comes great responsibility!"

As software developers, we cannot afford to blow off everything when shipping. That's why it's important to put in place different strategies to help us to catch errors asap, but also to avoid cruft in the long term. Come and discover those tools & techniques (Tests, Code Review, Static Analysis) and how to put them in place in your code base. Like safety nets, they will allow you to go forward with more confidence.

http://www.meetup.com/Le-Wagon-Brussels-Coding-Station/events/222354764/

Christophe Philemotte

June 23, 2015
Tweet

More Decks by Christophe Philemotte

Other Decks in Programming

Transcript

  1. describe Invoice do let(:item1) { Item.new(20.0, 3) } let(:item2) {

    Item.new(15.0, 2) } let(:empty_invoice) { Invoice.new } let(:invoice) do tmp = Invoice.new tmp.add_item(item1) tmp.add_item(item2) tmp end
  2. it 'returns a zero total when empty' do assert_equal 0,

    empty_invoice.total end it 'returns a correct total' do assert_equal 90.0, invoice.total end
  3. it 'returns a correct total even after updating a previously

    added item' do assert_equal 90.0, invoice.total item2.quantity = 3 assert_equal 105, invoice.total end end
  4. #... def total total = 0 @items.each do |item| total

    += item.price * item.quantity end total end end
  5. class Invoice def initialize @items = [] @total = 0

    end def add_item(item) @items << item end #...
  6. #... def total @total = 0 @items.each do |item| @total

    += item.price * item.quantity end @total end end
  7. class Invoice #... def total @total = 0 @items.each do

    |item| @total += item.price * item.quantity end
  8. if @country_code == 'BE' vat = 0.21 * @total elsif

    ['IT','FR','NL','LU','DE'].include?(@country_code) if valid_vat_number? vat = 0 else vat = 0.21 * @total end else vat = 0 end
  9. class Quote #... def total if @country_code == 'BE' vat

    = 0.21 * @total elsif ['IT','FR','NL','LU','DE'].include?(@country_code) if valid_vat_number? vat = 0 else vat = 0.21 * @total end
  10. $ flay lib Total score (lower is better) = 116

    1) IDENTICAL code found in :if (mass*2 = 116) lib/invoice.rb:21 lib/quote.rb:10
  11. class Invoice #... def total @total = 0 @items.each do

    |item| @total += item.price * item.quantity end
  12. $ ruby -w lib/invoice.rb lib/invoice.rb:41: warning: shadowing outer local variable

    - total lib/invoice.rb:40: warning: assigned but unused variable - total
  13. $ rubocop lib/invoice.rb Inspecting 1 file W Offenses: ------8<------ lib/invoice.rb:40:5:

    W: Useless assignment to variable - total. total = 0 ^^^^^
  14. lib/invoice.rb:41:26: W: Shadowing outer local variable - total. @items.reduce(0) do

    |total, item| ^^^^^ lib/invoice.rb:42:7: W: Useless assignment to variable - total. Use just operator +. total += item.price * item.quantity ^^^^^ 1 file inspected, 10 offenses detected
  15. It is common to take a sort of smug satisfaction

    in reports of colossal failures of automatic systems, but for every failure of automation, the failures of humans are legion. Exhortations to “write better code” plans for more code reviews, pair programming, and so on just don’t cut it, especially in an environment with dozens of programmers under a lot of time pressure. The value in catching even the small subset of errors that are tractable to static analysis every single time is huge. John Carmack
  16. module Vat def self.rate(country_code = '', vat_number = '') if

    country_code == 'BE' return 0.21 elsif %w(IT FR NL LU DE).include?(country_code) if is_valid?(vat_number) return 0 else return 0.21 end
  17. class Invoice # ... def total @total = calculate_subtotal vat

    = Vat::rate(@country_code, @vat_number) * @total @total += vat end # ... end
  18. class Country # ... def belgium? @code == 'BE' end

    def europe? %w(IT FR NL LU DE).include? @code end end
  19. module Vat def self.rate(country, vat_number = '') if country.belgium? return

    0.21 elsif country.europe? if is_valid?(vat_number) return 0 else return 0.21 end # ... end
  20. 34.7: flog total 2.9: flog/method average 7.0: Invoice#calculate_subtotal lib/invoice.rb:28 6.7:

    Invoice#initialize lib/invoice.rb:5 5.7: Invoice#total lib/invoice.rb:16 4.8: Vat::rate lib/vat.rb:2