누수 추상화의 의미?


88

"누수 추상화"라는 용어는 무엇을 의미합니까? (예를 들어 설명해주세요. 저는 종종 단순한 이론을 괴롭히는 데 어려움을 겪습니다.)



14
내가 아는 한 용어의 기원 인 Joel Spolsky의 원본 기사 The Law of Leaky Abstractions 를 읽고 싶을 수도 있습니다 .
Daniel Pryden 2010 년

1
제안 된 복제에 대한 대부분의 답변은 유창한 인터페이스에 관한 것입니다.
David Thornley

@David : 두 번째로 많이 득표 한 게시물이 누수 추상화의 의미에 대한 답변과 훌륭한 예입니다.
missingfaktor 2010 년

4
4 년 후이 질문에 대해 Google을 검색하면 어느 게시물이 두 번째로 높은 투표를 받았는지 추측하기 어렵습니다.
John Reynolds

답변:


104

다음은 미트 스페이스 예입니다.

자동차에는 운전자를위한 추상화가 있습니다. 가장 순수한 형태에는 스티어링 휠, 액셀러레이터 및 브레이크가 있습니다. 이 추상화는 엔진, 캠, 타이밍 벨트, 스파크 플러그, 라디에이터 등 후드 아래에있는 내용에 대한 많은 세부 정보를 숨 깁니다.

이 추상화의 깔끔한 점은 사용자를 재교육하지 않고도 구현의 일부를 개선 된 부분으로 대체 할 수 있다는 것입니다. 분배기 캡을 전자 점화 장치로 교체하고 고정 캠을 가변 캠으로 교체한다고 가정 해 보겠습니다. 이러한 변화는 성능을 향상 시키지만 사용자는 여전히 휠로 조종하고 페달을 사용하여 시작 및 정지합니다.

실제로 매우 놀랍습니다. 16 세 또는 80 세는 내부에서 작동하는 방식에 대해 많이 알지 못해도이 복잡한 기계를 조작 할 수 있습니다!

그러나 누출이 있습니다. 변속기는 작은 누출입니다. 자동 변속기에서는 자동차가 기어를 전환 할 때 잠시 힘을 잃는 것을 느낄 수있는 반면 CVT에서는 부드러운 토크를 느낄 수 있습니다.

더 큰 누출도 있습니다. 엔진을 너무 빨리 회전 시키면 엔진이 손상 될 수 있습니다. 엔진 블록이 너무 차가워지면 차량이 시동되지 않거나 성능이 저하 될 수 있습니다. 라디오, 헤드 라이트 및 AC를 동시에 크랭크하면 연비가 감소하는 것을 볼 수 있습니다.


7
예를 들어 주셔서 감사합니다. 누구도 간단한 설명을 할 수없는 것 같았습니다.
Sebastian Patten

7
이것은 특히 소프트웨어 버전이 무엇인지에 대한 사용자 관점을 보여주기 때문에 훌륭한 대답입니다.
chad

1
은 무슨 뜻인가요? 평신도 설명?
brumScouse

1
@brumScouse "meatspace"는 물리적 인 오프라인 세계를 의미합니다. 온라인 사이버 공간 세계와 대조하는 데 사용됩니다. 정의에 대한 링크를 포함하도록 답변을 편집하겠습니다.
Mark E. Haase

나는이 포스트가 "아직 누출이있다"고 지적하는 방식을 좋아한다. 그것들을 최소화하는 것이 전부입니다.
alaboudi

49

이는 추상화가 구현 세부 정보 중 일부를 노출하거나 추상화를 사용할 때 구현 세부 정보를 알고 있어야 함을 의미합니다. 이 용어는 2002 년경 Joel Spolsky에 기인합니다 . 자세한 내용은 wikipedia 기사 를 참조하십시오.

고전적인 예는 원격 파일을 로컬로 처리 할 수있는 네트워크 라이브러리입니다. 이 추상화를 사용하는 개발자는 네트워크 문제로 인해 로컬 파일이 수행하지 않는 방식으로 실패 할 수 있음을 알고 있어야합니다. 그런 다음 네트워크 라이브러리가 제공하는 추상화 외부의 오류를 특별히 처리하는 코드를 개발해야합니다.


7
@mehaase 당신의 추상화가 디자인이나 방치에 의해 누출되는지 여부가 얼마나 중요한지 모르겠습니다. 나는 그 자체로 설 수 있도록 참조 된 기사의 예제와 더 많은 정보로 대답을 확장했습니다. 더욱이 "누수 추상"이 반드시 경멸적일 필요는 없다고 생각합니다. 나에게 이것은 개발자로서 추상화 작업을 할 때 더 조심해야하는 상황을 설명 할뿐입니다. 디자인은 "누출"과 무관하게 좋거나 나쁘거나 무관심 할 수 있습니다.
tvanfosson 2011 년

12

Wikipedia는 이것에 대한 꽤 좋은 정의 를 가지고 있습니다.

누출 된 추상화는 구현 된 추상화를 의미하며, 복잡성을 줄이거 나 숨기려는 목적으로 기본 세부 정보가 완전히 숨겨지지 않습니다.

즉, 소프트웨어의 경우 프로그램의 제한이나 부작용을 통해 기능의 구현 세부 사항을 관찰 할 수 있습니다.

빠른 예는 C # / VB.Net 클로저와 ref / out 매개 변수를 캡처 할 수없는 경우입니다. 캡처 할 수없는 이유는 리프팅 프로세스가 발생하는 방법에 대한 구현 세부 사항 때문입니다. 더 나은 방법이 있다고 말하는 것은 아닙니다.


12

다음은 .NET 개발자에게 익숙한 예입니다. ASP.NET의 Page클래스는 HTTP 작업, 특히 양식 데이터 관리의 세부 정보를 숨기려고 시도하므로 개발자가 게시 된 값을 처리 할 필요가 없습니다 (양식 값을 서버에 자동으로 매핑하기 때문). 통제 수단).

그러나 가장 기본적인 사용 시나리오를 벗어나면 Page추상화가 누출되기 시작하고 클래스의 구현 세부 사항을 이해하지 않으면 페이지 작업이 어려워집니다.

한 가지 일반적인 예는 페이지에 컨트롤을 동적으로 추가하는 것입니다. 동적으로 추가 된 컨트롤의 값은 적절한 때에 추가하지 않는 한 매핑되지 않습니다 . 기본 엔진이 들어오는 양식 값을 적절한 컨트롤에 매핑하기 전에. 그것을 배워야 할 때 추상화가 유출되었습니다 .


Webforms는 버킷에 바닥이 있습니다. 더 나쁜 것은 얇게 가려진 추상화가 글러브 박스에서 작업하는 것처럼 Http와 함께 작동한다는 것입니다.
brumScouse

8

글쎄요, 그것은 중요하지 않지만 순전히 이론적 인 것입니다.

우리는 사물을 더 쉽게 이해할 수 있도록 추상화를 사용합니다. 개별 항목 인 정렬 된 문자 집합을 처리하고 있다는 사실을 숨기기 위해 일부 언어의 문자열 클래스에서 작업 할 수 있습니다. 나는 숫자를 다루고 있다는 사실을 숨기기 위해 순서가 지정된 문자 집합을 처리합니다. 나는 1과 0을 다루고 있다는 사실을 숨기기 위해 숫자를 다룬다.

새는 추상화는 숨기려는 세부 사항을 숨기지 않는 추상화입니다. Java 또는 .NET의 5 자 문자열에서 string.Length를 호출하면 해당 언어가 문자를 호출하는 것이 실제로 UTF-16 데이터 포인트 인 구현 세부 사항 때문에 1 또는 문자의 .5. 추상화가 유출되었습니다. 누출이 없다는 것은 길이를 찾는 것이 더 많은 저장 공간 (실제 길이를 저장하기 위해)이 필요하거나 O (1)에서 O (n) (실제 길이가 무엇인지 알아 내기 위해)로 변경된다는 것을 의미합니다. 내가 진짜 대답에 관심이 있다면 (종종 당신은 그렇지 않다) 진짜 무슨 일이 일어나고 있는지에 대한 지식을 연구해야합니다.

더 논쟁의 여지가있는 경우는 메서드 나 속성을 통해 내부 작업을 수행 할 수있는 경우가 발생합니다. 추상화 누출이든 더 낮은 수준의 추상화로 이동하는 잘 정의 된 방법은 때때로 사람들이 동의하지 않는 문제 일 수 있습니다.


2
그리고 당신은 (내가 아는 매우 늦게 코멘트) 1 개의 당신은 전자 물리학 작업을하고 있다는 사실을 숨기기 위해 0의 작업
Davy8

6

RPC를 사용하여 예제를 제공하는 맥락에서 계속하겠습니다.

RPC의 이상적인 세계에서 원격 프로 시저 호출은 로컬 프로 시저 호출처럼 보여야합니다 (또는 이야기가 진행됨). 여기에는 그들이 호출 할 때하는 프로그래머 완전히 투명해야 SomeObject.someFunction()하는 경우가 아무 생각이 없다 SomeObject(또는 someFunction그 문제에 대해) 로컬로 저장되고 실행 또는 원격으로 저장되고 실행됩니다. 이론은 이것이 프로그래밍을 더 간단하게 만든다는 것입니다.

(세계에서 가장 느린 해석 언어를 사용하는 경우에도) 로컬 함수 호출과 다음 사이에는 큰 차이가 있기 때문에 현실은 다릅니다.

  • 프록시 개체를 통해 호출
  • 매개 변수 직렬화
  • 네트워크 연결 만들기 (아직 설정되지 않은 경우)
  • 원격 프록시로 데이터 전송
  • 원격 프록시가 데이터를 복원하고 사용자를 대신하여 원격 기능을 호출하도록합니다.
  • 반환 값 직렬화
  • 반환 값을 로컬 프록시로 전송
  • 직렬화 된 데이터 재 조립
  • 원격 기능에서 응답 반환

시간 만에 그것은 약 3 차 (또는 그 이상!)의 크기 차이입니다. 이러한 3 배 이상의 크기는 RPC를 실수로 실제 함수 호출로 처음 처리 할 때 프로 시저 호출의 추상화를 확실히 유출시키는 성능에 큰 차이를 만들 것입니다. 추가로 실제 함수 호출은 코드의 심각한 문제를 제외하고 구현 버그 이외의 실패 지점이 거의 없습니다. RPC 호출에는 일반 로컬 호출에서 기대할 수있는 것보다 더 많은 실패 사례가 발생하는 다음과 같은 가능한 문제가 모두 있습니다.

  • 로컬 프록시를 인스턴스화하지 못할 수 있습니다.
  • 원격 프록시를 인스턴스화하지 못할 수 있습니다.
  • 프록시가 연결되지 않을 수 있습니다.
  • 당신이 보내는 매개 변수는 그것을 손상시키지 않거나 전혀 만들지 않을 수 있습니다
  • 원격이 보내는 반환 값은 손상되지 않거나 전혀 만들 수 없습니다.

이제 "로컬 함수 호출과 같은"RPC 호출에는 로컬 함수 호출을 수행 할 때 다룰 필요가없는 추가 오류 조건이 있습니다. 추상화가 다시 유출되었습니다.

결국 RPC는 성공할 때와 실패 할 때 모든 수준에서 체처럼 누출되기 때문에 잘못된 추상화입니다.


<pimp> 이에 대한 Erlang 접근 방식은 함수 호출과 프로세스에 매우 다른 구문을 사용하는 메시지를 보내는 것 사이의 차이를 숨기려고하지 않는다는 점에서 더 좋습니다. 원격 프로세스 메시지 전송은 동일한 일반 구문을 사용하지만 로컬 프로세스 전송과 눈에 띄게 다릅니다. </ pimp>
JUST MY 올바른 OPINION

2
글쎄, 이것은 실제로 좋은 예를 제공하는 유일한 응답입니다 (독해력, 여러분). 그래서 그것은 내 +1을 얻습니다.
Mark E. Haase 2011-06-23

3

의 예 장고는 다 대다 예를 ORM :

다 대다 속성에 Publication 객체를 추가하기 전에 기본 아티클 객체 a1을 .save ()해야한다는 것을 샘플 API 사용에서 확인하십시오. 다 대다 속성을 업데이트하면 기본 데이터베이스에 즉시 저장되는 반면, 단일 속성 업데이트는 .save ()가 호출 될 때까지 db에 반영되지 않습니다.

추상화는 단일 값 속성과 다중 값 속성이 속성 일 뿐인 개체 그래프로 작업한다는 것입니다. 그러나 RDBS의 무결성 시스템이 객체 인터페이스의 얇은 베니어를 통해 나타나기 때문에 관계형 데이터베이스 지원 데이터 저장소로서의 구현은 누출됩니다.


1

추상화 란 무엇입니까?

먼저 "추상화"가 무엇인지 이해하는 것이 가장 좋습니다.

추상화는 세상을 단순화하는 방법입니다. 그것은 실제로 후드 아래 / 커튼 뒤에서 일어나는 일에 대해 걱정할 필요가 없음을 의미합니다. 그것은 바보 증거라는 것을 의미합니다. 그래, 그게 무슨 뜻이야? 이것은 예를 통해 가장 잘 설명됩니다.

추상화의 예 : 737/747 비행의 복잡성은 "추상"됩니다.

보잉 여객기의 예를 들어 보겠습니다. 이 비행기는 매우 복잡한 기계입니다. 당신은 제트 엔진, 산소 시스템, 전기 시스템, 랜딩 기어 시스템 등을 가지고 있지만, 조종사는 제트 엔진의 복잡성에 대해 걱정할 필요가 없습니다 .... 모든 것이 "추상"입니다. 그날 조종사는 비행기를 조종하는 바퀴와 조종 대만 신경 쓰게됩니다. 왼쪽으로 이동하려면 왼쪽으로, 오른쪽으로 이동하려면 오른쪽으로, 위로 당기면 상승을, 아래로 밀어 내려갑니다. 그것은 충분히 간단합니다 ....... 사실 저는 거짓말을했습니다. 핸들을 제어하는 ​​것은 조금 더 복잡합니다. 이상적인 세상에서 그게 그가 해야 할 유일한 것걱정된다. 그러나 실제 생활에서는 그렇지 않습니다. 비행기가 어떻게 작동하는지 또는 구현 세부 사항에 대한 실제 이해없이 원숭이처럼 비행기를 타면 충돌하여 탑승 한 모든 사람을 죽일 수 있습니다.

누수 추상화

실제로 조종사는 많은 중요한 것들에 대해 걱정해야합니다. 모든 것이 추상화 된 것은 아닙니다. 조종사는 풍속, 추력, 공격 각도, 연료, 고도, 날씨 문제, 하강 각도에 대해 걱정해야합니다. 조종사는 올바른 방향으로 가고 있습니다. 비행기가 지금있는 곳입니다. 컴퓨터는 이러한 작업에서 파일럿을 도울 수 있지만 모든 것이 자동화 / 간소화되지는 않습니다.

예를 들어 조종사가 기둥에서 너무 세게 당기면 비행기는 순종하지만 조종사는 비행기를 멈출 위험이 있으며 비행기를 멈 추면 다시 지상으로 추락하기 전에 제어권을 회복하기가 매우 어렵습니다. .

즉, 조종사가 아무것도 모르고 운전대를 조종하는 것만으로는 충분하지 않습니다 ......... nooooo ....... 비행기의 근본적인 위험과 한계에 대해 알아야합니다. 그가 비행기를 타기 전에 ....... 그녀는 비행기가 어떻게 작동하는지, 비행기가 어떻게 날는지 알아야합니다. 그는 구현 세부 사항을 알아야합니다 . ..... 그녀는 너무 세게 당기면 실속으로 이어 지거나 너무 가파르게 착륙하면 비행기가 파괴된다는 것을 알아야합니다.

그런 것들은 추상화되지 않습니다. 많은 것들이 추상화되지만 전부는 아닙니다. 조종사는 스티어링 칼럼과 아마도 한두 가지 다른 것들에 대해서만 걱정하면됩니다. 추상화는 "누수"입니다.

...... 귀하의 코드에서도 마찬가지입니다. 기본 구현 세부 정보를 모르면 모퉁이에서 작업 할 수 있습니다.

다음은 코딩의 예입니다.

ORM은 데이터베이스 쿼리를 처리 할 때 많은 번거 로움을 추상화하지만 다음과 같은 작업을 수행 한 적이 있다면 다음과 같습니다.

User.all.each do |user|
   puts user.name # let's print each user's name
end

그러면 사용자가 2 백만 명 이상인 경우 앱을 죽이는 좋은 방법이라는 것을 알게 될 것입니다. 모든 것이 추상화 된 것은 아닙니다. User.all2,500 만 명의 사용자와 통화 하면 메모리 사용량이 급증하고 문제가 발생할 수 있음을 알아야합니다 . 몇 가지 기본 세부 사항을 알아야합니다. 추상화는 새롭습니다.


0

사실 그 어떤 시점에서 당신의 규모와 실행에 의해 안내합니다, 당신이 필요합니다은 그것이 행동 그런 식으로 행동 이유를 이해하기 위해 사용자의 추상화 프레임 워크의 구현 세부 사항에 대해 잘 알고 얻을 수 있습니다.

예를 들어 다음 SQL쿼리를 고려하십시오 .

SELECT id, first_name, last_name, age, subject FROM student_details;

그리고 그 대안 :

SELECT * FROM student_details;

이제는 논리적으로 동등한 솔루션처럼 보이지만 개별 열 이름 사양으로 인해 첫 번째 솔루션의 성능이 더 좋습니다.

사소한 예이지만 결국 Joel Spolsky의 인용문으로 돌아옵니다.

사소하지 않은 모든 추상화는 어느 정도 누출됩니다.

어느 시점에서 작업의 특정 규모에 도달하면 DB (SQL) 작동 방식을 최적화하고 싶을 것입니다. 이를 위해서는 관계형 데이터베이스가 작동하는 방식을 알아야합니다. 처음에는 추상화되었지만 새는 것입니다. 어느 시점에서 배워야합니다.


-1

라이브러리에 다음 코드가 있다고 가정합니다.

Object[] fetchDeviceColorAndModel(String serialNumberOfDevice)
{
    //fetch Device Color and Device Model from DB.
    //create new Object[] and set 0th field with color and 1st field with model value. 
}

소비자가 API를 호출하면 Object []를 얻습니다. 소비자는 객체 배열의 첫 번째 필드에 색상 값이 있고 두 번째 필드가 모델 값이라는 것을 이해해야합니다. 여기서 추상화가 라이브러리에서 소비자 코드로 유출되었습니다.

해결책 중 하나는 장치의 모델과 색상을 캡슐화하는 객체를 반환하는 것입니다. 소비자는 해당 개체를 호출하여 모델 및 색상 값을 가져올 수 있습니다.

DeviceColorAndModel fetchDeviceColorAndModel(String serialNumberOfTheDevice)
{
    //fetch Device Color and Device Model from DB.
    return new DeviceColorAndModel(color, model);
}

-3

누수 추상화는 상태 캡슐화에 관한 것입니다. 새는 추상화의 아주 간단한 예 :

$currentTime = new DateTime();

$bankAccount1->setLastRefresh($currentTime);
$bankAccount2->setLastRefresh($currentTime);
$currentTime->setTimestamp($aTimestamp);

class BankAccount {
    // ...

    public function setLastRefresh(DateTimeImmutable $lastRefresh)
    {
        $this->lastRefresh = $lastRefresh;
    } }

그리고 올바른 방법 (누수 추상화가 아님) :

class BankAccount
{
    // ...

    public function setLastRefresh(DateTime $lastRefresh)
    {
        $this->lastRefresh = clone $lastRefresh;
    }
}

여기에 자세한 설명이 있습니다 .

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