클래스에서 속성을 사전 초기화하거나 그 과정에서 속성을 추가하는 것이 더 좋은 방법입니까?


11

이것이 절대적으로 철학적 인 질문이라면 유감이지만, 모범 사례가 무엇인지 궁금해서 Google에서 좋은 대답을 찾지 못하는 것 같습니다.

파이썬에서는 보통 빈 클래스를 수퍼 캐치 데이터 구조 컨테이너 (JSON 파일과 같은 종류)로 사용하고 다음과 같이 속성을 추가합니다.

class DataObj:
    "Catch-all data object"
    def __init__(self):
        pass

def processData(inputs):
    data = DataObj()
    data.a = 1
    data.b = "sym"
    data.c = [2,5,2,1]

이것은 컨테이너 객체가 본질적으로 무엇이든 저장할 수 있기 때문에 엄청난 유연성을 제공합니다. 따라서 새로운 요구 사항이 발생하면 DataObj 객체에 다른 속성으로 추가하면됩니다 (코드에서 전달).

그러나 최근에는 (FP 프로그래머가) 이것이 코드를 읽기가 매우 어려워 지므로 이것이 끔찍한 관행이라는 사실에 깊은 인상을 받았습니다. DataObj가 실제로 가지고있는 속성을 파악하기 위해 모든 코드를 거쳐야합니다.

질문 : 유연성을 유지하면서 유지 관리 성을 향상시키기 위해 어떻게 이것을 다시 작성할 수 있습니까?

내가 채택 할 수있는 함수형 프로그래밍 아이디어가 있습니까?

모범 사례를 찾고 있습니다.

참고 : 하나의 아이디어는 예를 들어 발생할 것으로 예상되는 모든 속성으로 클래스를 사전 초기화하는 것입니다.

class DataObj:
    "Catch-all data object"
    def __init__(self):
        data.a = 0
        data.b = ""
        data.c = []

def processData(inputs):
    data = DataObj()
    data.a = 1
    data.b = "sym"
    data.c = [2,5,2,1]

이것이 실제로 좋은 생각입니까? 내 속성이 무엇인지 잘 모르겠다면 어떻게해야합니까?


데이터 구조는 변경이 가능하여 유지 관리가 걱정되는 것 같습니다. 풍부한 자유 시간 ™에서 불변 데이터 모델에 대한기사를 읽어보십시오 . 데이터에 대한 추론 방식이 완전히 변경 될 수 있습니다.
9000

@ 9000 이와 같은 기사는 이미 확신 한 사람들을 다시 확신시킵니다. 나에게 그것은 이유보다 방법처럼 보였습니다 (특정한 요구가 있다고 생각하지 않는 한 이유 목록은 실제로 설득력이 없습니다). 나에게 VB에서 송장을 업데이트하는 사람이 지속적으로 송장 객체의 새로운 사본을 만들어야한다는 것이 납득할 수 없다 (지불 추가, 새로운 송장 객체; 부품 추가, 새로운 송장 객체).
Paul

답변:


10

유연성을 유지하면서 유지 관리 성을 향상시키기 위해 어떻게 이것을 다시 작성할 수 있습니까?

당신은하지 않습니다. 유연성은 정확하게 문제의 원인입니다. 어느 곳에서나 코드가 객체의 속성을 변경할 수 있다면 유지 관리 기능은 이미 조각 된 것입니다. 이상적으로 모든 클래스에는 __init__모든 인스턴스에 대해 동일하게 설정된 일련의 속성이 있습니다. 항상 가능 또는 분별,하지만 당신이없는 때마다 경우해야하지 정말 좋은 그것을 피하는 이유를.

한 가지 아이디어는 발생할 것으로 예상되는 모든 속성으로 클래스를 사전 초기화하는 것입니다

그건 좋은 생각이 아니다. 물론, 속성이 있지만 값이 가짜이거나 값을 할당하지 않은 코드 (또는 철자가 틀린 값)를 포함하는 유효한 값을 가질 수도 있습니다. AttributeError무섭지 만 잘못된 결과를 얻는 것은 더 나쁩니다. 일반적으로 기본값은 괜찮지 만 합리적인 기본값을 선택하고 필요한 것을 결정하려면 객체의 용도를 알아야합니다.

내 속성이 무엇인지 잘 모르겠다면 어떻게해야합니까?

그런 다음 어쨌든 문제가 발생하여 속성 이름을 하드 코딩하는 대신 dict 또는 list를 사용해야합니다. 그러나 나는 당신이 "... 컨테이너 클래스를 작성할 때"를 의미한다고 생각합니다. 대답은 "잠금 단계에서 파일을 편집 할 수 있습니다." 새로운 속성이 필요하십니까? 컨테이너 클래스에 frigging 속성을 추가하십시오. 해당 클래스를 사용하는 코드가 더 있으며 해당 속성이 필요하지 않습니까? 두 개의 별도 클래스로 분할하는 것을 고려하십시오 (Dry를 유지하기 위해 믹스 인 사용). 그렇다면 선택 사항으로 만드십시오.

반복적 인 컨테이너 클래스를 작성하는 것을 두려워하는 경우 : 메타 프로그래밍을 신중하게 적용하거나 collections.namedtuple생성 후 멤버를 변경하지 않아도되는 경우 사용 하십시오 (FP 친구는 기뻐할 것입니다).


7

항상 Alex Martelli의 Bunch 클래스를 사용할 수 있습니다 . 귀하의 경우 :

class DataObj:
    "Catch-all data object"
    def __init__(self, **kwds):
        self.__dict__.update(kwds)

def processData(inputs):
    data = DataObj(a=1, b="sym", c=[2,5,2,1])

그렇게하면 최소한 데이터 가 바보 같은 데이터 저장소이며 모든 값이 한 줄에 있기 때문에 어떤 이름으로 어떤 값이 저장되는지 즉시 알 수 있습니다.

그리고 그렇습니다. 이런 식으로 일을하는 것은 때때로 좋은 생각입니다.


1

아마도 None잘못된 데이터를 나타내는 데 사용하는 두 번째 방법을 사용할 것 입니다. 나중에 속성을 추가하면 읽기 / 유지가 어렵다는 것이 사실입니다. 그러나이 클래스 / 객체의 목적에 대한 자세한 정보는 첫 번째 아이디어가 왜 나쁜 디자인인지에 대한 통찰력을 제공합니다. 메서드 또는 기본 데이터가없는 완전히 빈 클래스가있는 곳은 어디입니까? 왜 클래스의 속성이 무엇인지 모르십니까?

그것은이다 가능한processData방법은 (로 더 좋을 수 process_data는 클래스에 작용하기 때문에, 파이썬 명명 규칙을 따르도록). 예를 들어 데이터 구조 ( dict충분한 위치) 로 더 나을 것 같습니다 .

실제 예를 들어, 코드 리팩토링에 도움이 될 수있는 CodeReview에 대한 질문을 고려할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.