FizzBuzzとの3か月(13)

お世話になっております。

今日は、FizzBuzzの定義を設定ファイルに取り出してみました。
通常の業務においても、先輩方より「設定ファイルを変更するだけで対応できるようにしてくれ」と指示されますが、なかなかそこまでは実装できたことがありません。
いくつか原因を上げてみます。

  • 何を設定値とすればいいか、基準が分からない。設定ファイルに持たせても、空振りに終わってしまう。
  • 設定値が異常でないか、検出する仕組みを作りこむ時間がない。設定を変更したら、原因不明のシステム停止になってしまう。
  • 社内パッケージが既に設定ファイルをもっており、これ以上増やしたくない。
  • 「何でもできる」設定ファイルを変更するよりも、プログラムを直した方が早い。

設定ファイルを利用し、プログラムができなくてもシステムの動作を変更できる。というのは理想ですが、そこまで柔軟なシステムを組むには、かなりの工数が見込まれます。また、その設定ファイルを直すためには、プログラムを書く以上の知識が要求され、しかもその知識はある特定のプロジェクトでしか活かせないというのが現実ではないでしょうか。
この辺りについては、今後も試行錯誤が必要だと考えています。

以下、コードです。

# -*- coding: utf-8 -*-

import unittest
import configparser


class FizzBuzzFactoryTestCase(unittest.TestCase):
  def testgetAnswer(self):
    """1から100までの数をプリントするプログラムを書け。
    ただし3の倍数のときは数の代わりに「Fizz」と、7の倍数のときは「Buzz」とプリントし、
    3と7両方の倍数の場合には「FizzBuzz」とプリントすること。
    """
    for i in range(100):
      param = i + 1
      answer = fizzbuzz(param)
      if 'Fizz' == answer:
        self.assertEqual(0, param % 3)
      elif 'Buzz' == answer:
        self.assertEqual(0, param % 7)
      elif 'FizzBuzz' == answer:
        self.assertEqual(0, param % 3)
        self.assertEqual(0, param % 7)
      else:
        self.assertEqual(False, param % 3 == 0)
        self.assertEqual(False, param % 7 == 0)


class FizzBuzz(object):
  def __init__(self, text, *args):
    self._text = text
    self._measures = [x for x in args]

  def getAnswer(self, param):
    for measure in self._measures:
      if not 0 == param % measure:
        return None
    return self._text

  def __str__(self):
    return str.format('FizzBuzz({0}, {1})', self._text, self._measures);

config = []
config_parser = configparser.RawConfigParser()
config_parser.readfp(open('fizzbuzz.ini', mode='r', encoding='sjis'))
for section in config_parser.sections():
  for option in config_parser.options(section):
    text = config_parser.get(section, 'text')
    measures = config_parser.get(section, 'measures')
    num_measures = [int(x) for x in measures.split(',')]
    config.append(FizzBuzz(text, *num_measures))


def fizzbuzz(param):
  answer = None
  for obj in config:
    answer = obj.getAnswer(param)
    if answer:
      return answer
  return str(param)

if __name__ == '__main__':
  unittest.main()

設定ファイルはこちらです。

[FizzBuzz]
text=FizzBuzz
measures=3,7

[Fizz]
text=Fizz
measures=3

[Buzz]
text=Buzz
measures=7

シンタックス・ハイライトがconfigに対応しているのに驚きました。

以上