Xavier Nayrac

Rubyiste accro au TDD, serial blogger, apprenti data scientist, heureux utilisateur de Vim, accordéoniste.
Si vous vous sentez particulièrement généreux, suivez moi sur Twitter.

Ruby - Et si on écrivait un ORM ? - partie 9

| Comments

Niveau : intermédiaire

Encore du refactoring, cette fois ci dans la classe Base. Regardons le code suivant:

1
2
3
4
  class Base
    def self.sql(raw_query)
      Database.connection.execute(raw_query)
    end

Le Database.connection.execute me dérange. Il viole la loi de Demeter.

À bien y réfléchir, je n’ai tout simplement pas envie d’exposer la méthode connection, qu’on trouve aussi un peu plus loin dans la class Base:

1
2
3
4
def self.save(parameters)
  Recorder.new(Database.connection, self.to_s.downcase, parameters).save
  self.new(parameters)
end

La classe Database est actuellement comme ça:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  class Database
    @@connection = false

    def self.connect(database_filename)
      @@connection = SQLite3::Database.open(database_filename)
    end

    def self.connected?
      !!@@connection
    end

    def self.connection
      @@connection
    end
  end

Je supprime purement et simplement la méthode connection:

1
2
3
4
5
6
7
8
9
10
11
  class Database
    @@connection = false

    def self.connect(database_filename)
      @@connection = SQLite3::Database.open(database_filename)
    end

    def self.connected?
      !!@@connection
    end
  end

Maintenant, on rejoue les tests, qui vont nous indiquer ce qui doit être réécrit:

$ rspec sorm_spec.rb 
[...]
     NoMethodError:
       undefined method `connection' for SORM::Database:Class
     # ./sorm.rb:19:in `sql'
[...]
     NoMethodError:
       undefined method `connection' for SORM::Database:Class
     # ./sorm.rb:23:in `save'
[...]
7 examples, 5 failures

On va simplement créer une méthode Database.execute, qui elle, pourra utiliser l’objet connection:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  class Database
    @@connection = false

    def self.connect(database_filename)
      @@connection = SQLite3::Database.open(database_filename)
    end

    def self.connected?
      !!@@connection
    end

    def self.execute(sql)
      @@connection.execute(sql)
    end
  end

  class Base
    def self.sql(raw_query)
      Database.execute(raw_query)
    end
  # ...

À y regarder de près, je ne suis plus certain de trouver un intérêt à Base.sql. Il faudrait la supprimer puisqu’elle peut être remplacée par Database.execute. Mais il faudra attendre car il y a encore des tests qui ne passent plus, à cause de ce code:

1
2
3
4
def self.save(parameters)
  Recorder.new(Database.connection, self.to_s.downcase, parameters).save
  self.new(parameters)
end

On s’en occupera la prochaine fois.

To be continued

À demain.

Articles connexes

Commentaires