FizzBuzz Framework

FizzBuzzのフレームワーク

本気でFizzBuzzを作ったら、パイプライン処理のライブラリが出来た。

このフレームワークの構造

このフレームワークは、1個の入力に対して0個以上の出力を生成する Operator というクラスを中心に構築されています。

この Operator の派生として定義された 数列を生成するクラス値を置換するクラス結果をコンソールに表示するためのクラス を組み合わせることでFizzBuzzを実現しています。

設計の考え方

FizzBuzzの処理を以下の3つの処理に分けて考えることにします。

  1. 数列の生成

  2. 値の処理

  3. 結果の出力

ここで、この3つをそれぞれ GeneratorFilterPrinter と呼ぶことにします。

もっとも基本的な形である Filter は、1個の入力に対して0個以上の出力を生成する処理であると定義出来ます。

単純な実装では、 Generator は入力を取らずに0個以上の出力を生成する処理として、 Printer は1個の入力に対して出力を持たない処理として定義することが出来ます。

しかしここで、 Generator は入力を無視する処理であると定義すると、3つの処理は全て Filter と同じシグネチャにすることが出来るようになります。 この共通のシグネチャを持った物を Operator と呼び、このクラスから派生したクラスを組み合わせることでFizzBuzzの処理を実現しています。

使い方の例

FizzBuzz

単純に作るのであれば、 ModReplaceFilter を用いれば実現出来ます。

execute(
    RangeGenerator(1, 30),
    ModReplaceFilter(15, "fizzbuzz"),
    ModReplaceFilter(3, "fizz"),
    ModReplaceFilter(5, "buzz"),
    ConsolePrinter(),
)

FizzBuzzの処理をフィルタとして定義したい場合は、 ModReplaceFilterOperatorChain で連結する関数を作成してください。

def FizzBuzzFilter():
    return OperatorChain(
        ModReplaceFilter(15, "fizzbuzz"),
        ModReplaceFilter(3, "fizz"),
        ModReplaceFilter(5, "buzz"),
    )

ここで作成したフィルタは、組み込みのフィルタと同じように使用することが出来ます。

execute(
    RangeGenerator(1, 30),
    FizzBuzzFilter(),
    ConsolePrinter(),
)

階乗の計算

階乗の計算は組み込みのフィルタで実現出来ないため、 Operator を継承して新たにフィルタを作成します。

class FactorialFilter(Operator):
    def __init__(self):
        self.last_value = 1

    def execute(self, value):
        self.last_value = value * self.last_value

        return [self.last_value]  # 値を1つしか返さない場合でもリスト形式を取ることに注意してください。

使い方は通常のフィルタと同じです。

execute(
    RangeGenerator(1, 30),
    FactorialFilter(),
    ConsolePrinter(),
)