GitHubじゃ!Pythonじゃ!

GitHubからPython関係の優良リポジトリを探したかったのじゃー、でも英語は出来ないから日本語で読むのじゃー、英語社会世知辛いのじゃー

joealcorn

laboratory – あなたがリファクタリングを手助けするためのPythonライブラリ

投稿日:

あなたがリファクタリングを手助けするためのPythonライブラリ https://laboratory-python.readthedocs…

実験室!

GitHubの科学者に触発された Python 2.7,3.3 +のサポートを利用して、実稼働環境でテストしてクリティカルパスを慎重にリファクタリングするPythonライブラリ。

  1. どうして?
  2. インストール
  3. 入門
  4. コンテキストの追加
  5. ランプアップ
  6. 比較の制御
  7. 不一致を起こす
  8. 結果を公開する
  9. 警告
  10. リンク

どうして?

一部のコードブロックは他のコードブロックより重要です。 実験室では、実稼働環境で実験を行い、結果を検証することで、重要なコードパスをリファクタリングするのに役立ちます。

その価値は、これまでに存在しなかった信頼感を私たちに与える能力にあります。 実験を通して、候補コードが誤動作しているかどうかをすぐに確認すると同時に、正確性をより迅速に収束させるために使用できるフィードバックループを確立します。

あなたがもっと知りたいのならば、私はブログ投稿を書いています: 確かな足取りのリファクタリング このプロジェクトに影響を与えた元のブログ記事は、読んだだけでも価値があります。 科学者

インストール

pypiからインストールすることをお勧めします

$ pip install laboratory

Githubからタグ付きバージョンをインストールすることもできます

$ pip install https://github.com/joealcorn/laboratory/archive/v1.0.tar.gz

または最新の開発版

$ pip install git+https://github.com/joealcorn/laboratory.git

入門

参照: インストールまたはpip install laboratory

ラボでは、既知の良いコードをコントロールブロックとして、新しいコードブランチを候補として実験を行います。 検査室は:

  • 新しいコードと古いコードをランダムな順序で実行する
  • 戻り値を比較する
  • 古いコードと新しいコードに関するタイミング情報を記録する
  • 新しいコードで例外をキャッチします(ただし記録してください)。
  • このすべての情報を公開する

いくつかの認証コードをリファクタリングしているとしましょう。 あなたの既存のコードは動作していますが、維持が困難になっているスパゲッティの壊れやすい山です。 あなたはリファクタリングしたいと思いますが、これは重要なコードなので、これを間違える可能性はありません。そうしないと、ユーザーデータが漏れる危険があります。 元のコードの状態を考慮すると、これはやりにくくなる可能性がありますが、ラボラトリーが助けに来ています。

実験室は、生産を独自の環境(悪いデータや遺産のデータ、重い荷物など)にする要素の豊かさでも、私たちの実装の正しさを検証するのに役立ちます。

古い(制御)コードと新しい(候補)コードを実行するための実験を設定しましょう:

import laboratory

# set up the experiment and define control and candidate functions
experiment = laboratory.Experiment()
experiment.control(authorise_control, args=[user], kwargs={'action': action})
experiment.candidate(authorise_candidate, args=[user], kwargs={'action': action})

# conduct the experiment and return the control value
authorised = experiment.conduct()

Experimentクラスは、コントロール関数と候補関数が同じ引数をとる場合、デコレータとしても使用できることに注意してください。

def authorise_candidate(user, action=None):
    return True

@Experiment.decorator(candidate=authorise_candidate)
def authorise_control(user, action=None):
    return True

実験では、常にコントロールブロックの値が返されます。

コンテキストの追加

出版の際や結果を検証する際に便利な実験の周りには、多くの時間があります。 これを設定するにはいくつかの方法があります。

# The first is experiment-wide context, which will be set on every Observation an experiment makes
experiment = laboratory.Experiment(name='Authorisation experiment', context={'action': action})

# Context can also be set on an Observation-specific basis
experiment.control(control_func, context={'strategy': 1})
experiment.candidate(cand_func, context={'strategy': 2})

コンテキストは、 Experiment and Observationインスタンスのget_contextメソッドを使用して取得できます。

class Experiment(laboratory.Experiment):
    def publish(self, result):
        self.get_context()
        result.control.get_context()
        result.candidates[0].get_context()

ランプアップ

コードブロックを実行する前に、 Experiment.enabled室はExperiment.enabledを呼び出します。 このメソッドをオーバーライドすることで、候補コードがいつ実行されるかを制御できます。

たとえば、わずか10%の呼び出しで実験を有効にする場合は、次のような行を使用できます。

class MyExperiment(laboratory.Experiment):
    def enabled(self):
        return random.random() < 0.1

これは実験をゆっくり実行するのに便利ですが、 enabled方法で実験コンテキストにアクセスできるため、特定のユーザーのみを有効にするなどの面白いこともできます。

class MyExperiment(laboratory.Experiment):
    def enabled(self):
        ctx = self.get_context()
        return ctx['user'] in user_segment

比較の制御

すべてのデータが等しく作成されるわけではありません。 デフォルトでは、ラボは==を使って比較しますが、時にはニーズに合わせてこれを微調整する必要があるかもしれません。 Experimentをサブクラス化し、 compare(control, observation)メソッドを実装すれば十分です。

class MyExperiment(Experiment):
    def compare(self, control, observation):
        return control.value['id'] == observation.value['id']

不一致を起こす

Experimentクラスはraise_on_mismatch引数をraise_on_mismatchます。これは、比較結果がfalseを返したときにラボが例外を発生させたい場合にTrue設定できます。 例えば、これはテストに役立つかもしれません。

結果を公開する

このデータは、何かできることがない限り無用です。 ラボラトリーでは、これを行う方法については何も仮定していません。あなたのニーズに合わせて実装するのはあなたのためだけです。 例えば、タイミングデータをグラファイトに送ることができ、ミスマッチは、後でデバッグするために、赤く塗りつぶしたコレクションに配置することができます。

publishメソッドにはResultインスタンスが渡され、制御データと候補データはそれぞれResult.controlResult.candidates使用できます。

class MyExperiment(laboratory.Experiment):
    def publish(self, result):
        statsd.timing('MyExperiment.control', result.control.duration)
        for o in result.candidates:
            statsd.timing('MyExperiment.%s' % o.name, o.duration)

警告

実験室の仕組みのために、使用しないでください。 つまり、ディスクやデータベースの書き込みやその他の状態の変更などの副作用を伴うコードは、重複した書き込みにつながるため不適切です。 バグのあるデータや、コントロールの実行に影響する候補に終わる可能性があります。

また、古いコードに加えて新しいコードを実行することでパフォーマンスが低下するので注意してください。 実験をゆっくりと進めて、測定基準に注意を払う必要があります。

リンク

メンテナンス

研究室はJoe Alcorn( GithubTwitter )によって積極的に維持されています。







-joealcorn
-, , , , , ,

執筆者: