はじめに
実装中、ループのたびに同じデータをデータベースから取得している処理がありました。このデータ取得の処理をキャッシュ化したかった。
クラス変数によるキャッシュ化
まず、クラス変数を使用してキャッシュを実装しました。クラス変数はクラスとそのサブクラスのすべてのインスタンス間で共有されるため、アプリケーション全体で一貫したデータを保持するのに適しています。
以下のような形
class DataCache
@@cache = {}
def self.store(key, value)
@@cache[key] = value
end
def self.retrieve(key)
@@cache[key]
end
end
ただし、この実装ではサブクラスへの影響も考慮する必要があります。
DataCacheクラスのみで使用できるようにしたい。
クラスインスタンス変数によるキャッシュ化
次に、クラスインスタンス変数を使用したキャッシュ化を試みました。クラスインスタンス変数はクラス自体に固有で、クラスのすべてのインスタンスで共有されますが、サブクラスで共有されることはありません。
class DataCache
@cache = {}
def self.store(key, value)
@cache[key] = value
end
def self.retrieve(key)
@cache[key]
end
end
この方法では、クラスインスタンス変数がクラスの各インスタンスで共有されないため、複数のインスタンスが作成されると再びデータベースからデータを取得することになります。
最終的な実装
最終的には、クラスインスタンス変数をクラスのシングルトンメソッド(クラスメソッド)としてアクセス可能にする方法を採用しました。これにより、クラスレベルでキャッシュが保持され、DataCacheクラスのすべてのインスタンスで共有されます。
class DataCache
@cache = {}
class << self
attr_accessor :cache
end
def self.store(key, value)
@cache[key] = value
end
def self.retrieve(key)
@cache[key]
end
end
まとめ
この実装により、DataCacheクラスのインスタンス間で共有されるキャッシュが作成され、パフォーマンスが大幅に向上しました。また、クラスインスタンス変数はサブクラスに影響を与えないため、DataCacheクラス限定での使用が可能です。