Section 13.1.5 : Ruby — Classes et TDD avec Rake
🎯 Objectif pédagogique
Comprendre la programmation orientée objet en Ruby via les classes, et adopter le TDD (Test-Driven Development) avec Rake pour écrire du code fiable dès le départ.
Les classes : modéliser le monde réel
La programmation orientée objet (OOP) modélise votre programme comme un ensemble d'objets qui interagissent. Une classe est le plan de construction, un objet est une instance concrète.
class Utilisateur
attr_accessor :nom, :email
attr_reader :id
def initialize(nom, email)
@id = rand(1000..9999)
@nom = nom
@email = email
@date_inscription = Time.now
end
def presentation
"#{@nom} (#{@email}) - inscrit le #{@date_inscription.strftime('%d/%m/%Y')}"
end
def email_valide?
@email.include?('@') && @email.include?('.')
end
def to_s
presentation
end
end
alice = Utilisateur.new('Alice Martin', 'alice@example.com')
puts alice.nom # Alice Martin
puts alice.email_valide? # true
Variables d'instance vs de classe
class Compteur
@@total = 0 # Variable de classe (partagée)
def initialize(nom)
@nom = nom # Variable d instance (unique)
@@total += 1
end
def self.total
@@total
end
end
Compteur.new('A')
Compteur.new('B')
Compteur.total # 2
Encapsulation : public, private, protected
class CompteBancaire
def initialize(titulaire, solde)
@titulaire = titulaire
@solde = solde
end
def deposer(montant)
raise ArgumentError, 'Montant invalide' unless montant > 0
@solde += montant
historiser("Dépôt de #{montant} EUR")
end
def retirer(montant)
raise ArgumentError, 'Montant invalide' unless montant > 0
raise 'Solde insuffisant' unless solde_suffisant?(montant)
@solde -= montant
end
def afficher_solde
"Solde de #{@titulaire}: #{@solde} EUR"
end
private
def solde_suffisant?(montant)
@solde >= montant
end
def historiser(operation)
puts "[#{Time.now}] #{operation}"
end
end
TDD : Test-Driven Development
Le TDD suit un cycle en trois étapes : Red (test qui échoue), Green (code minimal), Refactor (améliorer).
Minitest en pratique
# test/calculatrice_test.rb
require 'minitest/autorun'
require_relative '../lib/calculatrice'
class CalculatriceTest < Minitest::Test
def setup
@calc = Calculatrice.new
end
def test_addition
assert_equal 5, @calc.additionner(2, 3)
end
def test_division_par_zero
assert_raises(ZeroDivisionError) do
@calc.diviser(10, 0)
end
end
end
# lib/calculatrice.rb
class Calculatrice
def additionner(a, b)
a + b
end
def diviser(a, b)
raise ZeroDivisionError if b.zero?
a / b
end
end
Rake : automatiser les tâches
# Rakefile
require 'rake/testtask'
Rake::TestTask.new do |t|
t.pattern = 'test/**/*_test.rb'
t.verbose = true
end
task default: :test
rake # Lance tous les tests
rake test # Idem, explicitement
Exercice : classe Restaurant
class Restaurant
attr_reader :nom, :ville
def initialize(nom, ville, cuisine)
@nom = nom
@ville = ville
@cuisine = cuisine
@notes = []
end
def noter(note)
raise ArgumentError unless (1..5).include?(note)
@notes << note
end
def note_moyenne
return 0 if @notes.empty?
(@notes.sum.to_f / @notes.length).round(1)
end
def populaire?
note_moyenne >= 4.0 && @notes.length >= 5
end
def to_s
"#{@nom} (#{@ville}) - #{@cuisine} - #{note_moyenne}/5"
end
end
Que signifie le @ devant une variable comme @nom ?
Dans le cycle TDD, quel est l'ordre correct ?
Learn AI, from prompts to agents