« ^ »

今日やった事 - 20240905

所要時間: 約 2分

本当に何もできない。力が入らない。でも良い天気だなぁ。

継承及びオーバーライドはできるだけ避けたい

何かしらのフレームワークを使う時、用意されているモデルを継承しメソッドをオーバーライドする事で拡張する事がしばしばある。ただし使い捨てのコードでないなら、この方法は行なわない方がいい。もはや禁止し、CIが通らないようにしてもいいかもしれない。

なぜそのように考えるのかを書いておく。

例えばフレームワークで以下のようなクラスが定義されているとする。

def save_func(obj):
   pass

class FrameworkClass:
    def save(self):
        save_func(self)

この FrameworkClass を継承し save メソッドをオーバーライドする。

from xxx import save_func, FrameworkClass

class CustomClass(FrameworkClass):
    def save(self)
        save_func(self)
        print("saved object!!")

この実装だと CustomClass のsaveメソッドを呼び出すと、 save_func によって自身を保存し、メッセージを表示する。

もしフレームワークのバージョンアップにより、以下のように FrameworkClass の実装が変わったとする。

def save_func(obj):
   pass

def new_save_func(obj):
   pass

class FrameworkClass:
    def save(self):
        new_save_func(self)

新しい FrameworkClass は、 save_func の変わりに new_save_func を呼び出している。これに気付かずフレームワークをアップグレードしてしまうと、 CustomClass は以前の実装のまま、 save_func を呼び出してしまう。古いコードと新しいコードで違いがある事を、継承先のコードのテストで確認する事もできない。

Pythonの場合、super()を使う事で継承元を取得する事もできるが、これもあまり得策ではない。

from xxx import FrameworkClass

class CustomClass(FrameworkClass):
    def save(self)
        super().save()
        print("saved object!!")

これならフレームワークをアップグレードする前は save_func が使われ、アップグレードした後は new_save_func が使われる。だいぶマシではあるけれど、これも出来れば避けたい。書いていて、なぜこれを避けるべきか忘れてしまった。また良い例を思い出したら書くが、避けたほうが良い事には変わりない。大規模なコードベースで、このような実装の修正を全て把握していく事が難しいといったような趣旨だ。

時刻とタイムゾーン、pytzとzoneinfo、そしてDjangoとDjango REST Frameworkを観察した

これらについて観察した。なかなか入り組んでいたけれど、今度まとめようと思う。