세계가 이해가된다면?


10

많은 객체에 필요한 가치가 있습니다. 예를 들어, 투자 대상이 다른 금융 응용 프로그램이며 대부분 현재 금리가 필요합니다.

나는 "재정 환경"을 이자율로 자산으로 캡슐화하기를 바랐다. 그러나 그 가치가 필요한 형제 자매는 그것을 얻을 수 없습니다.

디자인을 오버 커플 링하지 않고 여러 객체간에 가치를 공유하는 방법은 무엇입니까? 분명히 나는 ​​이것에 대해 생각하고 있습니다.


2
계산 기간 동안 이자율이 고정되어 있습니까? 아니면 시간 간격에 따라 달라질 수있는 시뮬레이션과 같은 일을하고 있습니까?
James

시뮬레이션과 비슷합니다. 실행 중에 변경 될 수 있습니다.
Greg

이 경우 각 투자는 실제로 이자율을 저장해야 update합니까, 아니면 매 단계마다 호출 되는 함수에 대한 매개 변수를 통해이를받을 수 있습니까? 시뮬레이션 작동 방식을 의사 코드로 게시 할 수 있습니까?
James

3
당신은 올바른 길 중 하나 Singleton이며, OO 구문 설탕이있는 글로벌이며 가능한 최악의 방법으로 코드를 밀접하게 결합시키는 끔찍한 솔루션입니다. 이해할 때 까지이 기사를 계속 읽으십시오 !

이자율은 시계열 과 같습니다. 시계열DateTime 은 입력으로 사용하고 출력으로 숫자를 반환하는 함수입니다 .
rwong

답변:


14

많은 객체에 필요한 가치가 있습니다.

이것은 디자인 냄새입니다. 많은 물체가 무언가에 대해 알아야하는 경우는 드 un니다. 즉, 현재 금리는 예외적 인 상황의 좋은 예입니다. 걱정에 한 가지에 대해 거의 없다이다 이자율. 다른 금융 상품은 다른 금리를 사용합니다. 최소한, 로케일마다 다른 '표준'비율을 사용합니다. 또한 테스트 및보고를 돕기 위해 현재 요율 을 사용하고 싶지 않으므로 일반적으로 요율을 전달하는 것이 좋습니다. '가정'또는 '보고 날짜 기준'요율을 사용하려고합니다.

디자인을 오버 커플 링하지 않고 여러 객체간에 가치를 공유하는 방법

공유함으로써 모든 사람이 단일 인스턴스를 참조하지는 않습니다. 같은 것을 전달하는 것은 여전히 ​​어느 정도 연결되어 있지만 다양한 계산의 입력으로 현재 이자율과 같은 것이 필요하기 때문에 초과 연결이 아닙니다 .


17
예외적 인 상황의 문제는 실제 소프트웨어에서는 그다지 뛰어나지 않다는 것입니다.
mattnz

나는 이것이 심각한 오해라고 생각합니다. 우리의 알고리즘은 서로 다른 상황에서 동시에 존재합니다. 첫 번째는 글로벌 컨텍스트입니다. 그런 다음 객체 지향 언어에 대한 "this"컨텍스트. 웹 서비스의 세션 컨텍스트, DB 환경의 트랜잭션 컨텍스트, GUI의 기본 창 및 이러한 컨텍스트에 속하는 정보가 있습니다. 그들은 같은 상황에있는 모든 사람을 위해 "매달려"있어야하며 동일한 세트 (객체)를 사용할 수 있어야합니다. 괜찮습니다 문제는 컨텍스트 서비스를 작성하거나 Spring in Java와 같은 프레임 워크를 사용하는 것이 아니라 각 객체에 대해 이것을 해결하는 것입니다.
Lorand Kedves

3
현재 금리에 대한 예외는 없습니다. 개방 도로 속도 제한, 수용 가능한 혈중 알코올 농도, GST (또는 부가가치세) 세율 중 하나의 값을 갖는 실제 항목의 예는 매우 적습니다. 그것은 과학과 공학의 차이점입니다. 엔지니어들은 오늘날의 실제 문제를 해결합니다. 과학자들은 현실 세계가 멋진 상자에 들어 맞고 그 문제를 해결할 날을 꿈꿉니다.
mattnz

1
나는 이것이 간단하고 10 년의 OOP 경험에 의존하지 않기 때문에 이것을 답으로 선택했습니다. 모든 응답자에게 감사드립니다. 많은 참고 문헌 덕분에 하루 종일 독서를했지만 여전히 조금 당황했습니다. 그런 간단한 질문에 대해, 나는 그 반응의 다양성과 감정 뒤에 놀랐습니다. 나는 때때로 싱글 톤이 가장 잘 제공하는 글로벌하지만 다양한 데이터의 중심 소스가 있다고 확신합니다. 싱글 톤을 피하기 위해 객체의 계층 구조를 위아래로 포인터를 전달해야한다고 생각하지 않습니다. 다시 한번 감사드립니다.
Greg

@mattnz, 문제는 귀하의 프로그램 중 하나가 회사, 주 또는 국가에 걸친 여러 사용자 기반으로 프로그램을 배포하는 경우 하나의 변수가 다양하다는 것입니다. 그들 모두는 또한 시간이 지남에 따라 변할 수 있습니다.
Dan Lyons

10

이 특별한 경우에는 Singleton Pattern을 사용합니다 . FinancialEnvironment는 다른 모든 클래스 라이브러리가 알고있는 객체이지만 Singleton에 의해 인스턴스화됩니다. 그런 다음 인스턴스화 된 객체를 다양한 클래스 라이브러리로 보내는 것이 이상적입니다.

예를 들면 다음과 같습니다.

  • 서비스 계층 (클래스 라이브러리)-싱글 톤을 통해 FinancialEnvironment 오브젝트를 인스턴스화
  • 비즈니스 로직 계층 (클래스 라이브러리)-서비스 계층에서 FinancialEnvironment 오브젝트를 승인합니다.
  • 데이터 액세스 계층 (클래스 라이브러리)-서비스 계층 (또는 아키텍처에 따라 비즈니스 로직 계층)에서 FinancialEnvironment 오브젝트를 승인합니다. 또는 Singleton이 데이터 액세스 계층을 호출하여 이율과 같은 정보를 리포지토리 (데이터베이스 / 웹 서비스 / WCF 서비스)에서 가져옵니다.
  • 엔티티 (또는이를 호출하려는 경우 DTO) 클래스 라이브러리-FinancialEnvironment 오브젝트가있는 위치. 다른 모든 클래스 라이브러리에는 Entities 클래스 라이브러리에 대한 참조가 있습니다.

다른 클래스는 Entities 클래스 라이브러리를 통해서만 묶여 있으며 인스턴스화 된 FinancialEnvironment 개체를 허용합니다. 그들은 어떻게 만들어 졌는지 신경 쓰지 않고 서비스 계층 만 수행하며 원하는 것은 정보입니다. 단일 톤은 @Telastyn이 지적한 로컬 규칙에 따라 여러 FinancialEnvironment 객체를 저장할 수있을만큼 똑똑 할 수 있습니다.

참고로, 나는 Singleton Pattern의 열렬한 팬이 아닙니다. 매우 쉽게 오용 될 수 있기 때문에 코드 냄새라고 생각합니다. 그러나 어떤 경우에는 필요합니다.

최신 정보:

절대적으로 글로벌 변수가 있어야한다면 위에서 설명한대로 싱글 톤 패턴을 구현하는 것이 좋습니다. 그러나 나는 이것에 대한 열렬한 팬이 아니며 원래 게시물의 의견을 바탕으로 다른 여러 사람들도 그렇지 않습니다. InterestRate만큼 변동성이 큰 싱글 톤이 최상의 솔루션이 아닐 수 있습니다. 싱글 톤은 정보가 변하지 않을 때 가장 잘 작동합니다. 예를 들어, 응용 프로그램 중 하나에서 Singleton을 사용하여 성능 카운터를 인스턴스화했습니다. 변경되는 경우 업데이트되는 데이터를 처리 할 논리가 있어야합니다.

내가 베팅 한 사람이라면 금리가 데이터베이스 어딘가에 저장되어 있거나 웹 서비스를 통해 검색되었다고 생각합니다. 이 경우 해당 정보를 검색하기 위해 리포지토리 (데이터 액세스 계층)가 권장됩니다. 데이터베이스로의 불필요한 트립을 피하기 위해 (금리가 얼마나 자주 변경되는지 또는 FinancialInformation 클래스의 다른 정보가 확실하지 않은 경우) 캐싱을 사용할 수 있습니다. C # 세계에서 Microsoft의 캐싱 응용 프로그램 블록 라이브러리는 매우 잘 작동합니다.

위의 예에서 변경된 유일한 것은 서비스 계층에서 FinancialInformation을 필요로하는 다양한 클래스가 개체를 인스턴스화하는 싱글 톤 대신 데이터 액세스 계층에서 검색하는 것입니다.


8
어. 지구본을 싱글 톤으로 만든다고해서 냄새가 덜 나지는 않습니다. 무엇이든 당신은 훨씬 더 자신을 제한했습니다.
Telastyn

3
@DavidCowden 구현하기가 복잡하지 않은지는 중요하지 않습니다. 그들은 세계보다 디자인을 더 나쁘게 만듭니다. 그들은 세계적 이며 그들은 당신이 하나만 가지고있는 (필요하지 않은) 제한을 시행합니다.
Telastyn

4
나는 "단일 톤으로 만들고 나쁜 연습에서 모범 사례로 넘어갈 것"이라는 비꼬는 의견을 게시하려고했지만, 이미 승인되고 투표권이있는 답변이라는 것을 알았습니다. 아주 좋아요!
Kevin

4
SingletonOO 구문 설탕과 게으른 약한 마음에 대한 버팀목과 글로벌입니다. Singleton/global이 코드가 엄청나게 나쁜 아이디어라는 것을 깨달았을 때 모든 사람이 왜 그렇게 말하는지 나중에 이 될 무언가에 코드 를 단단히 결합하는 최악의 방법입니다 !

4
@Telastyn : 완벽하게 주문 된 이론적 소프트웨어 디자인 세계를 떠나 실제 세계에 합류하면 fubar'd를 얻는 가장 완벽한 디자인은 불행한 현실입니다.
mattnz

4

구성 파일?

"전역 적으로"사용되는 값이 있으면 구성 파일에 넣으십시오. 그런 다음 각 시스템과 하위 시스템이이를 참조하여 필요한 키를 가져 와서 읽기 전용으로 만들 수 있습니다.


금리가 바뀔 때마다 사용자가 구성 파일을 업데이트하도록 하시겠습니까?
Caleb

2
왜 안돼? "가변"물론 자주 변경되는 사항은 CENTRALIZED 데이터 스토어에 배치해야합니다.
Darknight

1

방금 출시 한 크기가 큰 (~ 50k LOC) 프로젝트에서 약 한 달간 유지 보수를 한 경험이 있습니다.

나는 당신이 아마도 전역 객체를 원하지 않을 것이라고 말할 수 있습니다. 그런 종류의 부스러기를 소개하면 도움보다 남용의 기회가 더 많아집니다.

내 초기 제안은 현재 금리가 필요한 여러 클래스가있는 경우 아마도 클래스를 구현하고 싶을 IInterestRateConsumer것입니다. 해당 인터페이스 안에는 SetCurrentInterestRate(double rate)(또는 의미가있는 것) 또는 속성 일 수 있습니다.

금리를 전달하는 것은 실제로 커플 링되지 않습니다. 클래스에 금리가 필요한 경우 API의 일부입니다. 당신의 클래스 중 하나가 다른 클래스가 그 금리를 어떻게 사용하는지에 대해 걱정하기 시작할 때만 연결됩니다.


주위에 금리를 전달하면 됩니다 그냥 아니라, 커플 링 불량 커플.
vaughandroid

1

Martin Fowler는 정적 글로벌을보다 유연한 것으로 리팩토링하는 방법에 대해 간략하게 설명하는 기사를 제공 합니다. 기본적으로 단일 클래스로 만든 다음 하위 클래스로 인스턴스 클래스 재정의를 지원하도록 싱글 톤을 수정하십시오 (필요한 경우 인스턴스를 생성하는 논리를 하위 클래스로 만들 수있는 별도 클래스로 이동하십시오). 수퍼 클래스 인스턴스를 생성 한 다음 나중에 교체하는 것이 문제가됩니다).

물론 싱글 톤 (대체 가능한 싱글 톤)의 문제와 모든 곳에서 동일한 객체를 통과시키는 고통의 무게를 측정해야합니다.

"재무 환경"개체까지는 첫 번째 단계에서 프로그래밍하는 것이 편리하지만 완료되면 몇 가지 추가 종속성이 추가되었습니다. 금리가 필요한 클래스는 이제 금융 환경 개체를 통과 한 경우에만 작동하므로 재무 환경 개체가없는 경우 재사용하기가 어렵습니다. 그래서 나는 그것을 널리 전달하지 않을 것입니다.


0

이자율 데이터를 중앙 캐시에 넣지 않겠습니까?

memcached와 같은 여러 캐시 라이브러리 중 하나를 사용하면 요구 사항에 가장 적합한 것을 사용할 수 있으며 동시성 및 코드 관리 문제를 모두 해결하고 응용 프로그램을 여러 프로세스로 확장 할 수 있습니다.

또는 전체 돼지를 가져다가 데이터베이스에 저장하면 여러 서버로 확장 할 수 있습니다.


0

그러한 상황에서 나는 때때로 여러 개의 층을 가진 "문맥"이라는 용어를 성공적으로 도입 (재사용)했다.

즉, 이러한 종류의 개체를 요청할 수있는 "전역"개체 저장소 인 단일 항목을 의미합니다. 이를 필요로하는 코드에는 상점의 헤더가 포함되며 전역 함수를 사용하여 객체 인스턴스 (이자율 제공 업체 등)를 가져옵니다.

상점은 다음 중 하나 일 수 있습니다.

  • 엄격하게 유형이 지정됨 : 모든 게재 유형에 대한 헤더를 포함하므로 InterestRate getCurrentInterestRate ()와 같이 유형이 지정된 접근자를 만들 수 있습니다.
  • 또는 일반 : Object getObject (enum obType); 새로운 종류 (obtypeCurrentInterestRate)로 obType 열거 형 만 확장하십시오.

시스템이 클수록 잘못된 열거를 사용할 위험이 적기 때문에 후자의 솔루션이 더 유용합니다. 반면에 앞으로 형식 선언을 허용하는 언어를 사용하면 저장소에 모든 헤더를 포함하지 않고 형식화 된 접근자를 사용할 수 있다고 생각합니다.

한 가지 더 참고 : GUI 및 인쇄물, 전역 및 세션 수준 로그 등의 다른 언어 값과 같이 다른 용도로 동일한 객체 유형의 인스턴스가 여러 개있을 수 있으므로 열거 형 / 접근 자 이름이 실제 유형을 반영해서는 안됩니다 요청 된 인스턴스 (CurrentInterestRate)의 역할입니다.

상점 구현에서 컨텍스트 레벨 및 컨텍스트 인스턴스 콜렉션을 관리해야합니다. 간단한 예는 웹 서비스로, 전역 컨텍스트 (해당 개체에 대한 모든 요청에 ​​대한 하나의 인스턴스-서버 팜이있을 때 문제가 있음)와 각 웹 세션에 대한 컨텍스트가 있습니다. 여러 개의 병렬 세션 등을 가질 수있는 각 사용자에 대한 컨텍스트를 가질 수도 있습니다. 여러 서버의 경우 이러한 종류의 분산 캐시를 사용해야합니다.

요청이 들어 오면 요청 된 객체의 컨텍스트 수준을 결정하고 해당 컨텍스트를 호출에 가져옵니다. 객체가 있으면 다시 보냅니다. 그렇지 않은 경우 해당 컨텍스트 레벨에서 작성하여 저장 한 후 리턴합니다. 물론 작성 섹션을 동기화하고이를 분산 캐시에 공개하십시오. 클래스 이름 (Java, Objective C 등)으로 객체 인스턴스를 생성 할 수있는 언어를 사용하면 플러그인과 유사하게 구성 할 수 있지만 팩토리 기능이있는 플러그 가능 라이브러리를 사용하여 C에서 수행 할 수 있습니다.

참고 사항 : 호출자는 자신의 컨텍스트와 요청 된 객체의 컨텍스트 수준에 대해 너무 많이 알지 않아야합니다. 이유 : 1 : 이러한 매개 변수를 사용하여 실수 (또는 "영리한 트릭")를하기 쉽습니다. 2 : 요청 된 컨텍스트 레벨이 나중에 변경 될 수 있습니다. 나는 주로 컨텍스트 정보를 스레드에 연결하므로 객체 저장소에는 요청의 추가 매개 변수가없는 정보가 있습니다.

반면에 요청에는 인스턴스에 대한 힌트가 포함될 수 있습니다 (예 : 특정 날짜에 대한 이자율 확보). 동일한 "전역"액세스 여야하지만 날짜에 따라 여러 인스턴스가 있으며 (및 속도 변경간에 동일한 인스턴스로 다른 날짜 값을 가져옴) "힌트"개체를 요청에 추가하는 것이 좋습니다. 상점이 아닌 인스턴스 팩토리; 상점에서 사용하는 팩토리에 대한 keyForHint. 나중에 언급했듯이이 기능들을 나중에 추가 할 수 있습니다.

귀하의 경우 이것은 일종의 과잉입니다 (전역 수준에서 하나의 객체 만 제공됨). 현재 매우 작고 간단한 추가 코드의 경우 더 복잡한 요구 사항에 대한 메커니즘을 얻습니다.

또 다른 좋은 소식 : Java를 사용하는 경우 봄에 너무 많이 생각하지 않고이 서비스를 얻는다면 자세한 내용을 설명하고 싶었습니다.


0

전역 (또는 싱글 톤)을 사용하지 않는 이유는 처음에 하나의 값만 가질 것으로 예상하더라도 동일한 프로그램에서 동일한 코드를 여러 번 사용할 수 있다는 것은 놀랍게도 유용합니다.

  • 이자율이 다른 경우 WOULD 발생을 계산
  • 일부 구성 요소가 미국 이자율에 의존하고 일부 구성 요소가 영국 이자율에 의존하게하려면

금리를 "금융 상품"클래스의 멤버로 만들고 모든 계산을 클래스 단위로 전달하거나 건축시 포인터 / 후크를 제공해야한다는 점에 동의합니다.


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