Archives of learned topics

Dependency Injection

はじめに


Dependency Injectionについて自分なりにまとめてみる。 (Dependency Injection コンテントにつていは記述していません。) 修正箇所があれば、Updateをしていく。

そもそも


Dependency Injection(DI)をWikiで調べてみると…

コンポーネント間の依存関係をプログラムのソースコードから排除し、外部の設定ファイルなどで注入できるようにするソフトウェアパターンである。英語の頭文字からDIと略される。 依存性の注入 - Wikipedia

簡単に言うと、下記の様にクラス内でインスタンス発行(定数など)をせずに、引数として渡しましょうと言っているだけ。 なのに名前が仰々しすぎる…

非DIコード

import random

possible_moves = ['roll', 'hold']
other = {1: 0, 0: 1}
goal = 50


def clueless(state):
    "A strategy that ignores the state and chooses at random from possible moves."
    return random.choice(possible_moves)


def hold(state):
    """Apply the hold action to a state to yield a new state:
    Reap the 'pending' points and it becomes the other player's turn."""
    (p, me, you, pending) = state
    return (other[p], you, me + pending, 0)


def roll(state, d):
    """Apply the roll action to a state (and a die roll d) to yield a new state:
    If d is 1, get 1 point (losing any accumulated 'pending' points),
    and it is the other player's turn. If d > 1, add d to 'pending' points."""
    (p, me, you, pending) = state
    if d == 1:
        return (other[p], you, me + 1, 0)  # pig out; other player's turn
    else:
        return (p, me, you, pending + d)  # accumulate die roll in pending


def play_pig(A=clueless, B=clueless):
    """Play a game of pig between two players, represented by their strategies.
    Each time through the main loop we ask the current player for one decision,
    which must be 'hold' or 'roll', and we update the state accordingly.
    When one player's score exceeds the goal, return that player."""
    # your code here
    strategies = [A, B]
    state = (0, 0, 0, 0)

    while True:
        (p, me, you, _) = state
        if me >= goal:
            return strategies[p]
        elif you >= goal:
            return strategies[other[p]]
        elif strategies[p](state) == 'roll':
            state = roll(state, random.randint(1, 6)) #randomが毎回変わるのでテストができない・・・
        else:
            state = hold(state)

def always_roll(state):
    return 'roll'


def always_hold(state):
    return 'hold'

DIにする。 変更部分のみを記述。

def dierolls():
    "Generate die rolls."
    while True:
        yield random.randint(1, 6)

def play_pig(A=clueless, B=clueless, die=dierolls()): # generaterは、dierolls()の様に括弧付きでよい。
    """Play a game of pig between two players, represented by their strategies.
    Each time through the main loop we ask the current player for one decision,
    which must be 'hold' or 'roll', and we update the state accordingly.
    When one player's score exceeds the goal, return that player."""
    # your code here
    strategies = [A, B]
    state = (0, 0, 0, 0)

    while True:
        (p, me, you, _) = state
        if me >= goal:
            return strategies[p]
        elif you >= goal:
            return strategies[other[p]]
        elif strategies[p](state) == 'roll':
            state = roll(state, next(die))
        else:
            state = hold(state)