런타임에 클래스에 필드 추가-디자인 패턴


15

고객이 CMS의 eshop에서 제품에 새로운 속성 (예 : 색상)을 추가 할 수 있기를 원한다고 상상해보십시오.

속성을 필드로 사용하는 대신 :

class Car extends Product {
   protected String type;
   protected int seats;
}

아마 다음과 같은 일을 끝내게 될 것입니다.

class Product {
   protected String productName;
   protected Map<String, Property> properties;
}

class Property {
   protected String name;
   protected String value;
}

즉, 기존 시스템 위에 자체 유형 시스템을 작성하는 것입니다. 도메인 특정 언어를 만들거나 볼 수없는 것처럼 느껴집니다.

이 접근법은 알려진 디자인 패턴입니까? 문제를 다르게 해결 하시겠습니까? 런타임에 필드를 추가 할 수있는 언어가 있다는 것을 알고 있지만 데이터베이스는 어떻습니까? 위와 같이 열을 추가 / 변경하거나 someting을 사용 하시겠습니까?

시간 내 주셔서 감사합니다 :).



어떤 언어를 사용하고 있는지 확실하지 않지만 C # 인 경우 기본적으로 KVP를 제품에서 수행하는 것과 같은 사전에 저장하는 동적 유형을 사용할 수 있으며 직접 추가하지 않고도 속성에 고정시킬 수 있습니다 컬렉션으로서의 컬렉션. 그래도 강력한 타이핑은 없습니다. 나는 당신이 디자인 패턴을 요구한다는 것을 알고 있지만 사용하기 위해 복잡한 것이 필요하다고 생각하지 않습니다. msdn.microsoft.com/ko-kr/magazine/gg598922.aspx
Tony

Tony : Java를 사용하고 있지만 의사 coude :)를 고려하십시오. C #을 통해 해당 동적 개체를 데이터베이스에 유지할 수 있습니까? databse는 데이터의 구조를 미리 알아야하므로 의심합니다.
Filip

국가 종로 패턴 객체가 만드는 라 갱 오브 포, 표시 의 변경 유형을 하거나 런타임에 클래스 . 다른 대안은 관찰자 디자인 패턴 또는 프록시 디자인 패턴
Nikos M.

1
왜 맵 데이터 유형을 사용하지 않습니까? DB에서는 성능을 요구하지 않으면 {id} + {id, key, value}로 표시 될 수 있습니다.
Shadows In Rain

답변:


4

축하합니다! 당신은 방금 출발했을 때 세계 반대편에 도착하여 프로그래밍 언어 / 타입 시스템 지구를 우회했습니다. 다이나믹 언어 / 프로토 타입 기반 오브젝트 랜드의 경계에 도착했습니다!

많은 동적 언어 (예 : JavaScript, PHP, Python)는 런타임에 객체 속성을 확장하거나 변경할 수 있습니다.

이것의 극단적 인 형태는 Self 또는 JavaScript 와 같은 프로토 타입 기반 언어 입니다. 그들은 엄격하게 말해서 수업이 없습니다. 상속을 사용하여 클래스 기반의 객체 지향 프로그래밍처럼 보일 수 있지만 Java 및 C #과 같이 더 명확하게 정의 된 클래스 기반 언어에 비해 규칙이 크게 완화됩니다.

PHP와 Python과 같은 언어는 중간에 존재합니다. 규칙적이고 관용적 인 클래스 기반 시스템이 있습니다. 그러나 JavaScript에서는 찾을 수없는 몇 가지 제한 사항 (예 : "내장 유형 제외")이 있지만 런타임에 객체 속성을 추가, 변경 또는 삭제할 수 있습니다.

이 역동 성의 큰 단점은 성능입니다. 언어가 얼마나 강하거나 약한 유형인지 또는 기계 코드로 얼마나 잘 컴파일 될 수 있는지 잊어 버리십시오. 동적 객체는 단순한 구조체가 아닌 유연한지도 / 사전으로 표시되어야합니다. 이것은 모든 객체 액세스에 오버 헤드를 추가합니다. 일부 프로그램은이 오버 헤드를 줄이기 위해 많은 시간을 투자하지만 (예 : 파이썬의 팬텀 크 워그 할당 및 슬롯 기반 클래스), 추가 오버 헤드는 일반적으로 코스 및 입학 비용에 필적합니다.

디자인으로 돌아가서 클래스의 하위 집합에 동적 속성을 부여하는 기능을 접목하고 있습니다. ㅏProduct 는 가변 속성을 가질 수 있습니다. 아마 Invoice또는 의지 Order와 할 수 없었습니다. 가는 것은 나쁘지 않습니다. 엄격하고 규칙적인 언어 및 유형 시스템을 유지하면서 필요한 곳에서 변형 할 수있는 유연성을 제공합니다. 단점은 이러한 유연한 속성을 관리하는 책임이 있으며, 더 많은 고유 속성과 약간 다른 메커니즘을 통해 처리해야 할 수도 있습니다. p.prop('tensile_strength')보다는 p.tensile_strength, 예를 들어, 및 p.set_prop('tensile_strength', 104.4)보다는p.tensile_strength = 104.4. 그러나 저는 파스칼, Ada, C, Java 및 심지어 비표준 속성 유형에 대해 이러한 getter-setter 액세스를 사용하는 동적 언어로 많은 프로그램을 작업하고 빌드했습니다. 이 접근법은 분명히 실행 가능합니다.

기본적으로 정적 유형과 매우 다양한 세계 간의 긴장은 매우 일반적입니다. 데이터베이스 스키마를 설계 할 때 특히 관계형 및 사전 관계형 데이터 저장소에 대해 유사한 문제가 종종 발생합니다. 때로는 상상 된 모든 변형의 합집합을 포함하거나 정의하기에 충분한 유연성을 포함하는 "슈퍼 행"을 생성 한 다음 해당 필드에 제공되는 데이터를 채워서 처리합니다. 워드 프레스 wp_posts테이블 , 예를 들어, 같은 필드가 comment_count, ping_status, post_parentpost_date_gmt일부 상황에서 흥미로운 것을, 연습에 자주 비워 갈 것이다. 또 다른 접근 방식은 매우 여분입니다. 표준화 와 같은 테이블 wp_options처럼 많이, 당신의Property수업. 좀 더 명시적인 관리가 필요하지만 그 안에있는 항목은 거의 비어 있지 않습니다. 객체 지향 및 문서 데이터베이스 (예 : MongoDB)는 속성 변경을 처리하는 데 더 많은 시간을 할애하는 경우가 많습니다. 속성을 원하는대로 작성하고 설정할 수 있기 때문입니다.


0

나는이 질문이 마음에 든다.

두 가지 접근 방식은 근본적으로 다릅니다.

  • 첫 번째는 OO ans 강력하게 입력되었지만 확장 할 수는 없습니다.
  • 두 번째는 약하게 입력되었습니다 (문자열은 무엇이든 캡슐화합니다)

C ++에서 많은 사람들은 std :: map of boost :: variant 를 사용하여 두 가지를 혼합합니다.

Disgression : C #과 같은 일부 언어에서는 동적으로 유형을 만들 수 있습니다. 동적으로 멤버를 추가하는 일반적인 문제에 대한 훌륭한 솔루션이 될 수 있습니다. 그러나 컴파일 후 "수정 / 추가"유형은 유형 시스템 자체를 손상시키고 "수정 된"유형을 거의 쓸모 없게 만듭니다 (예 : 추가 된 속성에 대한 액세스 방법은 존재하지 않는지 여부 때문에 어떻게해야합니까? 순수한 동적 언어로 끝나는 각 객체에 체계적으로 반영하십시오. _ 'dynamic'.NET 키워드를 참조하십시오


런타임 솔기에서 유형을 만드는 것이 흥미롭지 만 너무 이국적입니다 (Java로 프로그래밍 중입니다). 데이터베이스에 객체를 저장하려는 경우 이러한 솔루션이 작동하지 않습니다. 내가 제안한 약한 유형의 솔루션은 데이터베이스에 쉽게 저장할 수 있습니다.
Filip

0

런타임에 유형을 작성하면 추상화 계층을 작성하는 것보다 훨씬 복잡하게 들립니다. 시스템을 분리하기위한 추상화를 만드는 것이 매우 일반적입니다.

연습의 예를 보여 드리겠습니다. 모스크바 교환 에는 거래자 API와 함께 Plaza2라는 거래 코어가 있습니다. 거래자는 재무 데이터 작업을위한 프로그램을 작성합니다. 문제는이 데이터가 매우 크고 복잡하며 변경에 크게 노출된다는 것입니다. 새로운 금융 상품이 출시되거나 반품이 취소 된 후에 변경 될 수 있습니다. 미래의 변화의 본질은 예측할 수 없습니다. 문자 그대로 매일 변경 될 수 있으며 가난한 프로그래머는 코드를 편집하고 새 버전을 출시해야하며 화난 거래자는 시스템을 수정해야합니다.

명백한 결정은 추상화 뒤에 모든 재정적 지옥을 숨기는 것입니다. 잘 알려진 SQL 테이블 추상화를 사용했습니다. 코어의 가장 큰 부분은 트레이더의 소프트웨어가 스키마를 동적으로 구문 분석하고 시스템과 호환되는지 여부를 알아내는 것과 마찬가지로 유효한 스키마와 함께 작동 할 수 있습니다.

예제로 되돌아 가면 일부 논리 앞에 추상 언어를 만드는 것이 일반적입니다. "속성", "테이블", "메시지"또는 심지어 사람의 언어 일 수도 있지만이 방법의 단점에주의를 기울이십시오.

  • 구문 분석 및 유효성 검사를위한 추가 코드 정적 타이핑에서 컴파일러가 수행 한 모든 작업은 런타임에 수행해야합니다.
  • 메시지, 테이블 또는 기타 기본 요소에 대한 추가 문서 모든 복잡성은 코드에서 일종의 스키마 또는 표준에 이르기까지 다양합니다. 다음은 위에서 언급 한 금융 지옥 스키마의 예입니다. http://ftp.moex.com/pub/FORTS/Plaza2/p2gate_en.pdf (수십 페이지의 테이블)

0

이 접근법은 알려진 디자인 패턴입니까?

XML 및 HTML에서 이는 노드 / 요소의 속성입니다. 또한 확장 속성, 이름 / 값 쌍 및 매개 변수라고도 들었습니다.

문제를 다르게 해결 하시겠습니까?

이것이 내가 문제를 해결하는 방법입니다.

런타임에 필드를 추가 할 수있는 언어가 있다는 것을 알고 있지만 데이터베이스는 어떻습니까?

어떤 의미에서 데이터베이스는 Java와 같습니다. pesudo-sql에서 :

TABLE products
(
    product_name VARCHAR(50),
    product_id INTEGER AUTOINCREMENT
)

TABLE attributes
(
    product_id INTEGER,
    name VARCHAR(50),
    value VARCHAR(2000)
)

이것은 자바에 해당합니다

class Product {
   protected String productName;
   protected Map<String, String> properties;
}

Map은 이름을 키로 저장하므로 Property 클래스가 필요하지 않습니다.

위와 같이 열을 추가 / 변경하거나 someting을 사용 하시겠습니까?

열 추가 / 변경을 시도했지만 악몽이었습니다. 할 수는 있지만 일이 계속 동기화되지 않아서 제대로 작동하지 않습니다. 위에서 설명한 테이블 구조가 훨씬 성공적이었습니다. 당신의에 의해 검색 및 주문을해야 할 경우, 각 데이터 유형 (대한 테이블 속성 사용을 고려 date_attributes, currency_attributes등) 또는 제품 테이블에서 좋은 오래된 데이터베이스 컬럼과 같은 속성 중 일부를 추가. 보고서는 종종 데이터베이스 열보다 하위 테이블에 작성하기가 훨씬 쉽습니다.

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