0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[リファクタリング技法]参照から値への変更

Posted at

リファクタリング前

以下のコードを考えます。
Person 内部で  Telephone クラスをインスタンス化していますが、電話番号は途中で変更するのではなく値オブジェクトとして新しいインスタンスを生成することが望ましいです。

class Person:
    def __init__(self) -> None:
        self._telephone_number = Telephone()
    @property
    def office_area_code(self):
        return self._telephone_number.area_code
    @office_area_code.setter
    def office_area_code(self, arg):
        self._telephone_number.area_code = arg
    @property
    def office_number(self):
        return self._telephone_number.number
    @office_number.setter
    def office_number(self, arg):
        self._telephone_number.number = arg

class Telephone:
    def __init__(self) -> None:
        self._area_code = 'area_code'
        self._number = 'number'
    @property
    def area_code(self):
        return self._area_code
    @area_code.setter
    def area_code(self, arg):
        self._area_code = arg
    @property
    def number(self):
        return self._number
    @number.setter
    def number(self, arg):
        self._number = arg


if __name__ == '__main__':
    telephone = Telephone()
    person = Person()
    person.office_area_code = '03'
    print(person.office_area_code) # 03

リファクタリング後

リファクタリング後のコードは以下です。
Person のセッター内部で新しいインスタンスを生成してセッターを削除することで Telephone クラスは初期化後に変更が不可となり、値オブジェクトに変更することが可能となります。

from __future__ import annotations


class Person:
    def __init__(self) -> None:
        self._telephone_number = None
        self._office_area_code = ''
        self._office_number = ''
    @property
    def office_area_code(self):
        return self._telephone_number.area_code
    @office_area_code.setter
    def office_area_code(self, arg):
        self._telephone_number = Telephone(arg, self._office_number)
    @property
    def office_number(self):
        return self._telephone_number.number
    @office_number.setter
    def office_number(self, arg):
        self._telephone_number = Telephone(self._office_area_code, arg)

class Telephone:
    def __init__(self, area_code, number) -> None:
        self._area_code = area_code
        self._number = number

    def __eq__(self, other: Telephone) -> bool:
        return self._area_code == other._area_code and self._number == other._number
    @property
    def area_code(self):
        return self._area_code
    @property
    def number(self):
        return self._number


if __name__ == '__main__':
    person = Person()
    person.office_area_code = '03'
    print(person.office_area_code)# 03

また、等価比較メソッド(eq)を定義し機能することをテストコードで検証します。

import pytest

from refactor_a import Telephone


class TestTelehoneNumber:
    def test_telephone_equal(self):
        assert Telephone('03', '03-1111-1111') == Telephone('03', '03-1111-1111')
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?