추상화 수준을 결정하는 방법


35

저는 오늘 "청결한 코드" 라는 책을 읽고 있었는데 저자가 함수 당 추상화 수준에 대해 이야기하고있는 단락을 발견했습니다. 그는 일부 코드를 저 / 중급 / 고수준 추상화로 분류했습니다.

내 질문은 추상화 수준을 결정하는 기준은 무엇입니까?

나는이 책에서 그 단락을 인용한다.

함수가 "한 가지"작업을 수행하도록하려면 함수 내 명령문이 모두 동일한 추상화 레벨에 있는지 확인해야합니다. Listing 3-1이이 규칙을 어떻게 위반하는지 쉽게 알 수있다. getHtml ()과 같이 추상화 수준이 매우 높은 개념이 있습니다. 중간 수준의 추상화에있는 다른 것 (예 : String pagePathName = PathParser.render (pagePath); .append ( "\ n")와 같이 여전히 낮은 수준의 다른 것.


답변:


27

저자는 추상화 (계층 적 들여 쓰기 광산)에 대해 설명하는 부분의 "위에서 아래로 코드 읽기"하위 섹션에서 설명합니다.

[...] 우리는 프로그램이 TO 단락 세트 인 것처럼 프로그램을 읽을 수 있기를 원합니다 . 각 단락은 현재 추상화 레벨을 설명하고 다음 TO 레벨에서 다음 TO 단락을 참조 합니다.

  • 설정 및 분류를 포함하기 위해 설정을 포함시킨 다음 테스트 페이지 내용을 포함시킨 다음 분류를 포함합니다.
    • 설정을 포함하기 위해 스위트 인 경우 스위트 설정을 포함시킨 다음 일반 설정을 포함시킵니다.
      • 제품군 설정을 포함하기 위해 "SuiteSetUp"페이지의 상위 계층 구조를 검색하고 해당 페이지의 경로와 함께 include 문을 추가합니다.
        • 부모를 검색하려면 ...

이것과 함께 갈 코드는 다음과 같습니다.

public void CreateTestPage()
{
    IncludeSetups();
    IncludeTestPageContent();
    IncludeTeardowns();
}

public void IncludeSetups()
{
    if(this.IsSuite())
    {
        IncludeSuiteSetup();
    }

    IncludeRegularSetup();
}

public void IncludeSuiteSetup()
{
    var parentPage = FindParentSuitePage();

    // add include statement with the path of the parentPage
}

등등. 함수 계층 구조를 자세히 살펴볼 때마다 추상화 수준을 변경해야합니다. 위의 예에서 IncludeSetups, IncludeTestPageContent그리고 IncludeTeardowns동일한 추상화 레벨에서 모두.

이 책에서 주어진 예에서, 저자는 큰 기능이 매우 구체적이고 한 가지만하는 작은 기능으로 나뉘어 야한다고 제안합니다. 올바르게 수행하면 리팩토링 된 함수는 여기 예제와 유사합니다. 리팩토링 된 버전은이 책의 목록 3-7에 나와 있습니다.


10

이 질문을 이해하려면 추상화가 무엇인지 이해해야합니다. (나는 공식적인 정의를 찾기에는 너무 게으르다. 그래서 나는 쇠약해질 것이라 확신한다. 그러나 여기에서 간다.) 추상화는 복잡한 주제 나 실체를 가지고 대부분의 세부 사항을 숨길 때이다 그 객체의 본질을 여전히 정의하는 기능을 노출시키면서

나는 그 책이 당신에게 준 예가 집이라고 믿습니다. 집을 자세히 살펴보면 보드, 못, 창문, 문으로 구성되어 있음을 알 수 있습니다. 그러나 사진 옆에 집을 그리는 만화는 여전히 집입니다. 많은 세부 사항.

소프트웨어도 마찬가지입니다. 책에서 알 수 있듯이 프로그래밍 할 때마다 소프트웨어를 레이어로 생각해야합니다. 주어진 프로그램은 쉽게 100 개 이상의 레이어를 가질 수 있습니다. 맨 아래에는 CPU에서 실행되는 어셈블리 명령어가있을 수 있습니다.이 명령어는 더 높은 수준에서 디스크 I / O 루틴을 형성하기 위해 결합 될 수 있으며, 더 높은 수준에서는 디스크 I / O로 작업 할 필요가 없습니다. Windows 기능을 사용하여 파일 열기 / 읽기 / 쓰기 / 탐색 / 닫기를 간단히 할 수 있기 때문에 O. 이들은 자신의 응용 프로그램 코드에 도달하기 전에도 모두 추상화됩니다.

코드 내에서 추상화 계층이 계속됩니다. 하위 수준의 문자열 / 네트워크 / 데이터 조작 루틴이있을 수 있습니다. 더 높은 수준에서 이러한 루틴을 사용자 관리, UI 계층, 데이터베이스 액세스를 정의하는 서브 시스템으로 결합 할 수 있습니다. 또 다른 계층은이 서브 시스템을 더 큰 엔터프라이즈 시스템의 일부로 통합하는 서버 구성 요소로 결합 할 수 있습니다.

이들 추상화 계층 각각의 핵심은 각각이 이전 계층 (들)에 의해 노출 된 세부 사항을 숨기고 다음 계층에 의해 소비 될 매우 깨끗한 인터페이스를 제시한다는 것이다. 파일을 열기 위해 개별 섹터를 작성하는 방법이나 처리 할 하드웨어 인터럽트를 몰라도됩니다. 그러나 추상화 계층 체인으로 이동하기 시작하면 Write () 함수 호출에서 하드 드라이브 컨트롤러로 전송되는 정확한 명령까지 추적 할 수 있습니다.

저자가 말한 것은 클래스 나 함수를 정의 할 때 어떤 레이어인지 생각하십시오. 서브 시스템 및 사용자 오브젝트를 관리하는 클래스가있는 경우, 동일한 클래스가 저수준 문자열 조작을 수행하거나 소켓 호출을위한 변수를 포함하지 않아야합니다. 그것은 추상화 계층을 넘어서고 하나의 클래스 / 함수가 하나의 일만하는 것입니다 (SRP-단일 책임 원칙).


2

내 질문은 추상화 수준을 결정하는 기준은 무엇입니까?

추상화 수준은 분명해야합니다. 프로그래밍 언어의 일부가 아닌 문제 영역의 일부인 경우 추상적입니다. "매우 추상적"== "실제하지 않음"== "문제 도메인"보다 명확하지 않습니다. 그리고 "추상적이지 않습니다 == 구체적 == 언어의 일부". 추상화 수준을 결정하는 것은 쉽지 않습니다. 전혀 미묘해서는 안됩니다.

.append("\n")추상이 아닙니다. 문자열에 문자를 넣습니다. 구체적입니다. 초록이 아닙니다.

String pagePathName = PathParser.render(pagePath);문자열을 다룹니다. 구체적인 것. 구체적인 프로그래밍 언어 기능에 부분적으로. 추상적 인 "경로"와 "파서"개념으로 부분적으로 작업.

getHtml(); 추상. "마크 업"및 사소하고 구체적인 언어 기능이 아닌 것들을 다룹니다.

초록 == 언어 기능이 아닙니다.

콘크리트 == 언어 기능.


1
프로그래머가 생성 한 추상화, 즉 프로그래머가 생성 한 추상화를 기술하는 품질로 추상화를 정의하면, 나는 당신의 단어 정의에 동의하는 경향이 있습니다. 그러나 모든 프로그래밍 언어는보다 구체적인 것에 대한 추상화입니다. 프로그래밍 언어의 선택에 따라 어느 정도의 추상화가 시작되는지가 결정됩니다.
— Robert Harvey

1

추상화 수준은 간단하다고 생각합니다. 코드 라인이 메소드의 단일 책임을 직접 구현하지 않으면 또 다른 추상화 수준입니다. 예를 들어, 내 메소드 이름이 SaveChangedCustomers ()이고 모든 고객 목록을 매개 변수로 사용하는 경우 단일 책임은 변경된 고객을 목록에 저장하는 것입니다.

foreach(var customer in allCustomers)
{
    if (CustomerIsChanged(customer)
        customer.Save();
}

종종 CustomerIsChanged () 메서드를 호출하는 대신 고객이 foreach 루프에 포함 된 것으로 변경되었는지 확인하는 논리를 찾을 수 있습니다. 고객 기록이 변경되었는지 확인하는 것은이 방법의 책임이 아닙니다! 다른 추상화 수준입니다. 그러나 그 결정을 내리는 논리가 단지 한 줄의 코드라면? 상관 없습니다 !!! 추상화 수준이 다르므로이 방법 외부에 있어야합니다.

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