1

(필자는 비교적 경험이 부족한 프로그래머임을 명심하십시오.이 질문은 너무 개방적이라고 볼 수 있습니다. OOP에서 상속에 대한 많은 철학이 있습니다.이 질문은 내 사고 과정에 더 중점을 둡니다. 즉, 경험이 많은 프로그래머가이 시나리오에 접근하고 있습니까? 분명히 정확합니다. 부정확합니까?)비즈니스 엔티티 상속 : 데이터 액세스 레이어에서 기본 클래스 유형을 요청할 때 하위 클래스 속성 액세스 및 표시

컴퓨터, 프린터, 스위치, 라우터, 휴대폰, 하드 드라이브 및 기타 장치를 포함하는 IT 하드웨어에 대한 정보를 추적하는 인벤토리 시스템을 설계하고 있습니다. 데이터베이스가 설계되어 있고 이제 프론트 엔드 애플리케이션을 계획하는 중입니다. 나는 응용 프로그램이 데이터 액세스 레이어, 비즈니스 로직 레이어 및 비즈니스 엔티티를 사용할 계획이다. 나는 개념적 계획 단계에 있으며 아직 구현 세부 사항을 고려해서는 안되는 것을 알지만 내 마음은 앞으로 나아가는 경향이 있습니다. 검색 기능이 작동하는 방식은 다음과 같습니다. 사용자가 검색 기준을 입력하고 검색을 실행합니다. 일치하는 장치 목록 (또는 일치하는 유일한 장치)이 리턴됩니다. 장치 목록은 일부 유형의 목록보기에 표시되며 장치를 선택한 경우 세부 정보보기가 표시됩니다.

내 최종 비즈니스 엔티티에서 상속을 사용하면 내 애플리케이션에 이익이되는지 아니면 불필요한 복잡성이 추가되는지 궁금해하고 있습니다. 내 초기 생각은 그림과 같은 설정입니다 :

특정 유형의 속성을 가진 각 장치 외에도 특정 시간에 모든 장치가있을 수 있습니다. 활성 또는 보관 된 두 상태 중 하나입니다. 나는 이것을 어떻게 모델링 할 지 모릅니다.

Conceptual Class Diagram

나는이 설정을 사용하는 경우 쿼리가 작동하는 방법에 대해 생각하기 시작했다. 데이터 액세스 계층에서 장치의 특정 서브 클래스를 쿼리 간단한데 같은

의사 코드 :이 질문을 작성하는 저를 이끌어

Computer comp = getComputerBySerialNumber(sn); 
List<Router> routers = getRouters(); 

// I can then write code to display a list of basic device information and 
// additionally display all details of a computer or router when requested. 
// Obviously display would be handled in a different layer. 

문제

는 다음과 같은 쿼리를 처리하는 방법입니다 " 특정 위치에서 모든 장치 가져 오기 "를 선택하십시오.

// Returns a list of devices regardless of device type 
// as long as they have the same location 
List<Device> devsFromLocation = getDevicesByLocation(loc); 

// List contains computers, routers, printers, etc. 

기본 클래스 개체 참조가있는 경우 기본 장치 세부 정보와 특정 장치 정보를 어떻게 표시합니까? 미친듯한 주조 나 반사음 사용을 피하려고합니다. 해당 위치의 각 장치에는 부속 유형의 특정 속성이 누락됩니다. 특정 장치에 대한 모든 데이터를 표시하려면 나머지 필드를 얻기 위해 데이터베이스를 다시 쿼리해야합니다. 열악한 디자인의 기호를 다른 쿼리를 실행해야합니까? 또한 올바른 유형의 장치를 어떻게 결정합니까? 각 Device.Type 속성을 테스트하는 대용량 switch/case 문은 정확한 쿼리를 실행하고 전체 하위 유형을 반환하고 세부 정보를 사용자에게 표시 하시겠습니까? 또는 전체 하위 유형의 객체를 포함하는 별도의 목록을 반환 한 다음 모든 목록을 반복하여 목록보기에 공통 속성을 표시 한 다음 상세보기에서 하위 유형 세부 정보를 쉽게 표시 할 수 있습니까?

유용한 상속 사례입니까 아니면 잘못 사용하고 있습니까? 나는 현재 너무 많은 정보의 문제로 고통 받고 있습니다. 나는 OOD에 관해 가능한 모든 것을 읽었고, 나는 내 머리 속에 너무 많은 규칙과 지침을 가지고있어서 내가 무엇인가를 올바르게하고 있는지 결코 알지 못한다. 내 머리가 내가 흡수 해 온 정보를 적용하려고하는 것 같아서 잘못된 구현을 상상하고 있습니다.코드를 유연하게 유지하기 위해 추상화를 프로그래밍하는 것에 대해서는이 모든 비즈니스에 대해 계속 생각하고 있지만, 어느 시점에서는 구체적인 클래스를 다루어야합니다. 내 관점에서 볼 때, 상속은 속성이 아니라 행동에 관한 것입니다. 실제로 어떤 행동을 모델링하지 않았기 때문에 (또는 나는 단지 그것을 볼 수 없습니까?) 장치에 대한 데이터를 수집하기 때문에 관계를 해석하기가 어렵습니다. 이 클래스들은 본질적으로 멍청한 속성 모음이므로 나는 모두 분리 된 클래스가되어야한다고 생각합니다. 그런 다음 다시 한 번 모든 클래스에서 중복 필드가 생길 것입니다. 그러나이 경우에는 정말로 중요합니까?

나는 OOD, 상속, 작곡 등에 관한 많은 책이 있다는 것을 알고있다. 나는 그 책들 중 일부를 읽었다; 나는 현재 더 많은 것을 읽고 있으며 온라인으로 조사하는 데 몇 일을 보냈습니다. 누구나 쉽게 상속의 명백한 사례를 사용합니다. 나는 과일, 동물, 모양에 대한 악몽을 꾼다.

제 질문을 읽어 주셔서 감사 드리며 제공 할 수있는 정보 나 통찰력에 감사드립니다. 다른 팁, 통찰력, 영업 비밀, 매장 된 보물에 대한지도, 바다에 걸린 배 및 육분의 등 무엇이든지 도움이 될 것으로 생각되는 것을 자유롭게 제공해주십시오.

답변

1

가장 직접적인 방법은 정보를 반환하는 기본 클래스에 정보 메서드를 추가하고 각 파생 된 형식이 올바른 정보로 해당 메서드를 재정의하도록하는 것입니다.

이 당신이 할 수있는 것 :

foreach (Base b in list) 
    Write(b.Information()); 

당신의 출력이 더 동적 디바이스 정보 객체를 고려해야 할 필요가있는 경우.

Device이 '가-A 이후 (N)를 귀하의 게시물 만, 나는 또한 당신이 Active StateDevice 기본 클래스의 구성원으로 만들 것을 제안했다 (그래서이 나쁜 생각하게 몇 가지 세부 사항을 놓친 것) 미끄러 데 'Active State (동일하면 Archive State).

당신의 디자인은 멋지고 간단하며 의미가 있습니다.

편집 :

그래서 당신이 정보에 기록하려는 Report 객체가있을 수 있습니다 그래서 당신은 할 것이다 :

class Device{ 
    write_information_to_report(Report report); 
} 

이것은 파생를 추가 할 수있는 파생 클래스에 의해 오버라이드 (override) 할 수있다 특정 정보.

정말로 원하는 경우 InformationOutputter과 같은 내용이 나오면 Report을 추상화 할 수 있습니다.

도형 그리기보고 이런 종류의 좋은 예 : 당신은 당신이 각각 고유의 기능에 대한 책임 개체 수 있습니다 볼 수 있습니다 여기에

class Graphics{ 
    line(int, int, int, int) = 0; 
    curve(float, float, float, float) = 0; 

class OpenGLDrawer : Graphics { 
    line(int, int, int, int) { // Use open gl to draw a line }; 
    curve(int, int, int, int) { // Use open gl to draw a line }; 
} 

class DirextXDrawer : Graphics { 
    line(int, int, int, int) { // Use directX to draw a line }; 
    curve(int, int, int, int) { // Use directX to draw a line }; 
} 

class Shape{ 
    draw(Graphics g) = 0; 
} 

class Triangle : Shape{ 
    draw(Graphics g) { g.line(... /* draw a triangle using line */ }; 
} 

class Circle : Shape{ 
    draw(Graphics g) { g.arc(... /* draw a circle using arc */}; 
} 

은 일반적인 기능은없는 baseclass 수준 및에서 공유 할 수 있습니다 그래픽 객체는 모든 모양을 그릴 수 있습니다.

+0

답변 해 주셔서 감사합니다. 이 정보 방법은 무엇을 할 것입니까? 그냥 모든 정보의 문자열을 반환? UI 필드에 특정 속성을 바인딩하려면 어떻게해야합니까? – TheSecretSquad

+1

@reallythecrash 자네가해야 할 일이 무엇이든 할 수있어. 이상적으로 당신은 어떤 객체를 정보 메소드에 전달할 것이고, 그 객체 자체에 정보를 쓸 수 있습니다. 이 답변을 수정하여 확장 해 보겠습니다 ... – sji