{"componentChunkName":"component---src-containers-post-index-tsx","path":"/backend/object/chapter8/의존성_관리하기/","result":{"pageContext":{"next":{"id":"5c30d890-7e1f-5638-9630-e5d1dea7f6c9","html":"<p>사람의 기억은 단기 기억과 장기 기억으로 분류할 수 있다. 실제로 문제를 해결하기 위해 사용하는 저장소는 장기 기억이 아니라 단기 기억이다.</p>\n<ul>\n<li>인지 과부하(cognitive overload): 문제 해결에 필요한 요소의 수가 단기 기억의 용량을 초과하는 순간 문제 해결 능력이 급격하게 떨어지는 것</li>\n<li>인지 과부하를 줄이는 가장 좋은 방법은 단기 기억 안에 보관할 정보의 양을 조절하는 것\n<ul>\n<li>추상화: 불필요한 정보를 제거하고 현재의 문제 해결에 필요한 핵심만 남기는 작업</li>\n<li>분해(decomposition): 큰 문제를 해결 가능한 작은 문제로 나누는 작업</li>\n</ul>\n</li>\n</ul>\n<blockquote>\n<p>한 번에 단기 기억에 담을 수 있는 추상화의 수에는 한계가 있지만 추상화를 더 큰 규모의 추상화로 압축시킴으로써 단기 기억의 한계를 초월할 수 있다.</p>\n</blockquote>\n<h2 id=\"-71-프로시저-추상화와-데이터-추상화\" style=\"position:relative;\"><a href=\"#-71-%ED%94%84%EB%A1%9C%EC%8B%9C%EC%A0%80-%EC%B6%94%EC%83%81%ED%99%94%EC%99%80-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B6%94%EC%83%81%ED%99%94\" aria-label=\" 71 프로시저 추상화와 데이터 추상화 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.1 프로시저 추상화와 데이터 추상화</h2>\n<p>모든 프로그래밍 패러다임은 추상화와 분해의 관점에서 설명할 수 있다.</p>\n<ol>\n<li>프로시저 추상화\n<ul>\n<li>소프트웨어가 무엇을 해야하는지를 추상화</li>\n<li>프로시저 추상화를 중심으로 시스템을 분해한다면 기능 분해(알고리즘 분해)</li>\n</ul>\n</li>\n<li>데이터 추상화\n<ul>\n<li>소프트웨어가 무엇을 알아야 하는지를 추상화</li>\n<li>데이터 추상화를 중심으로 시스템을 분해한다면 <strong>타입을 추상화(추상 데이터 타입)</strong> 하거나 <strong>프로시저를 추상화(객체지향)</strong> 해야한다.</li>\n</ul>\n</li>\n</ol>\n<p><code>협력하는 공동체</code>를 구성하도록 객체들로 나누는 과정이 바로 객체지향 패러다임에서의 분해를 의미</p>\n<h2 id=\"-72-프로시저-추상화와-기능-분해\" style=\"position:relative;\"><a href=\"#-72-%ED%94%84%EB%A1%9C%EC%8B%9C%EC%A0%80-%EC%B6%94%EC%83%81%ED%99%94%EC%99%80-%EA%B8%B0%EB%8A%A5-%EB%B6%84%ED%95%B4\" aria-label=\" 72 프로시저 추상화와 기능 분해 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.2 프로시저 추상화와 기능 분해</h2>\n<h3 id=\"-721-메인-함수로의-시스템\" style=\"position:relative;\"><a href=\"#-721-%EB%A9%94%EC%9D%B8-%ED%95%A8%EC%88%98%EB%A1%9C%EC%9D%98-%EC%8B%9C%EC%8A%A4%ED%85%9C\" aria-label=\" 721 메인 함수로의 시스템 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.2.1 메인 함수로의 시스템</h3>\n<p>기능 분해의 관점에서 추상화의 단위는 프로시저이며 시스템은 프로시저를 단위로 분해</p>\n<ul>\n<li>프로시저는 반복적으로 실행되거나 거의 유사하게 실행되는 작업들을 하나의 장소에 모아놓음으로써 로직을 재사용하고 중복을 방지할 수 있는 추상화 방법</li>\n<li>프로시저는 잠재적으로 정보은닉의 가능성을 제시</li>\n</ul>\n<blockquote>\n<p>시스템은 필요한 더 작은 작업으로 분해될 수 있는 하나의 커다란 메인 함수다.</p>\n</blockquote>\n<p>전통적인 기능 분해 방법은 **하향식 접근법(Top-Down Approach)**을 따른다.</p>\n<ul>\n<li>가장 최상위 기능을 정의하고, 이 기능을 좀 더 작은 단계의 하위 기능으로 분해해 나가는 방법</li>\n<li>분해는 세분화된 마지막 하위 기능이 프로그래밍 언어로 구현 가능한 수준이 될 때까지 계속된다.</li>\n</ul>\n<h3 id=\"-722-급여-관리-시스템\" style=\"position:relative;\"><a href=\"#-722-%EA%B8%89%EC%97%AC-%EA%B4%80%EB%A6%AC-%EC%8B%9C%EC%8A%A4%ED%85%9C\" aria-label=\" 722 급여 관리 시스템 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.2.2 급여 관리 시스템</h3>\n<p><code>급여 = 기본급 - (기본급 * 소득세율)</code></p>\n<p><code>직원의 급여를 계산한다</code></p>\n<ul>\n<li>급여 관리 시스템에 대한 추상적인 최상위 문장</li>\n</ul>\n<deckgo-highlight-code language=\"text\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">직원의 급여를 계산한다\n  사용자로부터 소득세율을 입력받는다.\n  직원의 급여를 계산한다.\n  양식에 맞게 결과를 출력한다.</code>\n        </deckgo-highlight-code>\n<ul>\n<li>세부적인 절차로 구체화</li>\n</ul>\n<deckgo-highlight-code language=\"text\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">직원의 급여를 계산한다\n  사용자로부터 소득세율을 입력받는다.\n    &quot;세율을 입력하세요: &quot;라는 문장을 화면에 출력한다.\n    키보드를 통해 세율을 입력받는다.\n  직원의 급여를 계산한다.\n    전역 변수에 저장된 직원의 기본급 정보를 얻는다.\n    급여를 계산한다.\n  양식에 맞게 결과를 출력한다.\n    &quot;이름: {직원명}, 급여: {계산된 금액}&quot; 형식에 다라 출력 문자열을 생성한다.</code>\n        </deckgo-highlight-code>\n<ul>\n<li>기능 분해의 결과</li>\n<li>입력 정보는 직원정보와 소득세율이고 출력은 계산된 급여 정보</li>\n</ul>\n<h3 id=\"-723-급여-관리-시스템-구현\" style=\"position:relative;\"><a href=\"#-723-%EA%B8%89%EC%97%AC-%EA%B4%80%EB%A6%AC-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%ED%98%84\" aria-label=\" 723 급여 관리 시스템 구현 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.2.3 급여 관리 시스템 구현</h3>\n<p>루비 언어를 기반으로 예시를 든다.</p>\n<p><code>직원의 급여를 계산한다</code></p>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def main(name)\nend</code>\n        </deckgo-highlight-code>\n<ul>\n<li>최상위 문장은 하나의 메인 함수로 매핑된다.</li>\n</ul>\n<deckgo-highlight-code language=\"text\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">  사용자로부터 소득세율을 입력받는다.\n  직원의 급여를 계산한다.\n  양식에 맞게 결과를 출력한다.</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def main(name)\n  taxRate = getTaxRate()\n  pay = calculatePayFor(name, taxRate)\n  puts(describeResult(name, pay))\nend</code>\n        </deckgo-highlight-code>\n<ul>\n<li>각 문장에 대응된다.</li>\n</ul>\n<deckgo-highlight-code language=\"text\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">  사용자로부터 소득세율을 입력받는다.\n    &quot;세율을 입력하세요: &quot;라는 문장을 화면에 출력한다.\n    키보드를 통해 세율을 입력받는다.</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def getTaxRate()\n  print(&quot;세율을 입력하세요: &quot;)\n  return gets().chomp().to_f()\nend</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"text\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">  직원의 급여를 계산한다.\n    전역 변수에 저장된 직원의 기본급 정보를 얻는다.\n    급여를 계산한다.</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">$employees = [&quot;직원A&quot;, &quot;직원B&quot;, &quot;직원C&quot;]\n$basePays = [400, 300, 250]</code>\n        </deckgo-highlight-code>\n<ul>\n<li>동일한 직원에 대한 이름과 기본급 정보는 두 배열 내의 동일한 인덱스에 저장</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def calculatePayFor(name, taxRate)\n  index = $imployees.index(name)\n  basePay = $basePays[index]\n  return basePay - (basePay * taxRate)\nend</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"text\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">  양식에 맞게 결과를 출력한다.\n    &quot;이름: {직원명}, 급여: {계산된 금액}&quot; 형식에 다라 출력 문자열을 생성한다.</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def describeResult(name, pay)\n  return &quot;이름: #{name}, 급여: #{pay}&quot;\nend</code>\n        </deckgo-highlight-code>\n<p>하향식 기능 분해 방식으로 설계한 시스템은 메인 함수를 루트로 하는 '트리(tree)'로 표현할 수 있다. 체계적이고 이상적으로 보이지만 우리가 사는 세계는 그렇게 체계적이지도, 이상적이지도 않다.</p>\n<h3 id=\"-724-하향식-기능-분해의-문제점\" style=\"position:relative;\"><a href=\"#-724-%ED%95%98%ED%96%A5%EC%8B%9D-%EA%B8%B0%EB%8A%A5-%EB%B6%84%ED%95%B4%EC%9D%98-%EB%AC%B8%EC%A0%9C%EC%A0%90\" aria-label=\" 724 하향식 기능 분해의 문제점 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.2.4 하향식 기능 분해의 문제점</h3>\n<ul>\n<li>시스템은 하나의 메인 함수로 구성돼 있지 않다.</li>\n<li>기능 추가나 요구사항 변경으로 인해 메인 함수를 빈번하게 수정해야 한다.</li>\n<li>비즈니스 로직이 사용자 인터페이스와 강하게 결합된다.</li>\n<li>하향식 분해는 너무 이른 시기에 함수들의 실행 순서를 고정시키기 때문에 유연성과 재사용성이 저하된다.</li>\n<li>데이터 형식이 변경될 경우 파급효과를 예측할 수 없다.</li>\n</ul>\n<h4 id=\"-하나의-메인-함수라는-비현실적인-아이디어\" style=\"position:relative;\"><a href=\"#-%ED%95%98%EB%82%98%EC%9D%98-%EB%A9%94%EC%9D%B8-%ED%95%A8%EC%88%98%EB%9D%BC%EB%8A%94-%EB%B9%84%ED%98%84%EC%8B%A4%EC%A0%81%EC%9D%B8-%EC%95%84%EC%9D%B4%EB%94%94%EC%96%B4\" aria-label=\" 하나의 메인 함수라는 비현실적인 아이디어 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠 하나의 메인 함수라는 비현실적인 아이디어</h4>\n<ul>\n<li>어떤 시스템도 최초에 release됐던 당시의 모습을 그대로 유지하지는 않는다. 즉, 지속적으로 새로운 기능을 추가하게 된다.</li>\n<li>대부분의 추가되는 기능은 메인 함수의 일부가 아닐 것이다. 결국 어느 시점에 이르면 유일한 메인 함수라는 개념은 의미가 없어지고 시스템은 여러 개의 동등한 수준의 함수 집합으로 성장하게 될 것이다.</li>\n<li>하향식 접근법은 하나의 알고리즘을 구현하거나 배치 처리를 구현하기에는 적합하지만 현대적인 상호작용 시스템을 개발하는 데는 적합하지 않다.</li>\n</ul>\n<blockquote>\n<p>실제 시스템에 정상(top)이란 존재하지 않는다.      - 버트란드 마이어</p>\n</blockquote>\n<h4 id=\"-메인-함수의-빈번한-재설계\" style=\"position:relative;\"><a href=\"#-%EB%A9%94%EC%9D%B8-%ED%95%A8%EC%88%98%EC%9D%98-%EB%B9%88%EB%B2%88%ED%95%9C-%EC%9E%AC%EC%84%A4%EA%B3%84\" aria-label=\" 메인 함수의 빈번한 재설계 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠 메인 함수의 빈번한 재설계</h4>\n<ul>\n<li>기존 로직과는 아무런 상관이 없는 새로운 함수의 적절한 위치를 확보해야 하기 때문에 메인 함수의 구조를 급격하게 변경할 수밖에 없다.</li>\n</ul>\n<p>급여 관리 시스템에 모든 직원들의 기본급의 총합을 구하는 기능을 추가해 달라는 새로운 요구사항이 접수됐다고 가정</p>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def sumOfBasePays()\n  result = 0\n  for basePay in $basePays\n    result += basePay\n  end\n  puts(result)\nend</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def main(name)\n  taxRate = getTaxRate()\n  pay = calculatePayFor(name, taxRate)\n  puts(describeResult(name, pay))\nend</code>\n        </deckgo-highlight-code>\n<ul>\n<li>메인함수 안에서 호출할 자리가 마땅치 않다.</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def calculatePay(name)\n  taxRate = getTaxRate()\n  pay = calculatePayFor(name, taxRate)\n  puts(describeResult(name, pay))\nend</code>\n        </deckgo-highlight-code>\n<ul>\n<li>메인함수를 <code>calcuatePay</code> 함수로 옮기자</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def main(operation, args={})\n  case(operation)\n  when :pay then calculatePay(args[:name])\n  when :basePays then sumOfBasePays()\n  end\nend</code>\n        </deckgo-highlight-code>\n<ul>\n<li>인자에 따라 다른 함수를 호출</li>\n<li>결과적으로 기존 코드의 빈번한 수정으로 인한 버그 발생 확률이 높아지기 때문에 시스템 변경에 취약해질 수 밖에 없다.</li>\n</ul>\n<h4 id=\"-비즈니스-로직과-사용자-인터페이스의-결합\" style=\"position:relative;\"><a href=\"#-%EB%B9%84%EC%A6%88%EB%8B%88%EC%8A%A4-%EB%A1%9C%EC%A7%81%EA%B3%BC-%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EC%9D%98-%EA%B2%B0%ED%95%A9\" aria-label=\" 비즈니스 로직과 사용자 인터페이스의 결합 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠 비즈니스 로직과 사용자 인터페이스의 결합</h4>\n<ul>\n<li>비즈니스 로직을 설계하는 초기 단계부터 입력 방법과 출력 양식을 함께 고민하도록 강요</li>\n<li>코드 안에서 비즈니스 로직과 사용자 인터페이스 로직이 밀접하게 결합\n<ul>\n<li>사용자 인터페이스가 변경되는 빈번도 ⏫</li>\n<li>비즈니스 로직이 변경되는 빈번도 ⏬</li>\n<li>사용자 인터페이스가 변경되는 경우 비즈니스 로직까지 변경에 영향을 받음</li>\n<li>근본적으로 변경에 불안정한 아키텍처를 낳는다.</li>\n</ul>\n</li>\n<li>하향식 접근법은 기능을 분해하는 과정에서 사용자 인터페이스의 관심사와 비즈니스 로직의 관심사를 동시에 고려하도록 강요하기 때문에 \"관심사의 분리\"라는 아키텍처 설계의 목적을 달성하기 어렵다.</li>\n</ul>\n<h4 id=\"-성급하게-결정된-실행-순서\" style=\"position:relative;\"><a href=\"#-%EC%84%B1%EA%B8%89%ED%95%98%EA%B2%8C-%EA%B2%B0%EC%A0%95%EB%90%9C-%EC%8B%A4%ED%96%89-%EC%88%9C%EC%84%9C\" aria-label=\" 성급하게 결정된 실행 순서 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠 성급하게 결정된 실행 순서</h4>\n<ul>\n<li>하향식 기능 분해는 설계를 시작하는 시점에서 시스템이 무엇(what)을 해야 하는지가 아니라 어떻게(how) 동작해야 하는지에 집중하도록 만든다.</li>\n<li>처음부터 구현을 염두에 두기 때문에 함수들의 실행 순서를 정의하는 시간 제약을 강조</li>\n<li>중앙집중 제어 스타일의 형태를 띈다.</li>\n<li>하향식 접근법을 통해 분해한 함수들은 재사용이 어렵다.</li>\n</ul>\n<p>하향식 설계와 관련된 모든 문제의 원인은 <strong>결합도</strong> ❗️</p>\n<ul>\n<li>전체 시스템의 핵심적인 구조를 결정하는 함수들이 데이터와 강하게 결합된다는 것</li>\n</ul>\n<h4 id=\"-데이터-변경으로-인한-파급효과\" style=\"position:relative;\"><a href=\"#-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B3%80%EA%B2%BD%EC%9C%BC%EB%A1%9C-%EC%9D%B8%ED%95%9C-%ED%8C%8C%EA%B8%89%ED%9A%A8%EA%B3%BC\" aria-label=\" 데이터 변경으로 인한 파급효과 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠 데이터 변경으로 인한 파급효과</h4>\n<ul>\n<li>하향식 기능 분해의 가장 큰 문제점은 어떤 데이터를 어떤 함수가 사용하고 있는지를 추적하기 어렵다는 것이다.\n<ul>\n<li>데이터 변경으로 인해 어떤 함수가 영향을 받을지 예상하기 어렵다.</li>\n</ul>\n</li>\n</ul>\n<p>정규 직원의 급여뿐만 아니라 아르바이트 직원에 대한 급여도 관리를 할 수 있도록 해달라는 변경 요청이 왔다고 가정</p>\n<ul>\n<li>아르바이트 직원은 시간에 시급을 곱한 금액만큼을 지급</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">$employees = [&quot;직원A&quot;, &quot;직원B&quot;, &quot;직원C&quot;, &quot;아르바이트D&quot;, &quot;아르바이트E&quot;, &quot;아르바이트F&quot;]\n$basePays = [400, 300, 250, 1, 1, 1.5]\n$hourlys = [false, false, false, true, true, true]\n$timeCards = [0, 0, 0, 120, 120, 120]</code>\n        </deckgo-highlight-code>\n<ul>\n<li>hourlys: true: 아르바이트, false: 정규직원</li>\n<li>timeCards: 한달 간의 업무 누적 시간</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def calculateHourlyPayFor(name, taxRate)\n  index = $imployees.index(name)\n  basePay = $basePays[index] * $timeCards[index]\n  return basePay - (basePay * taxRate)\nend</code>\n        </deckgo-highlight-code>\n<ul>\n<li>아르바이트 직원의 급여를 계산하는 함수</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def hourly?(name)\n  return $hourlys[$employees.index(name)]\nend</code>\n        </deckgo-highlight-code>\n<ul>\n<li>정규직원과 아르바이트 직원을 판단하는 함수</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def calculatePay(name)\n  taxRate = getTaxRate()\n  if (hourly?(name)) then\n    pay = calculateHourlyPayFor(name, taxRate)\n  else\n    pay = calculatePayFor(name, taxRate)\n  end\n  puts(describeResult(name, pay))\nend</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def sumOfBasePays()\n  result = 0\n  for name in $employees\n    if (not hourly?(name)) then\n      result += $basePays[$employees.index(name)]\n    end\n  end\n  puts(result)\nend</code>\n        </deckgo-highlight-code>\n<p>이처럼 데이터 변경으로 인해 발생하는 함수에 대한 영향도를 파악하는 것이 쉽지 않다.</p>\n<ul>\n<li>변경에 대한 영향을 최소화하기 위해 영향을 받는 부분과 받지 않는 부분을 명확하게 분리하고 잘 정의된 퍼블릭 인터페이스를 통해 변경되는 부분에 대한 접근을 통제하는 것이 의존성 관리의 핵심이다.</li>\n</ul>\n<h3 id=\"-725-언제-하향식-분해가-유용한가\" style=\"position:relative;\"><a href=\"#-725-%EC%96%B8%EC%A0%9C-%ED%95%98%ED%96%A5%EC%8B%9D-%EB%B6%84%ED%95%B4%EA%B0%80-%EC%9C%A0%EC%9A%A9%ED%95%9C%EA%B0%80\" aria-label=\" 725 언제 하향식 분해가 유용한가 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.2.5 언제 하향식 분해가 유용한가?</h3>\n<p>하향식 설계는 설계가 어느 정도 안정화 된 후에는 설계의 다양한 측면을 논리적으로 설명하고 문서화하기에 용이하다.</p>\n<blockquote>\n<p>하향식은 이미 완전히 이해된 사실을 서술하기에 적합한 방법이다.</p>\n</blockquote>\n<ul>\n<li>하향식 분해는 작은 프로그램과 개별 알고리즘을 위해서는 유용하다.</li>\n<li>이미 해결된 알고리즘을 문서화하고 서술하는 데 유용하다.</li>\n</ul>\n<h2 id=\"-73-모듈\" style=\"position:relative;\"><a href=\"#-73-%EB%AA%A8%EB%93%88\" aria-label=\" 73 모듈 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.3 모듈</h2>\n<h3 id=\"-731-정보-은닉과-모듈\" style=\"position:relative;\"><a href=\"#-731-%EC%A0%95%EB%B3%B4-%EC%9D%80%EB%8B%89%EA%B3%BC-%EB%AA%A8%EB%93%88\" aria-label=\" 731 정보 은닉과 모듈 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.3.1 정보 은닉과 모듈</h3>\n<p><strong>정보 은닉</strong>은 시스템을 모듈 단위로 분해하기 위한 기본 원리로 시스템에서 자주 변경되는 부분을 상대적으로 덜 변경되는 안정적인 인터페이스 뒤로 감춰야 한다는 것이 핵심이다.</p>\n<blockquote>\n<p>모듈은 서브 프로그램이라기보다는 책임의 할당이다.</p>\n</blockquote>\n<ul>\n<li>기능 분해는 하나의 기능을 구현하기 위해 필요한 기능들을 순차적으로 찾아가는 탐색의 과정</li>\n<li>모듈 분해는 감춰야 하는 비밀을 선택하고 비밀 주변에 안정적인 보호막을 설치하는 보존의 과정</li>\n</ul>\n<p>모듈이 감춰야 할 비밀</p>\n<ol>\n<li>복잡성</li>\n<li>변경 가능성</li>\n</ol>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">module Employees\n  $employees = [&quot;직원A&quot;, &quot;직원B&quot;, &quot;직원C&quot;, &quot;아르바이트D&quot;, &quot;아르바이트E&quot;, &quot;아르바이트F&quot;]\n  $basePays = [400, 300, 250, 1, 1, 1.5]\n  $hourlys = [false, false, false, true, true, true]\n  $timeCards = [0, 0, 0, 120, 120, 120]\n\n  def Employees.calculatePay(name, taxRate)\n    if (Employees.hourly?(name)) then\n      pay = calculateHourlyPayFor(name, taxRate)\n    else\n      pay = calculatePayFor(name, taxRate)\n    end\n  end\n\n  def Employees.hourly?(name)\n    return $hourlys[$employees.index(name)]\n  end\n\n  def Employees.calculateHourlyPayFor(name, taxRate)\n    index = $imployees.index(name)\n    basePay = $basePays[index] * $timeCards[index]\n    return basePay - (basePay * taxRate)\n  end\n\n  def Employees.calculatePayFor(name, taxRate)\n    return basePay - (basePay * taxRate)\n  end\n\n  def Employees.sumOfBasePays()\n    result = 0\n    for name in $employees\n      if (not Employees.hourly?(name)) then\n        result += $basePays[$employees.index(name)]\n      end\n    end\n    return result\n  end</code>\n        </deckgo-highlight-code>\n<ul>\n<li>ruby 언어는 <code>module</code>이라는 키워드를 제공하지만 모듈은 키워드의 지원 여부와 상관없이 적용할 수 있는 논리적인 개념이다.</li>\n<li>모듈 외부에서는 모듈 내부에 어떤 데이터가 존재하는지 알 수 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def main(operation, args={})\n  case(operation)\n  when :pay then calculatePay(args[:name])\n  when :basePays then sumOfBasePays()\n  end\nend\n\ndef calculatePay(name)\n  taxRate = getTaxRate()\n  pay = Employees.calculatePayFor(name, taxRate)\n  puts(describeResult(name, pay))\nend\n\ndef getTaxRate()\n  print(&quot;세율을 입력하세요: &quot;)\n  return gets().chomp().to_f()\nend\n\ndef describeResult(name, pay)\n  return &quot;이름: #{name}, 급여: #{pay}&quot;\nend\n\ndef sumOfBasePays()\n  puts(Employees.sumOfBasePays())\nend</code>\n        </deckgo-highlight-code>\n<h3 id=\"-732-모듈의-장점과-한계\" style=\"position:relative;\"><a href=\"#-732-%EB%AA%A8%EB%93%88%EC%9D%98-%EC%9E%A5%EC%A0%90%EA%B3%BC-%ED%95%9C%EA%B3%84\" aria-label=\" 732 모듈의 장점과 한계 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.3.2 모듈의 장점과 한계</h3>\n<p>모듈의 장점</p>\n<ul>\n<li>모듈 내부의 변수가 변경되더라도 모듈 내부에만 영향을 미친다.\n<ul>\n<li>데이터 변경으로 인한 파급효과를 제어할 수 있으므로 코드를 수정하고 디버깅이 용이</li>\n</ul>\n</li>\n<li>비즈니스 로직과 사용자 인터페이스에 대한 관심사를 분리한다.\n<ul>\n<li>사용자 인터페이스가 변경되어도 비즈니스 로직은 변경되지 않는다.</li>\n</ul>\n</li>\n<li>전역 변수와 전역 함수를 제거함으로써 네임스페이스 오염을 방지한다.\n<ul>\n<li>모듈은 네임스페이스를 제공</li>\n<li>이름 충돌의 위험 방지</li>\n</ul>\n</li>\n</ul>\n<p>모듈은 기능이 아니라 변경의 정도에 따라 시스템을 분해하게 한다.</p>\n<ul>\n<li>높은 응집도\n<ul>\n<li>비밀과 관련성 높은 데이터의 집합</li>\n</ul>\n</li>\n<li>낮은 결합도\n<ul>\n<li>모듈과 모듈은 퍼블릭 인터페이스를 통해서만 통신</li>\n</ul>\n</li>\n</ul>\n<p>모듈은 데이터와 함수가 통합된 한 차원 높은 추상화를 제공하는 설계 단위이다 ❗️</p>\n<p>모듈의 가장 큰 단점은 인스턴스의 개념을 제공하지 않는다는 점이다. 다수의 직원 인스턴스가 존재하는 추상화 메커니즘이 추상 데이터 타입이다.</p>\n<h2 id=\"-74-데이터-추상화와-추상-데이터-타입\" style=\"position:relative;\"><a href=\"#-74-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%B6%94%EC%83%81%ED%99%94%EC%99%80-%EC%B6%94%EC%83%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85\" aria-label=\" 74 데이터 추상화와 추상 데이터 타입 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.4 데이터 추상화와 추상 데이터 타입</h2>\n<h3 id=\"-741-추상-데이터-타입\" style=\"position:relative;\"><a href=\"#-741-%EC%B6%94%EC%83%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85\" aria-label=\" 741 추상 데이터 타입 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.4.1 추상 데이터 타입</h3>\n<p>프로그래밍 언어에서 <strong>타입(type)</strong> 이란 변수에 저장할 수 있는 내용물의 종류와 변수에 적용될 수 있는 연산의 가짓수를 의미한다.</p>\n<p>추상 데이터 타입을 구현하려면 다음과 같은 특성을 위한 프로그래밍 언어의 지원이 필요하다.</p>\n<ul>\n<li>타입 정의를 선언할 수 있어야 한다.</li>\n<li>타입의 인스턴스를 다루기 위해 사용할 수 있는 오퍼레이션의 집합을 정의할 수 있어야 한다.</li>\n<li>제공된 오퍼레이션을 통해서만 조작할 수 있도록 데이터를 외부로부터 보호할 수 있어야 한다.</li>\n<li>타입에 대해 여러 개의 인스턴스를 생성할 수 있어야 한다.</li>\n</ul>\n<p>리스코프는 추상 데이터 타입을 정의하기 위해 제시한 언어적인 메커니즘을 오퍼레이션 클러스터라고 불렀다.</p>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">Employee = Struct.new(:name, :basePay, :hourly, :timeCard) do\nEnd</code>\n        </deckgo-highlight-code>\n<ul>\n<li>개별 직원을 위한 추상 데이터 타입</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">Employee = Struct.new(:name, :basePay, :hourly, :timeCard) do\n  def calculatePay(taxRate)\n    if (hourly) then\n      return calculateHourlyPayFor(taxRate)\n    end\n    return calculateSalariedFor(taxRate)\n  end\n\nprivate\n  def calculateHourlyPayFor(taxRate)\n    return (basePay * timeCard) - (basePay * timeCard) * taxRate\n  end\n\n  def calculateSalariedFor(taxRate)\n    return basePay - (basePay * taxRate)\n  end\nend</code>\n        </deckgo-highlight-code>\n<ul>\n<li>직원을 지정하지 않아도 된다.</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">Employee = Struct.new(:name, :basePay, :hourly, :timeCard) do\n  def monthlyBasePay()\n    if (hourly) then return 0 end\n    return basePay\n  end\nend</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">$employees = [\n    Employee.new(&quot;직원A&quot;, 400, false, 0),\n    Employee.new(&quot;직원B&quot;, 300, false, 0),\n    Employee.new(&quot;직원C&quot;, 200, false, 0),\n    Employee.new(&quot;아르바이트D&quot;, 1, true, 120),\n    Employee.new(&quot;아르바이트E&quot;, 1, true, 120),\n    Employee.new(&quot;아르바이트F&quot;, 1, true, 120),\n]</code>\n        </deckgo-highlight-code>\n<ul>\n<li>직원들의 인스턴스</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def calculatePay(name)\n  taxRate = getTaxRate()\n  for each in $employees\n    if (each.name === name) then employee = each; break end\n  end\n  pay = employee. calculatePay(taxRate)\n  puts(describeResult(name, pay))\nend</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def sumOfBasePays()\n  result = 0\n  for each in $employees\n    result += each.monthlyBasePay()\n  end\n  puts(result)\nend</code>\n        </deckgo-highlight-code>\n<ul>\n<li>추상 데이터 타입은 사람들이 세상을 바라보는 방식에 좀 더 근접해지도록 추상화 수준을 향상시킨다.</li>\n<li>여전히 데이터와 기능을 분리해서 바라본다.</li>\n<li>추상 데이터 타입은 말 그대로 시스템의 상태를 저장할 데이터를 표현한다.</li>\n</ul>\n<p>추상 데이터 타입의 기본 의도는 프로그래밍 언어가 제공하는 타입처럼 동작하는 사용자 정의 타입을 추가할 수 있게 하는 것</p>\n<h2 id=\"-75-클래스\" style=\"position:relative;\"><a href=\"#-75-%ED%81%B4%EB%9E%98%EC%8A%A4\" aria-label=\" 75 클래스 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 7.5 클래스</h2>\n<h3 id=\"-751-클래스는-추상-데이터-타입인가\" style=\"position:relative;\"><a href=\"#-751-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%8A%94-%EC%B6%94%EC%83%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85%EC%9D%B8%EA%B0%80\" aria-label=\" 751 클래스는 추상 데이터 타입인가 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.5.1 클래스는 추상 데이터 타입인가?</h3>\n<p>클래스와 추상 데이터 타입 모두 데이터 추상화를 기반으로 시스템을 분해한다. 그러나 명확한 의미에서 추상 데이터 타입과 클래스는 동일하지 않다.</p>\n<ul>\n<li>클래스는 상속과 다형성을 지원(객체지향 프로그래밍)하지만 추상 데이터 타입은 지원하지 못한다(객체기반 프로그래밍).</li>\n</ul>\n<p>하나의 대표적인 타입이 다수의 세부적인 타입을 감추기 때문에 이를 타입 추상화라 부른다.</p>\n<ul>\n<li>Employee 타입은 직원 타입과 아르바이트 타입이 있다.</li>\n<li>타입 추상화를 기반으로 하는 대표적인 기법이 바로 추상 데이터 타입이다.</li>\n</ul>\n<p>추상 데이터 타입이 오퍼레이션을 기준으로 타입을 묶는 방법이라면 객체지향은 타입을 기준으로 오퍼레이션을 묶는다.</p>\n<ul>\n<li>클래스를 이용한 다형성은 절차에 대한 차이점을 감춘다.</li>\n<li>객체 지향은 <strong>절차 추상화</strong>다.</li>\n</ul>\n<h3 id=\"-752-추상-데이터-타입에서-클래스로-변경하기\" style=\"position:relative;\"><a href=\"#-752-%EC%B6%94%EC%83%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85%EC%97%90%EC%84%9C-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A1%9C-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0\" aria-label=\" 752 추상 데이터 타입에서 클래스로 변경하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.5.2 추상 데이터 타입에서 클래스로 변경하기</h3>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Employee\n  attr_reader :name, :basePay\n\n  def initialize(name, basePay)\n    @name = name\n    @basePay = basePay\n  end\n\n  def calculatePay(taxRate)\n    raise NotImplementedError\n  end\n\n  def monthlyBasePay()\n    raise NotImplementedError\n  end\nend</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java 기준으로 보면 <code>Employee</code> class는 추상 클래스, <code>calculatePay</code>, <code>monthlyBasePay</code>는 추상 메서드이다.</li>\n</ul>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class SalariedEmployee &lt; Employee\n  def initialize(name, basePay)\n    super(name, basePay)\n  end\n\n  def calculatePay(taxRate)\n    return basePay - (basePay * taxRate)\n  end\n\n  def monthlyBasePay()\n    return basePay\n  end\nend</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class HourlyEmployee &lt; Employee\n  attr_reader :timeCard\n  def initialize(name, basePay, timeCard)\n    super(name, basePay)\n    @timeCard = timeCard\n  end\n\n  def calculatePay(taxRate)\n    return (basePay * timeCard) - (basePay * timeCard) * taxRate\n  end\n\n  def monthlyBasePay()\n    return 0\n  end\nend</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">$employees = [\n    SalariedEmployee.new(&quot;직원A&quot;, 400),\n    SalariedEmployee.new(&quot;직원B&quot;, 300),\n    SalariedEmployee.new(&quot;직원C&quot;, 200),\n    HourlyEmployee.new(&quot;아르바이트D&quot;, 1, 120),\n    HourlyEmployee.new(&quot;아르바이트E&quot;, 1, 120),\n    HourlyEmployee.new(&quot;아르바이트F&quot;, 1, 120),\n]</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"ruby\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">def sumOfBasePays()\n  result = 0\n  for each in $employees\n    result += each.monthlyBasePay()\n  end\n  puts(result)\nend</code>\n        </deckgo-highlight-code>\n<ul>\n<li>메시지를 수신한 객체는 자신의 클래스에 구현된 메서드를 이용해 적절하게 반응할 수 있다.</li>\n</ul>\n<h3 id=\"-753-변경을-기준으로-선택하라\" style=\"position:relative;\"><a href=\"#-753-%EB%B3%80%EA%B2%BD%EC%9D%84-%EA%B8%B0%EC%A4%80%EC%9C%BC%EB%A1%9C-%EC%84%A0%ED%83%9D%ED%95%98%EB%9D%BC\" aria-label=\" 753 변경을 기준으로 선택하라 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.5.3 변경을 기준으로 선택하라</h3>\n<p>비록 클래스를 사용하고 있더라도 타입을 기준으로 절차를 추상화하지 않았다면 그것은 객체지향 분해가 아니다.</p>\n<ul>\n<li>클래스가 추상 데이터 타입의 개념을 다르는지를 확인할 수 있는 가장 간단한 방법은 클래스 내부에 인스턴스의 타입을 표현하는 변수가 있는지를 살펴보는 것</li>\n<li>객체지향에서는 타입 변수를 이용한 조건문을 다형성으로 대체</li>\n</ul>\n<p>개방-폐쇄 원칙(Open-Closed Principle, OCP)</p>\n<ul>\n<li>기존 코드에 아무런 영향도 미치지 않고 새로운 객체 유형과 행위를 추가할 수 있는 객체지향의 특성</li>\n<li>대부분의 객체지향 서적에서는 추상 데이터 타입을 기반으로 애플리케이션을 설계하는 방식을 잘못된 것으로 설명한다.\n<ul>\n<li>설계에 요구되는 변경의 압력이 '타입 추가'에 관한 것인지, 아니면 '오퍼레이션 추가'에 관한 것인지에 따라 달라진다.</li>\n<li>새로운 타입을 빈번하게 추가해야 한다면 객체지향의 클래스 구조가 더 유용</li>\n<li>새로운 오퍼레이션을 빈번하게 추가해야 한다면 추상 데이터 타입이 더 유용</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-754-협력이-중요하다\" style=\"position:relative;\"><a href=\"#-754-%ED%98%91%EB%A0%A5%EC%9D%B4-%EC%A4%91%EC%9A%94%ED%95%98%EB%8B%A4\" aria-label=\" 754 협력이 중요하다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 7.5.4 협력이 중요하다</h3>\n<p>협력이라는 문맥을 고려하지 않고 객체를 고립시킨 채 오퍼레이션의 구현 방식을 타입별로 분배하는 것은 올바른 접근법이 아니다.</p>\n<p>객체가 참여할 협력을 결정하고 협력에 필요한 책임을 수행하기 위해 어떤 객체가 필요한지에 관해 고민하라.</p>\n<ul>\n<li>그 책임을 다양한 방식으로 수행해야 할 때만 타입 계층 안에 각 절차를 추상화하라.</li>\n<li>타입 계층과 다형성은 협력이라는 문맥 안에서 책임을 수행하는 방법에 관해 고민한 결과물이어야 하며 그 자체가 목적이 되어서는 안 된다.</li>\n</ul>","excerpt":"사람의 기억은 단기 기억과 장기 기억으로 분류할 수 있다. 실제로 문제를 해결하기 위해 사용하는 저장소는 장기 기억이 아니라 단기 기억이다. 인지 과부하(cognitive overload): 문제 해결에 필요한 요소의 수가 단기 기억의 용량을 초과하는 순간 문제 해결 능력이 급격하게 떨어지는 것 인지 과부하를 줄이는 가장 좋은 방법은 단기 기억 안에 보관할 정보의 양을 조절하는 것 추상화: 불필요한 정보를 제거하고 현재의 문제 해결에 필요한 핵심만 남기는 작업 분해(decomposition…","fields":{"slug":"/backend/object/chapter7/객체_분해/"},"frontmatter":{"title":"Object - 7장 객체 분해","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/dd0e1990925e942697544e2bdcd9332e/9b73b/object.png"}}},"draft":false,"category":"Back-End","tags":["java"],"date":"October 08, 2023"}},"previous":{"id":"b14e7f9b-76a7-59bf-b641-5c48cac92a69","html":"<h2 id=\"-91-개방-폐쇄-원칙\" style=\"position:relative;\"><a href=\"#-91-%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84-%EC%9B%90%EC%B9%99\" aria-label=\" 91 개방 폐쇄 원칙 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 9.1 개방-폐쇄 원칙</h2>\n<blockquote>\n<p>소프트웨어 개체(클래스, 모듈, 함수 등등)는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다.</p>\n</blockquote>\n<ul>\n<li>확장에 대해 열려 있다: 애플리케이션의 요구사항이 변경될 때 이 변경에 맞게 새로운 '동작'을 추가해서 애플리케이션의 기능을 확장할 수 있다.</li>\n<li>수정에 대해 닫혀 있다: 기존의 '코드'를 수정하지 않고도 애플리케이션의 동작을 추가하거나 변경할 수 있다.</li>\n</ul>\n<h3 id=\"-911-컴파일타임-의존성을-고정시키고-런타임-의존성을-변경하라\" style=\"position:relative;\"><a href=\"#-911-%EC%BB%B4%ED%8C%8C%EC%9D%BC%ED%83%80%EC%9E%84-%EC%9D%98%EC%A1%B4%EC%84%B1%EC%9D%84-%EA%B3%A0%EC%A0%95%EC%8B%9C%ED%82%A4%EA%B3%A0-%EB%9F%B0%ED%83%80%EC%9E%84-%EC%9D%98%EC%A1%B4%EC%84%B1%EC%9D%84-%EB%B3%80%EA%B2%BD%ED%95%98%EB%9D%BC\" aria-label=\" 911 컴파일타임 의존성을 고정시키고 런타임 의존성을 변경하라 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 9.1.1 컴파일타임 의존성을 고정시키고 런타임 의존성을 변경하라</h3>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1114px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 29.333333333333332%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAABYlAAAWJQFJUiTwAAAA9klEQVQY013Ny27CMBCFYd7/7WikIEsE0hhiHNnO+JL4MjhTEWgX/Vaz+c8ctm1DxFIKIj6fz5xL/rVtGxHlnGNMMcZSyn7HdV0RkYgOiAgA4zgaY7TW0zRxfrter0qpUgoRzfMshJBSWmuVUm3bNk0DAK+YiEIIAOCcq7WGEB6PB+fcWltrJaIYY9jVWkvBJSwhhJzzJ35LKUkpT6eTlFJrzRjrus45573XWhtj1nX13l8ul/P5vCzL/5gxdjx+DcPrLed8GAbnHAAIIcZxFELc77fvnff+E9sUjbXTNHVdxxjr+14pBQDGmJTSe7rWaq19N39+AAmIU6iuKMtnAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"9.1\"\n        title=\"9.1\"\n        src=\"/static/c48c54664a1af80484ca8ea31a6937f8/cd536/9.1.png\"\n        srcset=\"/static/c48c54664a1af80484ca8ea31a6937f8/5a46d/9.1.png 300w,\n/static/c48c54664a1af80484ca8ea31a6937f8/0a47e/9.1.png 600w,\n/static/c48c54664a1af80484ca8ea31a6937f8/cd536/9.1.png 1114w\"\n        sizes=\"(max-width: 1114px) 100vw, 1114px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n    </span></p>\n<ul>\n<li>기존 클래스는 전혀 수정하지 않은 채 애플리케이션의 동작을 확장했다.</li>\n<li>단순히 새로운 클래스를 추가하는 것만으로 <code>Movie</code>를 새로운 컨텍스트에 사용되도록 확장할 수 있었던 것</li>\n</ul>\n<p>OCP를 수용하는 코드는 컴파일타임 의존성을 수정하지 않고도 런타임 의존성을 쉽게 변경할 수 있다. 의존성 관점에서 OCP를 따르는 설계란 컴파일타임 의존성은 유지하면서 런타임 의존성의 가능성을 확장하고 수정할 수 있는 구조라고 할 수 있다.</p>\n<h3 id=\"-912-추상화가-핵심이다\" style=\"position:relative;\"><a href=\"#-912-%EC%B6%94%EC%83%81%ED%99%94%EA%B0%80-%ED%95%B5%EC%8B%AC%EC%9D%B4%EB%8B%A4\" aria-label=\" 912 추상화가 핵심이다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 9.1.2 추상화가 핵심이다</h3>\n<p>OCP의 핵심은 <strong>추상화에 의존하는 것</strong></p>\n<ul>\n<li>추상화란 핵심적인 부분만 남기고 불필요한 부분은 생략함으로써 복잡성을 극복하는 기법</li>\n<li>OCP의 관점에서 생략되지 않고 남겨지는 부분은 다양한 상황에서의 공통점을 반영한 추상화의 결과물</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public abstract class DiscountPolicy {\n    private final List&lt;DiscountCondition&gt; conditions;\n    \n    protected DiscountPolicy(DiscountCondition... conditions) {\n        this.conditions = Arrays.asList(conditions);\n    }\n    \n    public Money calculateDiscountAmount(Screening screening) {\n        for (DiscountCondition condition : conditions) {\n            if (condition.isSatisfiedBy(screening)) {\n                return getDiscountAmount(screening);\n            }\n        }\n        return screening.getMovieFee();\n    }\n    protected abstract Money getDiscountAmount(Screening screening);\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>언제라도 추상화의 생략된 부분을 채워넣음으로써 새로운 문맥에 맞게 기능을 확장할 수 있다.</li>\n<li>OCP에서 폐쇄를 가능하게 하는 것은 의존성의 방향이다.</li>\n<li>수정에 대한 영향을 최소화하기 위해서는 모든 요소가 추상화에 의존해야 한다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@AllArgsConstructor\npublic class Movie {\n\n    private String title;\n\n    private Duration runningTime;\n\n    @Getter\n    private Money fee;\n\n    private DiscountPolicy discountPolicy;\n    \n    public Money calculateMovieFee(Screening screening) {\n        return fee.minus(discountPolicy.calculateDiscountAmount(screening));\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>Movie</code>는 안정된 추상화인 <code>DiscountPolicy</code>에 의존하기 때문에 할인 정책을 추가하기 위해 <code>DiscountPolicy</code>의 자식 클래스를 추가하더라도 영향을 받지 않는다. 따라서 수정에 대해 닫혀 있다.</li>\n</ul>\n<p>추상화를 했다고 해서 모든 수정에 대해 설계가 폐쇄되는 것은 아니다. 추상화가 수정에 대해 닫혀 있을 수 있는 이유는 변경되지 않을 부분을 신중하게 결정하고 올바른 추상화를 주의 깊게 선택했기 때문이다.</p>\n<h2 id=\"-92-생성-사용-분리\" style=\"position:relative;\"><a href=\"#-92-%EC%83%9D%EC%84%B1-%EC%82%AC%EC%9A%A9-%EB%B6%84%EB%A6%AC\" aria-label=\" 92 생성 사용 분리 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 9.2 생성 사용 분리</h2>\n<p>결합도가 높아질수록 개방-폐쇄 원칙을 따르는 구조를 설계하기가 어려워진다.</p>\n<ul>\n<li>알아야 하는 지식이 많으면 결합도도 높아진다.</li>\n<li>객체 생성에 대한 지식은 과도한 결합도를 초래하는 경향이 있다.\n<ul>\n<li>부적절한 곳에서 객체를 생성한다는 것이 문제❗️</li>\n</ul>\n</li>\n</ul>\n<p>유연하고 재사용 가능한 설계를 원한다면 <strong>객체에 대한 생성과 사용을 분리(seperating use from creation)</strong> 해야 한다.</p>\n<p>사용으로부터 생성을 분리하는 데 사용되는 가장 보편적인 방법은 <strong>객체를 생성할 책임을 클라이언트로 옮기는 것</strong></p>\n<h3 id=\"-921-factory-추가하기\" style=\"position:relative;\"><a href=\"#-921-factory-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0\" aria-label=\" 921 factory 추가하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 9.2.1 FACTORY 추가하기</h3>\n<blockquote>\n<p>생성과 사용을 분리하기 위해 객체 생성에 특화된 객체를 FACTORY라고 부른다.</p>\n</blockquote>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Factory {\n    public Movie createAvatarMovie() {\n        return new Movie(&quot;아바타&quot;, Duration.ofMinutes(120), Money.wons(10000), new AmountDiscountPolicy(...));\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@AllArgsConstructor\npublic class Client {\n    private Factory factory;\n\n    public Money getAvatarFee() {\n        Movie avatar = factory.createAvatarMovie();\n        return avatar.getFee();\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Client는 오직 사용과 관련된 책임만 지고 생성과 관련된 어떤 지식도 가지지 않을 수 있다.</li>\n</ul>\n<h3 id=\"-922-순수한-가공물에게-책임-할당하기\" style=\"position:relative;\"><a href=\"#-922-%EC%88%9C%EC%88%98%ED%95%9C-%EA%B0%80%EA%B3%B5%EB%AC%BC%EC%97%90%EA%B2%8C-%EC%B1%85%EC%9E%84-%ED%95%A0%EB%8B%B9%ED%95%98%EA%B8%B0\" aria-label=\" 922 순수한 가공물에게 책임 할당하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 9.2.2 순수한 가공물에게 책임 할당하기</h3>\n<p>도메인 모델은 Information expert를 찾기 위해 참조할 수 있는 일차적인 재료다.</p>\n<p>시스템을 객체로 분해하는 데는 크게 두 가지 방식이 존재</p>\n<ol>\n<li>\n<p>표현적 분해</p>\n<ul>\n<li>도메인에 존재하는 사물 또는 개념을 표현하는 객체들을 이용해 시스템을 분해하는 것</li>\n<li>도메인 모델에 담겨 있는 개념과 관계를 따르며 도메인과 소프트웨어 사잉의 표현적 차이를 최소화하는 것을 목적으로 함.</li>\n</ul>\n</li>\n<li>\n<p>행위적 분해</p>\n<ul>\n<li>순수한 가공물(pure fabrication): 책임을 할당하기 위해 창조되는 도메인과 무관한 인공적인 객체</li>\n</ul>\n</li>\n</ol>\n<p>도메인 개념이 만족스럽지 못하다면 주저하지 말고 인공적인 객체를 창조하라. 객체지향이 실세계의 모방이라는 말은 옳지 않다.</p>\n<h2 id=\"-93-의존성-주입\" style=\"position:relative;\"><a href=\"#-93-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%A3%BC%EC%9E%85\" aria-label=\" 93 의존성 주입 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 9.3 의존성 주입</h2>\n<p>의존성 주입: 사용하는 객체가 아닌 외부의 독립적인 객체가 인스턴스를 생성한 후 이를 전달해서 의존성을 해결하는 방법</p>\n<ul>\n<li>생성자 주입: 객체를 생성하는 시점에 생성자를 통한 의존성 해결</li>\n<li>setter 주입: 객체 생성 후 setter 메서드를 통한 의존성 해결</li>\n<li>메서드 주입: 메서드 실행 시 인자를 이용한 의존성 해결</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">Movie avatar = new Movie(&quot;아바타&quot;, Duration.ofMinutes(120), Money.wons(10000), new AmountDiscountPolicy(...));</code>\n        </deckgo-highlight-code>\n<ul>\n<li>생성자 주입</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">avatar.setDiscountPolicy(new AmountDiscountPolicy(...));</code>\n        </deckgo-highlight-code>\n<ul>\n<li>setter 주입</li>\n<li>장점: 언제라도 의존 대상을 교체할 수 있다.</li>\n<li>단점: 객체가 올바로 생성되기 위해 어떤 의존성이 필수적인지를 명시적으로 표현할 수 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">avatar.calculateDiscountAmount(screening, new AmountDiscountPolicy(...));</code>\n        </deckgo-highlight-code>\n<ul>\n<li>메서드 주입(메서드 호출 주입)</li>\n<li>메서드가 의존성을 필요로하는 유일한 경우일 때 사용할 수 있다.</li>\n</ul>\n<h3 id=\"-931-숨겨진-의존성은-나쁘다\" style=\"position:relative;\"><a href=\"#-931-%EC%88%A8%EA%B2%A8%EC%A7%84-%EC%9D%98%EC%A1%B4%EC%84%B1%EC%9D%80-%EB%82%98%EC%81%98%EB%8B%A4\" aria-label=\" 931 숨겨진 의존성은 나쁘다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 9.3.1 숨겨진 의존성은 나쁘다</h3>\n<p>Service Locator 패턴</p>\n<ul>\n<li>의존성을 해결할 수 있는 방법</li>\n<li>Service Locator는 의존성을 해결할 객체들을 보관하는 일종의 저장소</li>\n<li>객체가 직접 Service Locator에게 의존성을 해결해줄 것을 요청</li>\n<li>서비스를 사용하는 코드로부터 서비스가 누구인지(서비스를 구현한 구체 클래스의 타입이 무엇인지), 어디에 있는지(클래스 인스턴스를 어떻게 얻을지)를 몰라도 되게 해준다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@NoArgsConstructor(access = AccessLevel.PRIVATE)\npublic class ServiceLocator {\n    \n    private static final ServiceLocator soleInstance = new ServiceLocator();\n    private DiscountPolicy discountPolicy;\n    \n    public static DiscountPolicy discountPolicy() {\n        return soleInstance.discountPolicy;\n    }\n    \n    public static void provide(DiscountPolicy discountPolicy) {\n        soleInstance.discountPolicy = discountPolicy;\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">ServiceLocator.provide(new AmountDiscountPolicy(...));\nMovie avatar = new Movie(&quot;아바타&quot;, Duration.ofMinutes(120), Money.wons(10000));</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위 패턴의 가장 큰 단점은 의존성을 감춘다는 것</li>\n</ul>\n<p>의존성을 구현 내부로 감출 경우</p>\n<ul>\n<li>의존성과 관련된 문제가 컴파일타임이 아닌 런타임에 가서야 발견된다.</li>\n<li>단위 테스트 작성이 어렵다.\n<ul>\n<li>각 단위 테스트는 서로 고립돼야 한다는 기본 원칙 위반</li>\n</ul>\n</li>\n<li>의존성을 이해하기 위해 코드의 내부 구현을 이해할 것을 강요한다.</li>\n<li>의존성의 대상을 설정하는 시점과 의존성이 해결되는 시점을 멀리 떨어트려 놓는다.\n<ul>\n<li>코드를 이해하고 디버깅하기 어렵게 만든다.</li>\n</ul>\n</li>\n</ul>\n<p>의존성 주입을 지원하는 프레임워크를 사용하지 못하는 경우나 깊은 호출 계층에 걸쳐 동일한 객체를 계속해서 전달해야 하는 고통을 견디기 어려운 경우에는 어쩔 수 없이 Service Locator 패턴을 사용하는 것을 고려하라.</p>\n<h2 id=\"-94-의존성-역전-원칙\" style=\"position:relative;\"><a href=\"#-94-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%97%AD%EC%A0%84-%EC%9B%90%EC%B9%99\" aria-label=\" 94 의존성 역전 원칙 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 9.4 의존성 역전 원칙</h2>\n<h3 id=\"-941-추상화와-의존성-역전\" style=\"position:relative;\"><a href=\"#-941-%EC%B6%94%EC%83%81%ED%99%94%EC%99%80-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%97%AD%EC%A0%84\" aria-label=\" 941 추상화와 의존성 역전 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 9.4.1 추상화와 의존성 역전</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Movie {\n    private AmountDiscountPolicy discountPolicy;\n}</code>\n        </deckgo-highlight-code>\n<p>의존성은 변경의 전파와 관련된 것이기 때문에 설계는 변경의 영향을 최소화하도록 의존성을 관리해야 한다.</p>\n<ul>\n<li>상위 수준의 클래스는 어떤 식으로든 하위 수준의 클래스에 의존해서는 안 된다.</li>\n<li>대부분의 경우 우리가 재사용하려는 대상은 상위 수준의 클래스다.</li>\n</ul>\n<p>가장 중요한 것은 추상화에 의존하는 것이다.</p>\n<ul>\n<li>모든 의존성의 방향이 추상 클래스나 인터페이스와 같은 추상화를 따라야 한다.</li>\n</ul>\n<p>의존성 역전 원칙(Dependency Inversion Principle, DIP)</p>\n<ol>\n<li>상위 수준의 모듈은 하위 수준의 모듈에 의존해서는 안 된다. 둘 모두 추상화에 의존해야 한다.</li>\n<li>추상화는 구체적인 사항에 의존해서는 안 된다. 구체적인 사항은 추상화에 의존해야 한다.</li>\n<li>역전이라는 단어를 사용한 이유는 DIP를 따르는 설계는 의존성의 방향이 전통적인 절차형 프로그래밍과는 반대 방향으로 나타나기 때문</li>\n</ol>\n<h3 id=\"-942-의존성-역전-원칙과-패키지\" style=\"position:relative;\"><a href=\"#-942-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%97%AD%EC%A0%84-%EC%9B%90%EC%B9%99%EA%B3%BC-%ED%8C%A8%ED%82%A4%EC%A7%80\" aria-label=\" 942 의존성 역전 원칙과 패키지 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 9.4.2 의존성 역전 원칙과 패키지</h3>\n<p>역전은 의존성의 방향뿐만 아니라 인터페이스의 소유권에도 적용된다.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1025px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 37%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAABYlAAAWJQFJUiTwAAAA6klEQVQY032Qy26EMAxF5/9/jAVrBKzI8BCjOBmKwUlISNyKzFStKvUsLMvysax744vzPLXW6oKIEHFZlufF/oaInLNEFELI1u1bRsSPN8MwrOtKRFJKpVTf9wCAiCmlfIiZU0ovOaUEAEKI+70fhkFr7b1nZiICkF3XAUB2iMy+0y+ZmUMI3vtw4S/yPMbonM3bzGyMIfoj/+Q8T2MMInZdJ6UEACmlEGLbNkQ0xvwnxxi11lVVFUXRtu00TU3TlGVZ1/U8P6x1L9kEDxs+tc4JK6VyHcdxnmdr7XEc1lrnXAgh9/n/r7Q/AR3lkPPrF582AAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"9.9\"\n        title=\"9.9\"\n        src=\"/static/ee458d231b0407087aa63239dee7bd94/d0143/9.9.png\"\n        srcset=\"/static/ee458d231b0407087aa63239dee7bd94/5a46d/9.9.png 300w,\n/static/ee458d231b0407087aa63239dee7bd94/0a47e/9.9.png 600w,\n/static/ee458d231b0407087aa63239dee7bd94/d0143/9.9.png 1025w\"\n        sizes=\"(max-width: 1025px) 100vw, 1025px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n        decoding=\"async\"\n      />\n    </span></p>\n<ul>\n<li><code>Movie</code>를 다양한 컨텍스트에서 재사용하기 위해서는 불필요한 클래스들이 <code>Movie</code>와 함께 배포해야한 한다.</li>\n<li>불필요한 클래스들을 같은 패키지에 두는 것은 전체적인 빌드 시간을 가파르게 상승시킨다.</li>\n</ul>\n<p>Separated interface 패턴</p>\n<ul>\n<li>추상화를 별도의 독립적인 패키지가 아니라 클라이언트가 속한 패키지에 포함시켜야 한다.</li>\n<li>함게 재사용될 필요가 없는 클래스들은 별도의 독립적인 패키지에 모아햐 한다.</li>\n</ul>\n<p>의존성 역전 원칙에 따라 상위 수준의 협력 흐름을 재사용하기 위해서는 추상화가 제공하는 인터페이스의 소유권 역시 역전시켜야 한다.</p>\n<h2 id=\"-95-유연성에-대한-조언\" style=\"position:relative;\"><a href=\"#-95-%EC%9C%A0%EC%97%B0%EC%84%B1%EC%97%90-%EB%8C%80%ED%95%9C-%EC%A1%B0%EC%96%B8\" aria-label=\" 95 유연성에 대한 조언 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 9.5 유연성에 대한 조언</h2>\n<h3 id=\"-951-유연한-설계는-유연성이-필요할-때만-옳다\" style=\"position:relative;\"><a href=\"#-951-%EC%9C%A0%EC%97%B0%ED%95%9C-%EC%84%A4%EA%B3%84%EB%8A%94-%EC%9C%A0%EC%97%B0%EC%84%B1%EC%9D%B4-%ED%95%84%EC%9A%94%ED%95%A0-%EB%95%8C%EB%A7%8C-%EC%98%B3%EB%8B%A4\" aria-label=\" 951 유연한 설계는 유연성이 필요할 때만 옳다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 9.5.1 유연한 설계는 유연성이 필요할 때만 옳다</h3>\n<p>유연하고 재사용 가능한 설계가 항상 좋은 것은 아니다.</p>\n<ul>\n<li>설계의 미덕은 단순함과 명확함으로부터 나온다.</li>\n<li>아직 일어나지 않은 변경은 변경이 아니다.</li>\n<li>유연성은 항상 복잡성을 수반한다.</li>\n<li>불필요한 유연성은 불필요한 복잡성을 낳는다.</li>\n</ul>\n<p>복잡성에 대한 걱정보다 유연하고 재사용 가능한 설계의 필요성이 더 크다면 코드의 구조와 실행 구조를 다르게 만들어라.</p>\n<h3 id=\"-952-협력과-책임이-중요하다\" style=\"position:relative;\"><a href=\"#-952-%ED%98%91%EB%A0%A5%EA%B3%BC-%EC%B1%85%EC%9E%84%EC%9D%B4-%EC%A4%91%EC%9A%94%ED%95%98%EB%8B%A4\" aria-label=\" 952 협력과 책임이 중요하다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 9.5.2 협력과 책임이 중요하다</h3>\n<p>설계를 유연하게 만들기 위해서는 먼저 역할, 책임, 협력에 초점을 맞춰야 한다.</p>\n<ul>\n<li>다양한 컨텍스트에서 협력을 재사용할 필요가 없다면 설계를 유연하게 만들 당위성도 함께 사라진다.</li>\n<li>객체들이 메시지 전송자의 관점에서 동일한 책임을 수행하는지 여부를 판단할 수 없다면 공통의 추상화를 도출할 수 없다.</li>\n<li>동일한 역할을 통해 객체들을 대체 가능하게 만들지 않았다면 협력에 참여하는 객체들을 교체할 필요가 없다.</li>\n<li>중요한 비즈니스 로직을 처리하기 위해 책임을 할당하고 협력의 균형을 맞추는 것이 객체 생성에 관한 책임을 할당하는 것보다 우선이다.</li>\n</ul>\n<p>불필요한 Singleton 패턴은 객체 생성에 관해 너무 이른 시기에 고민하고 결정할 때 도입되는 경향이 있다.</p>\n<p>이번 장에서 설명한 다양한 기법들을 적용하기 전에 역할, 책임, 협력의 모습이 선명하게 그려지지 않는다면 의존성을 관리하는 데 들이는 모든 노력이 물거품이 될 수도 있다는 사실을 명심하라.</p>","excerpt":"📖 9.1 개방-폐쇄 원칙 소프트웨어 개체(클래스, 모듈, 함수 등등)는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다. 확장에 대해 열려 있다: 애플리케이션의 요구사항이 변경될 때 이 변경에 맞게 새로운 '동작'을 추가해서 애플리케이션의 기능을 확장할 수 있다. 수정에 대해 닫혀 있다: 기존의 '코드'를 수정하지 않고도 애플리케이션의 동작을 추가하거나 변경할 수 있다. 🔖 9.1.…","fields":{"slug":"/backend/object/chapter9/유연한_설계/"},"frontmatter":{"title":"Object - 9장 유연한 설계","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/dd0e1990925e942697544e2bdcd9332e/9b73b/object.png"}}},"draft":false,"category":"Back-End","tags":["java"],"date":"October 22, 2023"}},"node":{"id":"7df70221-cf06-58ea-9288-34d2e832195f","html":"<p>협력은 필수적이지만 과도한 협력은 설계를 곤경에 빠트릴 수 있다. 협력을 위해서는 의존성이 필요하지만 과도한 의존성은 애플리케이션을 수정하기 어렵게 만든다.</p>\n<p>객체지향 설계의 핵심은 협력을 위해 필요한 의존성은 유지하면서도 변경을 방해하는 의존성은 제거하는데 있다. 이런 관점에서 객체지향 설계란 의존성을 관리하는 것이고 객체가 변화를 받아들일 수 있게 의존성을 정리하는 기술이라고 할 수 있다.</p>\n<h2 id=\"-81-의존성-이해하기\" style=\"position:relative;\"><a href=\"#-81-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0\" aria-label=\" 81 의존성 이해하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 8.1 의존성 이해하기</h2>\n<h3 id=\"-811-변경과-의존성\" style=\"position:relative;\"><a href=\"#-811-%EB%B3%80%EA%B2%BD%EA%B3%BC-%EC%9D%98%EC%A1%B4%EC%84%B1\" aria-label=\" 811 변경과 의존성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.1 변경과 의존성</h3>\n<p>어떤 객체가 협력하기 위해 다른 객체를 필요로 할 때 두 객체 사이에 의존성이 존재하게 된다. 의존성은 실행 시점과 구현 시점에 서로 다른 의미를 가진다.</p>\n<ul>\n<li>실행 시점: 의존하는 객체가 정상적으로 동작하기 위해서는 실행 시에 의존 대상 객체가 반드시 존재해야 한다.</li>\n<li>구현 시점: 의존 대상 객체가 변경될 경우 의존하는 객체도 함께 변경된다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@AllArgsConstructor\npublic class PeriodCondition implements DiscountCondition {\n\n    private DayOfWeek dayOfWeek;\n    private LocalTime startTime;\n    private LocalTime endTime;\n\n    @Override\n    public boolean isSatisfiedBy(Screening screening) {\n        return screening.getStartTime().getDayOfWeek().equals(dayOfWeek) &amp;&amp;\n                !startTime.isAfter(screening.getStartTime().toLocalTime()) &amp;&amp;\n                !endTime.isBefore(screening.getStartTime().toLocalTime());\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>실행 시점에 <code>PeriodCondition</code>의 인스턴스가 정상적으로 동작하기 위해서는 <code>Screening</code>의 인스턴스가 존재해야 한다.</li>\n</ul>\n<p>이처럼 어떤 객체가 예정된 작업을 정상적으로 수행하기 위해 다른 객체를 필요로 하는 경우 두 객체 사이에 의존성이 존재한다고 말한다.</p>\n<ul>\n<li>의존성은 방향성을 가지며 항상 단방향이다.</li>\n<li>두 요소 사이의 의존성은 의존되는 요소가 변경될 때 의존하는 요소도 함께 변경될 수 있다는 것을 의미\n<ul>\n<li>의존성은 변경에 의한 영향의 전파 가능성을 암시</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-812-의존성-전이\" style=\"position:relative;\"><a href=\"#-812-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%A0%84%EC%9D%B4\" aria-label=\" 812 의존성 전이 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.2 의존성 전이</h3>\n<ul>\n<li>의존성은 함께 변경될 수 있는 <em>가능성</em>을 의미하기 때문에 모든 경우에 의존성이 전이되는 것은 아니다.</li>\n<li>의존성이 실제로 전이될지 여부는 변경의 방향과 캡슐화의 정도에 따라 달라진다.</li>\n<li>의존성 전이는 변경에 의해 영향이 널리 전파될 수도 있다는 경고일 뿐이다.</li>\n</ul>\n<p>직접 의존성</p>\n<ul>\n<li>한 요소가 다른 요소에 직접 의존하는 경우</li>\n<li><code>PeriodCondition</code>이 <code>Screening</code>에 직접 의존하는 경우</li>\n</ul>\n<p>간접 의존성</p>\n<ul>\n<li>직접적인 관계는 존재하지 않지만 의존성 전이에 의해 영향이 전파되는 경우</li>\n</ul>\n<h3 id=\"-813-런타임-의존성과-컴파일타임-의존성\" style=\"position:relative;\"><a href=\"#-813-%EB%9F%B0%ED%83%80%EC%9E%84-%EC%9D%98%EC%A1%B4%EC%84%B1%EA%B3%BC-%EC%BB%B4%ED%8C%8C%EC%9D%BC%ED%83%80%EC%9E%84-%EC%9D%98%EC%A1%B4%EC%84%B1\" aria-label=\" 813 런타임 의존성과 컴파일타임 의존성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.3 런타임 의존성과 컴파일타임 의존성</h3>\n<p>런타임 의존성</p>\n<ul>\n<li>런타임: 애플리케이션이 실행되는 시점</li>\n<li>객체 사이의 의존성</li>\n</ul>\n<p>컴파일타임 의존성</p>\n<ul>\n<li>컴파일타임: 코드를 컴파일하는 시점, 문맥에 따라서는 코드 그 자체</li>\n<li>클래스 사이의 의존성</li>\n</ul>\n<p>유연하고 재사용 가능한 설계를 창조하기 위해서는 동일한 소스코드 구조를 가지고 다양한 실행 구조를 만들 수 있어야 한다.</p>\n<ul>\n<li>어떤 클래스의 인스턴스가 다양한 클래스의 인스턴스와 협력하기 위해서는 협력할 인스턴스의 구체적인 클래스를 알아서는 안 된다.</li>\n</ul>\n<h3 id=\"-814-컨텍스트-독립성\" style=\"position:relative;\"><a href=\"#-814-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%EB%8F%85%EB%A6%BD%EC%84%B1\" aria-label=\" 814 컨텍스트 독립성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.4 컨텍스트 독립성</h3>\n<ul>\n<li>클래스가 사용될 특정한 문맥에 대해 최소한의 가정만으로 이뤄져 있다면 다른 문맥에서 재사용하기가 더 수월해진다.</li>\n<li>가능한 한 자신이 실행될 컨텍스트에 대한 구체적인 정보를 최대한 적게 알아야 한다.\n<ul>\n<li>더 다양한 컨텍스트에서 재사용될 수 있기 때문</li>\n</ul>\n</li>\n</ul>\n<blockquote>\n<p>시스템을 구성하는 객체가 컨텍스트 독립적이라면 해당 시스템은 변경하기 쉽다.\n여기서 컨텍스트 독립적이라는 말은 각 객체가 해당 객체를 실행하는 시스템에 관해 아무것도 알지 못한다는 의미다.</p>\n</blockquote>\n<h3 id=\"-815-의존성-해결하기\" style=\"position:relative;\"><a href=\"#-815-%EC%9D%98%EC%A1%B4%EC%84%B1-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0\" aria-label=\" 815 의존성 해결하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.1.5 의존성 해결하기</h3>\n<p>컴파일타임 의존성은 구체적인 런타임 의존성으로 대체돼야 한다.</p>\n<ul>\n<li>의존성 해결: 컴파일타임 의존성을 실행 컨텍스트에 맞는 적절한 런타임 의존성으로 교체하는 것\n<ul>\n<li>객체를 생성하는 시점에 생성자를 통해 의존성 해결</li>\n<li>객체 생성 후 setter 메서드를 통해 의존성 해결\n<ul>\n<li>객체를 생성한 이후에도 의존하고 있는 대상을 변경할 수 있는 가능성을 열어 놓고 싶은 경우에 유용</li>\n<li>객체가 생성된 후에 협력에 필요한 의존 대상을 설정하기 때문에 객체를 생성하고 의존 대상을 설정하기 전까지는 객체의 상태가 불완전할 수 있다.</li>\n<li>생성자 방식과 혼합해서 사용하는 걸 권장</li>\n</ul>\n</li>\n<li>메서드 실행 시 인자를 이용해 의존성 해결\n<ul>\n<li>메서드가 실행되는 동안만 일시적으로 의존 관계가 존재해도 무방할 때 사용</li>\n<li>메서드가 실행될 때마다 의존 대상이 매번 달라져야 하는 경우에 유용</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"-82-유연한-설계\" style=\"position:relative;\"><a href=\"#-82-%EC%9C%A0%EC%97%B0%ED%95%9C-%EC%84%A4%EA%B3%84\" aria-label=\" 82 유연한 설계 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 8.2 유연한 설계</h2>\n<h3 id=\"-821-의존성과-결합도\" style=\"position:relative;\"><a href=\"#-821-%EC%9D%98%EC%A1%B4%EC%84%B1%EA%B3%BC-%EA%B2%B0%ED%95%A9%EB%8F%84\" aria-label=\" 821 의존성과 결합도 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.1 의존성과 결합도</h3>\n<p>의존성은 객체들의 협력을 가능하게 만드는 매개체라는 관점에서는 바람직한 것이다. 하지만 의존성이 과하면 문제가 될 수 있다.</p>\n<p>바람직한 의존성은 <strong>재사용성</strong>과 관련이 있다.</p>\n<ul>\n<li>어떤 의존성이 다양한 환경에서 클래스를 재사용할 수 없도록 제한한다면 그 의존성은 바람직하지 못한 것이다.</li>\n<li>독립적인 의존성은 바람직한 의존성이고 특정한 컨텍스트에 강하게 결합된 의존성은 바람직하지 않은 의존성이다.</li>\n<li>의존성이 바람직할 때 느슨한 결합도(loose coupling) 또는 약한 결합도(weak coupling)를 가진다고 말한다.</li>\n<li>의존성이 바람직하지 못할 때 단단한 결합도(tight coupling) 또는 강한 결합도(strong coupling)를 가진다고 말한다.</li>\n</ul>\n<h3 id=\"-822-지식이-결합을-낳는다\" style=\"position:relative;\"><a href=\"#-822-%EC%A7%80%EC%8B%9D%EC%9D%B4-%EA%B2%B0%ED%95%A9%EC%9D%84-%EB%82%B3%EB%8A%94%EB%8B%A4\" aria-label=\" 822 지식이 결합을 낳는다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.2 지식이 결합을 낳는다</h3>\n<p>결합도의 정도는 한 요소가 자신이 의존하고 있는 다른 요소에 대해 알고 있는 정보의 양으로 결정</p>\n<ul>\n<li>한 요소가 다른 요소에 대해 더 많은 정보를 알고 있을수록 강하게 결합\n<ul>\n<li>더 적은 컨텍스트에서 재사용 가능하다는 것을 의미</li>\n</ul>\n</li>\n<li>한 요소가 다른 요소에 대해 더 적은 정보를 알고 있을수록 두 요소는 약하게 결합</li>\n</ul>\n<p>결합도를 느슨하게 만들기 위해서는 협력하는 대상에 대해 필요한 정보 외에는 최대한 감추는 것이 중요</p>\n<h3 id=\"-823-추상화에-의존하라\" style=\"position:relative;\"><a href=\"#-823-%EC%B6%94%EC%83%81%ED%99%94%EC%97%90-%EC%9D%98%EC%A1%B4%ED%95%98%EB%9D%BC\" aria-label=\" 823 추상화에 의존하라 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.3 추상화에 의존하라</h3>\n<p>추상화란 어떤 양상, 세부사항, 구조를 좀 더 명확하게 이해하기 위해 특정 절차나 물체를 의도적으로 생략하거나 감춤으로써 복잡도를 극복하는 방법</p>\n<p>일반적으로 추상화와 결합도의 관점에서 의존 대상을 다음과 같이 구분하는 것이 유용하다. 아래로 갈수록 결합도가 느슨해진다.</p>\n<ul>\n<li>구체 클래스 의존성</li>\n<li>추상 클래스 의존성\n<ul>\n<li>상속 계층이 무엇인지 알아야 한다.</li>\n</ul>\n</li>\n<li>인터페이스 의존성\n<ul>\n<li>상속 계층을 모르더라도 협력이 가능해진다.</li>\n</ul>\n</li>\n</ul>\n<p>의존하는 대상이 더 추상적일수록 결합도는 더 낮아진다.</p>\n<h3 id=\"-824-명시적인-의존성\" style=\"position:relative;\"><a href=\"#-824-%EB%AA%85%EC%8B%9C%EC%A0%81%EC%9D%B8-%EC%9D%98%EC%A1%B4%EC%84%B1\" aria-label=\" 824 명시적인 의존성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.4 명시적인 의존성</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Movie {\n\n  private DiscountPolicy discountPolicy;\n\n  public Movie(String title, Duration runningTime, Money fee) {\n    this.discountPolicy = new AmountDiscountPolicy(...);\n  }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>구체 클래스인 <code>AmountDiscountPolicy</code>의 인스턴스를 직접 생성해서 대입하고 있어 결합도가 불필요하게 높아졌다.</li>\n<li><strong>숨겨진 의존성</strong>: 의존성이 퍼블릭 인터페이스에 표현되지 않는다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Movie {\n\n  private DiscountPolicy discountPolicy;\n\n  public Movie(String title, Duration runningTime, Money fee, DiscountPolicy discountPolicy) {\n    this.discountPolicy = discountPolicy;\n  }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>생성자를 사용해 의존성을 해결했다.</li>\n<li><strong>명시적인 의존성</strong>: 모든 경우에 의존성은 명시적으로 퍼블릭 인터페이스에 노출된다.</li>\n</ul>\n<p>의존성을 구현 내부에 숨겨두지 마라. 명시적인 의존성을 사용해야만 퍼블릭 인터페이스를 통해 컴파일타임 의존성을 적절한 런타임 의존성으로 교체할 수 있다.</p>\n<ul>\n<li>클래스가 다른 클래스에 의존하는 것은 부끄러운 것이 아니다❗️</li>\n<li>경계해야 할 것은 의존성 자체가 아니라 의존성을 감추는 것이다.</li>\n</ul>\n<h3 id=\"-825-new는-해롭다\" style=\"position:relative;\"><a href=\"#-825-new%EB%8A%94-%ED%95%B4%EB%A1%AD%EB%8B%A4\" aria-label=\" 825 new는 해롭다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.5 new는 해롭다</h3>\n<p><code>new</code>를 잘못 사용하면 클래스 사이의 결합도가 극단적으로 높아진다.</p>\n<ul>\n<li><code>new</code> 연산자를 사용하기 위해서는 구체 클래스의 이름을 직접 기술해야한다. 즉, 구체 클래스에 의존할 수 밖에 없기에 결합도가 높아진다.</li>\n<li><code>new</code> 연산자는 생성하려는 구체 클래스뿐만 아니라 어떤 인자를 이용해 클래스의 생성자를 호출해야 하는지도 알아야 한다. 즉, 지식의 양이 늘어나기 때문에 결합도가 높아진다.</li>\n</ul>\n<p>사용과 생성의 책임을 분리하고, 의존성을 생성자에 명시적으로 드러내고, 구체 클래스가 아닌 추상 클래스에 의존하게 함으로써 설계를 유연하게 만들 수 있다.</p>\n<ul>\n<li>객체를 생성하는 책임을 객체 내부가 아니라 클라이언트로 옮겨라❗️</li>\n</ul>\n<h3 id=\"-826-가끔은-생성해도-무방하다\" style=\"position:relative;\"><a href=\"#-826-%EA%B0%80%EB%81%94%EC%9D%80-%EC%83%9D%EC%84%B1%ED%95%B4%EB%8F%84-%EB%AC%B4%EB%B0%A9%ED%95%98%EB%8B%A4\" aria-label=\" 826 가끔은 생성해도 무방하다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.6 가끔은 생성해도 무방하다</h3>\n<p>주로 협력하는 기본 객체를 설정하고 싶은 경우 클래스 안에서 객체의 인스턴스를 직접 생성하는 방식이 유용하다.</p>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Movie {\n\n  private DiscountPolicy discountPolicy;\n\n  public Movie(String title, Duration runningTime, Money fee) {\n    this(title, runningTime, fee, new AmountDiscountPolicy(...));\n  }  \n\n  public Movie(String title, Duration runningTime, Money fee, DiscountPolicy discountPolicy) {\n    this.discountPolicy = discountPolicy;\n  }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>생성자 체이닝을 활용</li>\n<li>메서드 오버로딩에도 사용 가능</li>\n</ul>\n<p>모든 결합도가 모이는 새로운 클래스를 추가함으로써 사용성과 유연성이라는 두 마리 토끼를 잡을 수 있는 경우도 있다.</p>\n<h3 id=\"-827-표준-클래스에-대한-의존은-해롭지-않다\" style=\"position:relative;\"><a href=\"#-827-%ED%91%9C%EC%A4%80-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%98%EC%A1%B4%EC%9D%80-%ED%95%B4%EB%A1%AD%EC%A7%80-%EC%95%8A%EB%8B%A4\" aria-label=\" 827 표준 클래스에 대한 의존은 해롭지 않다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.7 표준 클래스에 대한 의존은 해롭지 않다</h3>\n<p>의존성이 불편한 이유는 그것이 항상 변경에 대한 영향을 암시하기 때문</p>\n<ul>\n<li>변경될 확률이 거의 없는 클래스라면 의존성이 문제가 되지 않는다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public abstract class DiscountPolicy {\n  \n  private List&lt;DiscountCondition&gt; conditions = new ArrayList&lt;&gt;();\n\n  public void switchConditions(List&lt;DiscountCondition&gt; conditions) {\n    this.conditions = conditions;\n  }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>ArrayList</code>의 코드가 수정될 확률은 0에 가깝기 때문에 인스턴스를 직접 생성하더라도 문제가 되지 않는다.</li>\n<li>클래스를 직접 생성하더라도 가능한 한 추상적인 타입을 사용하는 것이 확장성 측면에서 유리하다.\n<ul>\n<li>인터페이스 <code>List</code>를 사용하여 다양한 객체로 대체가능하도록 설계</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-828-컨텍스트-확장하기\" style=\"position:relative;\"><a href=\"#-828-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%ED%99%95%EC%9E%A5%ED%95%98%EA%B8%B0\" aria-label=\" 828 컨텍스트 확장하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.8 컨텍스트 확장하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Movie {\n\n  private DiscountPolicy discountPolicy;\n\n  public Movie(String title, Duration runningTime, Money fee) {\n    this(title, runningTime, fee, null);\n  }  \n\n  public Movie(String title, Duration runningTime, Money fee, DiscountPolicy discountPolicy) {\n    this.discountPolicy = discountPolicy;\n  }\n\n  public Money calculateMovieFee(Screening screening) {\n    if (discountPolicy == null) {\n      return fee;\n    }\n\n    return fee.minus(discountPolicy.calculateDiscountAmount(screening))\n  }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>예외 케이스가 추가되어 내부 코드가 수정되었다.\n<ul>\n<li>버그 발생 가능성 ⬆️</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class NoneDiscountPolicy extends DiscountPolicy {\n    \n    @Override\n    protected Money getDiscountAmount(Screening screening) {\n        return Money.ZERO;\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>내부 코드를 수정하지 않아도 된다.</li>\n</ul>\n<p>설계를 유연하게 만들 수 있었던 이유는 <code>Movie</code>가 <code>DiscountPolicy</code>라는 추상화에 의존하고, 생성자를 통해 <code>DiscountPolicy</code>에 대한 의존성을 명시적으로 드러냈으며, <code>new</code>와 같이 구체 클래스를 직접적으로 다뤄야 하는 책임을 <code>Movie</code> 외부로 옮겼기 때문이다.</p>\n<ul>\n<li>결합도를 낮춤으로써 얻게 되는 컨텍스트 확장이라는 개념이 유연하고 재사용 가능한 설계를 만드는 핵심</li>\n</ul>\n<h3 id=\"-828-조합-가능한-행동\" style=\"position:relative;\"><a href=\"#-828-%EC%A1%B0%ED%95%A9-%EA%B0%80%EB%8A%A5%ED%95%9C-%ED%96%89%EB%8F%99\" aria-label=\" 828 조합 가능한 행동 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 8.2.8 조합 가능한 행동</h3>\n<p>어떤 객체와 협력하느냐에 따라 객체의 행동이 달라지는 것은 유연하고 재사용 가능한 설계가 가진 특징이다. 유연하고 재사용 가능한 설계는 응집도 높은 책임들을 가진 작은 객체들을 다양한 방식으로 연결함으로써 애플리케이션의 기능을 쉽게 확장할 수 있다.</p>\n<p>훌륭한 객체지향 설계란 객체가 어떻게 하는지를 표현하는 것이 아니라 객체들의 조합을 선언적으로 표현함으로써 객체들이 무엇을 하는지를 표현하는 설계다.</p>\n<p>설계를 창조하는 데 있어서의 핵심은 <strong>의존성을 관리</strong>하는 것이다.</p>","excerpt":"협력은 필수적이지만 과도한 협력은 설계를 곤경에 빠트릴 수 있다. 협력을 위해서는 의존성이 필요하지만 과도한 의존성은 애플리케이션을 수정하기 어렵게 만든다. 객체지향 설계의 핵심은 협력을 위해 필요한 의존성은 유지하면서도 변경을 방해하는 의존성은 제거하는데 있다. 이런 관점에서 객체지향 설계란 의존성을 관리하는 것이고 객체가 변화를 받아들일 수 있게 의존성을 정리하는 기술이라고 할 수 있다. 📖 8.1 의존성 이해하기 🔖 8.1.…","fields":{"slug":"/backend/object/chapter8/의존성_관리하기/"},"frontmatter":{"title":"Object - 8장 의존성 관리하기","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/dd0e1990925e942697544e2bdcd9332e/9b73b/object.png"}}},"draft":false,"category":"Back-End","tags":["java"],"date":"October 15, 2023"}}}},"staticQueryHashes":["2374173507","2996537568","3691437124"]}