친구가 그의 일화를 바탕으로 수많은 역풍에 직면하고있는 것 같습니다. 그것은 불행한 일이며 작업하기가 매우 어려운 환경 일 수 있습니다. 어려움에도 불구하고, 그는 인생을 더 쉽게 만들기 위해 패턴을 사용하는 올바른 길을 가고 있었으며, 그 길을 떠난 것은 부끄러운 일입니다. 스파게티 코드는 최고의 결과입니다.
기술 및 대인 관계의 두 가지 문제 영역이 있으므로 각 문제를 개별적으로 다룰 것입니다.
대인 관계
친구가 겪고있는 어려움은 빠르게 변화하는 요구 사항과 그것이 유지 관리 가능한 코드를 작성하는 능력에 어떻게 영향을 미치는지입니다. 먼저, 하루에 두 번, 매일 그렇게 긴 시간 동안 변화하는 요구 사항은 더 큰 문제이며 비현실적인 암시 적 기대가 있다고 말하고 싶습니다. 코드가 변경할 수있는 것 보다 요구 사항이 빠르게 변하고 있습니다. 코드 또는 프로그래머가 계속 유지할 것으로 기대할 수 없습니다. 이러한 빠른 변화 속도는 원하는 제품에 대한 불완전한 개념이 더 높은 수준에서 나타납니다. 이것은 문제입니다. 그들이 정말로 무엇을 원하는지 모른다면, 절대 그것을 얻기 위해 많은 시간과 돈을 낭비 할 것입니다.
변경 경계를 설정하는 것이 좋습니다. 2 주마다 변경 사항을 그룹으로 묶은 다음 구현하는 동안 2 주 동안 동결합니다. 다음 2 주 동안 새 목록을 작성하십시오. 이러한 변경 사항 중 일부가 겹치거나 모순되는 느낌이 듭니다 (예 : 두 옵션 사이에서 앞뒤로 흔들림). 변화가 빠르고 격렬 해지면 모두 우선 순위가 높습니다. 이들이 목록에 누적되도록하면 노력과 생산성을 극대화하는 데 가장 중요한 것을 구성하고 우선 순위를 정하기 위해 그들과 함께 작업 할 수 있습니다. 그들은 그들의 변화 중 일부가 어리 석거나 덜 중요하여 친구에게 호흡 공간을주는 것을 볼 수 있습니다.
그러나 이러한 문제로 인해 좋은 코드를 작성하지 못하게해서는 안됩니다. 잘못된 코드는 문제를 악화시킵니다. 한 솔루션에서 다른 솔루션으로 리팩토링하는 데 시간이 걸릴 수 있지만 가능한 사실은 패턴과 원칙을 통해 좋은 코딩 방법의 이점을 보여줍니다.
빈번한 변화가있는 환경에서는 기술 부채 가 발생할 것 입니다. 타월에 던지기보다 너무 지불하는 것이 훨씬 낫고 극복하기에는 너무 커질 때까지 기다리십시오. 패턴이 더 이상 유용하지 않으면 리팩토링하지만 카우보이 코딩 방식으로 돌아 가지 마십시오.
인위적인
친구가 기본 디자인 패턴을 잘 알고있는 것 같습니다. Null 개체는 그가 직면 한 문제에 대한 좋은 접근 방식입니다. 사실, 그것은 여전히 좋은 접근법입니다. 그가 어려움을 겪는 것처럼 보이는 이유 는 패턴 뒤에있는 원칙, 그 이유 에 대한 이해 입니다. 그렇지 않으면, 그가 접근을 포기했을 것이라고는 생각하지 않습니다.
(다음은 원래 질문에서 요구되지 않았지만 예시 목적으로 패턴을 준수하는 방법을 보여주는 일련의 기술 솔루션입니다.)
null 객체의 기본 원리는 다양한 것을 캡슐화 한다는 개념입니다 . 변경 사항을 숨기므로 다른 곳에서는 처리 할 필요가 없습니다. 여기서 null 객체는 product.Price
인스턴스의 분산을 캡슐화 했습니다 (이를 Price
객체 라고 부르고 null 객체 가격은입니다 NullPrice
). Price
비즈니스 개념 인 도메인 개체입니다. 때로는 비즈니스 로직에서 가격을 아직 모릅니다. 이런 일이 발생합니다. null 객체의 완벽한 유스 케이스. 가격을 출력 Price
하는 ToString
메소드가 있거나 알 수없는 경우 빈 문자열이거나 빈 문자열을 NullPrice#ToString
리턴합니다. 이것은 합리적인 행동입니다. 그런 다음 요구 사항이 변경됩니다.
null
API보기에 a를 출력 하거나 관리자보기에 다른 문자열 을 출력해야합니다 . 이것이 우리의 비즈니스 로직에 어떤 영향을 미칩니 까? 글쎄요. 위의 진술에서 'view'라는 단어를 두 번 사용했습니다. 이 단어는 분명하게 말하지 않았지만 요구 사항에서 숨겨진 단어를 들으려면 스스로 훈련해야합니다. 그렇다면 왜 '보기'가 그렇게 중요한가? 변화가 실제로 어디에서 일어나야 하는지 알려주기 때문 입니다.
제쳐두고 : 우리가 MVC 프레임 워크를 사용하는지 여부는 여기와 관련이 없습니다. MVC는 'View'에 대해 매우 구체적인 의미를 갖지만 프레젠테이션 코드의보다 일반적인 의미로 사용하고 있습니다.
뷰에서이 문제를 해결해야합니다. 우리는 어떻게 할 수 있습니까? 가장 쉬운 방법은 if
진술입니다. null 객체가 모든 if를 제거하기위한 것이지만 우리는 실용적이어야합니다. 문자열이 비어 있는지 확인하고 전환 할 수 있습니다.
if(product.Price.ToString("c").Length == 0) { // one way of many
writer.write("Price unspecified [Change]");
} else {
writer.write(product.Price.ToString("c"));
}
이것이 캡슐화에 어떤 영향을 줍니까? 여기서 가장 중요한 부분은 뷰 로직이 뷰에 캡슐화되어 있다는 것 입니다. 이러한 방식으로 비즈니스 로직 / 도메인 객체를 뷰 로직의 변경 사항과 완전히 격리시킬 수 있습니다. 추악하지만 작동합니다. 그러나 이것이 유일한 옵션은 아닙니다.
가격이 설정되지 않은 경우 기본 문자열을 출력하기 위해 비즈니스 로직이 약간 변경되었다고 말할 수 있습니다. 우리는 우리의 Price#ToString
방법 을 약간 조정할 수 있습니다 (실제로 과부하 된 방법을 만듭니다). 기본 반환 값을 수락하고 가격이 설정되어 있지 않은 경우 반환 할 수 있습니다.
class Price {
...
// A new ToString method
public string ToString(string c, string default) {
return ToString(c);
}
...
}
class NullPrice {
...
// A new ToString method
public string ToString(string c, string default) {
return default;
}
...
}
이제 뷰 코드는 다음과 같습니다.
writer.write(product.Price.ToString("c", "Price unspecified [Change]"));
조건이 사라졌습니다. 그러나이 작업을 너무 많이 수행하면 특수 사례 메소드가 도메인 객체로 확산 될 수 있으므로이 경우가 거의없는 경우에만 의미가 있습니다.
대신 부울을 반환 하는 IsSet
메서드를 만들 수 있습니다 Price
.
class Price {
...
public bool IsSet() {
return return true;
}
...
}
class NullPrice {
...
public bool IsSet() {
return false;
}
...
}
로직보기 :
if(product.Price.IsSet()) {
writer.write(product.Price.ToString("c"));
} else {
writer.write("Price unspecified [Change]");
}
우리는 관점에서 조건부로 돌아 오는 것을 보았지만 가격이 설정되어 있는지를 알려주는 비즈니스 로직의 경우가 더 강합니다. 사용 가능한 Price#IsSet
다른 곳에서 사용할 수 있습니다.
마지막으로, 우리는 견해를 돕는 도우미에게 가격을 제시한다는 아이디어를 요약 할 수 있습니다. 이것은 우리가 원하는만큼 도메인 객체를 유지하면서 조건부를 숨길 것입니다.
class PriceStringHelper {
public PriceStringHelper() {}
public string PriceToString(Price price, string default) {
if(price.IsSet()) { // or use string length to not change the Price class at all
return price.ToString("c");
} else {
return default;
}
}
}
로직보기 :
writer.write(new PriceStringHelper().PriceToString(product.Price, "Price unspecified [Change]"));
변화를 만들기 위해 더 많은 가지 방법이 있습니다 (우리가 일반화 할 수있는 PriceStringHelper
객체로는 반환 문자열이 비어있는 경우 기본), 그러나 이들은 (대부분의) 보존 몇 가지 간단한 것들 패턴 모두 와 원칙, 등 뿐만 아니라 그러한 변화를 만드는 실질적인 측면도 있습니다.