データの一元管理が必要性であることは、簡単に理解できます。
しかし、この原則はデータだけでなく、コード内のロジックにも適用されます。
本記事では、ロジックに対する信頼できる唯一の情報源を持つことの重要性と、その実現方法について解説します。
サンプルコードを交えながら、具体的な実装例を見ていきましょう。
複数の情報源によるバグの発生リスク
以下のコードは、ユーザーの情報を管理するためのクラスの例です。
class UserManager: def __init__(self): self.users = [] def add_user(self, name, email): user = {"name": name, "email": email} self.users.append(user) def save_users(self, file_path): with open(file_path, "w") as file: for user in self.users: file.write(f"{user['name']},{user['email']}\n") class UserLoader: def load_users(self, file_path): users = [] with open(file_path, "r") as file: for line in file: name, email = line.strip().split(",") user = {"name": name, "email": email} users.append(user) return users
このコードでは、UserManagerクラスがユーザーの情報を管理し、ファイルに保存する役割を持っています。
一方、UserLoaderクラスは、ファイルからユーザー情報を読み込む役割を持っています。
両方のクラスが、ユーザー情報をファイルに保存・読み込みするための形式について、独自のロジックを持っています。
具体的には、以下の形式が使用されています。
- ユーザー情報を「名前,メールアドレス」の形式で1行ずつファイルに保存する。
- ファイルからユーザー情報を読み込む際は、カンマ区切りで分割し、名前とメールアドレスを取得する。
しかし、この形式について2つの情報源(UserManagerとUserLoader)が存在しています。
そのため、片方のクラスでロジックを変更し、もう一方のクラスでは変更し忘れることが有り得ます。
そのような場合、バグが発生することになります。
例えば、UserManagerクラスで、ユーザー情報の保存形式をカンマ区切りからタブ区切りに変更したとします。
この場合、UserLoaderクラスでもそれに合わせた変更が必要です。
これを変更し忘れると、ユーザー情報の読み込みが正しく行われなくなります。
解決策: 信頼できる唯一の情報源を持つ
上記の問題を解決するために、ユーザー情報の保存・読み込みの形式について、信頼できる唯一の情報源を持つことが重要です。
以下のコードは、UserFormatterクラスを導入することで、この問題を解決する方法を示しています。
class UserFormatter: DELIMITER = "," @staticmethod def serialize(user): return f"{user['name']}{UserFormatter.DELIMITER}{user['email']}" @staticmethod def deserialize(user_string): name, email = user_string.split(UserFormatter.DELIMITER) return {"name": name, "email": email} class UserManager: def __init__(self): self.users = [] def add_user(self, name, email): user = {"name": name, "email": email} self.users.append(user) def save_users(self, file_path): with open(file_path, "w") as file: for user in self.users: user_string = UserFormatter.serialize(user) file.write(user_string + "\n") class UserLoader: def load_users(self, file_path): users = [] with open(file_path, "r") as file: for line in file: user = UserFormatter.deserialize(line.strip()) users.append(user) return users
UserFormatterクラスは、ユーザー情報のシリアライズとデシリアライズを行うための静的メソッドを提供します。
serializeメソッドは、ユーザー情報を文字列に変換し、deserializeメソッドは、文字列からユーザー情報を復元します。
また、UserFormatterクラスには、区切り文字を表す定数DELIMITERが定義されています。
これにより、区切り文字についても信頼できる唯一の情報源が提供されます。
UserManagerクラスとUserLoaderクラスは、ともにUserFormatterクラスを使用してユーザー情報のシリアライズとデシリアライズを行うようになりました。
これにより、ユーザー情報の保存・読み込みの形式について、信頼できる唯一の情報源が確保されます。
今後、ユーザー情報の保存・読み込みの形式を変更する必要がある場合は、UserFormatterクラスのみを変更するだけ済みます。
これにより、UserManagerクラスとUserLoaderクラスを変更し忘れるリスクが大幅に減少します。
まとめ
ロジックに対して信頼できる唯一の情報源を持つことは、コードの信頼性と保守性を高めるために重要です。
複数の情報源が存在する場合、片方のロジックを変更し、もう一方を変更し忘れるリスクがあります。
これによりバグが発生する可能性があります。
信頼できる唯一の情報源を提供するクラスを導入することで、このリスクを大幅に減らすことができます。
ロジックの重要な部分を一箇所にまとめ、信頼できる唯一の情報源を持つことで、コードをより堅牢にし、バグの発生リスクを減らすことができるでしょう。