"누수 추상화"라는 용어는 무엇을 의미합니까? (예를 들어 설명해주세요. 저는 종종 단순한 이론을 괴롭히는 데 어려움을 겪습니다.)
"누수 추상화"라는 용어는 무엇을 의미합니까? (예를 들어 설명해주세요. 저는 종종 단순한 이론을 괴롭히는 데 어려움을 겪습니다.)
답변:
다음은 미트 스페이스 예입니다.
자동차에는 운전자를위한 추상화가 있습니다. 가장 순수한 형태에는 스티어링 휠, 액셀러레이터 및 브레이크가 있습니다. 이 추상화는 엔진, 캠, 타이밍 벨트, 스파크 플러그, 라디에이터 등 후드 아래에있는 내용에 대한 많은 세부 정보를 숨 깁니다.
이 추상화의 깔끔한 점은 사용자를 재교육하지 않고도 구현의 일부를 개선 된 부분으로 대체 할 수 있다는 것입니다. 분배기 캡을 전자 점화 장치로 교체하고 고정 캠을 가변 캠으로 교체한다고 가정 해 보겠습니다. 이러한 변화는 성능을 향상 시키지만 사용자는 여전히 휠로 조종하고 페달을 사용하여 시작 및 정지합니다.
실제로 매우 놀랍습니다. 16 세 또는 80 세는 내부에서 작동하는 방식에 대해 많이 알지 못해도이 복잡한 기계를 조작 할 수 있습니다!
그러나 누출이 있습니다. 변속기는 작은 누출입니다. 자동 변속기에서는 자동차가 기어를 전환 할 때 잠시 힘을 잃는 것을 느낄 수있는 반면 CVT에서는 부드러운 토크를 느낄 수 있습니다.
더 큰 누출도 있습니다. 엔진을 너무 빨리 회전 시키면 엔진이 손상 될 수 있습니다. 엔진 블록이 너무 차가워지면 차량이 시동되지 않거나 성능이 저하 될 수 있습니다. 라디오, 헤드 라이트 및 AC를 동시에 크랭크하면 연비가 감소하는 것을 볼 수 있습니다.
이는 추상화가 구현 세부 정보 중 일부를 노출하거나 추상화를 사용할 때 구현 세부 정보를 알고 있어야 함을 의미합니다. 이 용어는 2002 년경 Joel Spolsky에 기인합니다 . 자세한 내용은 wikipedia 기사 를 참조하십시오.
고전적인 예는 원격 파일을 로컬로 처리 할 수있는 네트워크 라이브러리입니다. 이 추상화를 사용하는 개발자는 네트워크 문제로 인해 로컬 파일이 수행하지 않는 방식으로 실패 할 수 있음을 알고 있어야합니다. 그런 다음 네트워크 라이브러리가 제공하는 추상화 외부의 오류를 특별히 처리하는 코드를 개발해야합니다.
Wikipedia는 이것에 대한 꽤 좋은 정의 를 가지고 있습니다.
누출 된 추상화는 구현 된 추상화를 의미하며, 복잡성을 줄이거 나 숨기려는 목적으로 기본 세부 정보가 완전히 숨겨지지 않습니다.
즉, 소프트웨어의 경우 프로그램의 제한이나 부작용을 통해 기능의 구현 세부 사항을 관찰 할 수 있습니다.
빠른 예는 C # / VB.Net 클로저와 ref / out 매개 변수를 캡처 할 수없는 경우입니다. 캡처 할 수없는 이유는 리프팅 프로세스가 발생하는 방법에 대한 구현 세부 사항 때문입니다. 더 나은 방법이 있다고 말하는 것은 아닙니다.
다음은 .NET 개발자에게 익숙한 예입니다. ASP.NET의 Page
클래스는 HTTP 작업, 특히 양식 데이터 관리의 세부 정보를 숨기려고 시도하므로 개발자가 게시 된 값을 처리 할 필요가 없습니다 (양식 값을 서버에 자동으로 매핑하기 때문). 통제 수단).
그러나 가장 기본적인 사용 시나리오를 벗어나면 Page
추상화가 누출되기 시작하고 클래스의 구현 세부 사항을 이해하지 않으면 페이지 작업이 어려워집니다.
한 가지 일반적인 예는 페이지에 컨트롤을 동적으로 추가하는 것입니다. 동적으로 추가 된 컨트롤의 값은 적절한 때에 추가하지 않는 한 매핑되지 않습니다 . 기본 엔진이 들어오는 양식 값을 적절한 컨트롤에 매핑하기 전에. 그것을 배워야 할 때 추상화가 유출되었습니다 .
글쎄요, 그것은 중요하지 않지만 순전히 이론적 인 것입니다.
우리는 사물을 더 쉽게 이해할 수 있도록 추상화를 사용합니다. 개별 항목 인 정렬 된 문자 집합을 처리하고 있다는 사실을 숨기기 위해 일부 언어의 문자열 클래스에서 작업 할 수 있습니다. 나는 숫자를 다루고 있다는 사실을 숨기기 위해 순서가 지정된 문자 집합을 처리합니다. 나는 1과 0을 다루고 있다는 사실을 숨기기 위해 숫자를 다룬다.
새는 추상화는 숨기려는 세부 사항을 숨기지 않는 추상화입니다. Java 또는 .NET의 5 자 문자열에서 string.Length를 호출하면 해당 언어가 문자를 호출하는 것이 실제로 UTF-16 데이터 포인트 인 구현 세부 사항 때문에 1 또는 문자의 .5. 추상화가 유출되었습니다. 누출이 없다는 것은 길이를 찾는 것이 더 많은 저장 공간 (실제 길이를 저장하기 위해)이 필요하거나 O (1)에서 O (n) (실제 길이가 무엇인지 알아 내기 위해)로 변경된다는 것을 의미합니다. 내가 진짜 대답에 관심이 있다면 (종종 당신은 그렇지 않다) 진짜 무슨 일이 일어나고 있는지에 대한 지식을 연구해야합니다.
더 논쟁의 여지가있는 경우는 메서드 나 속성을 통해 내부 작업을 수행 할 수있는 경우가 발생합니다. 추상화 누출이든 더 낮은 수준의 추상화로 이동하는 잘 정의 된 방법은 때때로 사람들이 동의하지 않는 문제 일 수 있습니다.
RPC를 사용하여 예제를 제공하는 맥락에서 계속하겠습니다.
RPC의 이상적인 세계에서 원격 프로 시저 호출은 로컬 프로 시저 호출처럼 보여야합니다 (또는 이야기가 진행됨). 여기에는 그들이 호출 할 때하는 프로그래머 완전히 투명해야 SomeObject.someFunction()
하는 경우가 아무 생각이 없다 SomeObject
(또는 someFunction
그 문제에 대해) 로컬로 저장되고 실행 또는 원격으로 저장되고 실행됩니다. 이론은 이것이 프로그래밍을 더 간단하게 만든다는 것입니다.
(세계에서 가장 느린 해석 언어를 사용하는 경우에도) 로컬 함수 호출과 다음 사이에는 큰 차이가 있기 때문에 현실은 다릅니다.
시간 만에 그것은 약 3 차 (또는 그 이상!)의 크기 차이입니다. 이러한 3 배 이상의 크기는 RPC를 실수로 실제 함수 호출로 처음 처리 할 때 프로 시저 호출의 추상화를 확실히 유출시키는 성능에 큰 차이를 만들 것입니다. 추가로 실제 함수 호출은 코드의 심각한 문제를 제외하고 구현 버그 이외의 실패 지점이 거의 없습니다. RPC 호출에는 일반 로컬 호출에서 기대할 수있는 것보다 더 많은 실패 사례가 발생하는 다음과 같은 가능한 문제가 모두 있습니다.
이제 "로컬 함수 호출과 같은"RPC 호출에는 로컬 함수 호출을 수행 할 때 다룰 필요가없는 추가 오류 조건이 있습니다. 추상화가 다시 유출되었습니다.
결국 RPC는 성공할 때와 실패 할 때 모든 수준에서 체처럼 누출되기 때문에 잘못된 추상화입니다.
의 예 장고는 다 대다 예를 ORM :
다 대다 속성에 Publication 객체를 추가하기 전에 기본 아티클 객체 a1을 .save ()해야한다는 것을 샘플 API 사용에서 확인하십시오. 다 대다 속성을 업데이트하면 기본 데이터베이스에 즉시 저장되는 반면, 단일 속성 업데이트는 .save ()가 호출 될 때까지 db에 반영되지 않습니다.
추상화는 단일 값 속성과 다중 값 속성이 속성 일 뿐인 개체 그래프로 작업한다는 것입니다. 그러나 RDBS의 무결성 시스템이 객체 인터페이스의 얇은 베니어를 통해 나타나기 때문에 관계형 데이터베이스 지원 데이터 저장소로서의 구현은 누출됩니다.
먼저 "추상화"가 무엇인지 이해하는 것이 가장 좋습니다.
추상화는 세상을 단순화하는 방법입니다. 그것은 실제로 후드 아래 / 커튼 뒤에서 일어나는 일에 대해 걱정할 필요가 없음을 의미합니다. 그것은 바보 증거라는 것을 의미합니다. 그래, 그게 무슨 뜻이야? 이것은 예를 통해 가장 잘 설명됩니다.
추상화의 예 : 737/747 비행의 복잡성은 "추상"됩니다.
보잉 여객기의 예를 들어 보겠습니다. 이 비행기는 매우 복잡한 기계입니다. 당신은 제트 엔진, 산소 시스템, 전기 시스템, 랜딩 기어 시스템 등을 가지고 있지만, 조종사는 제트 엔진의 복잡성에 대해 걱정할 필요가 없습니다 .... 모든 것이 "추상"입니다. 그날 조종사는 비행기를 조종하는 바퀴와 조종 대만 신경 쓰게됩니다. 왼쪽으로 이동하려면 왼쪽으로, 오른쪽으로 이동하려면 오른쪽으로, 위로 당기면 상승을, 아래로 밀어 내려갑니다. 그것은 충분히 간단합니다 ....... 사실 저는 거짓말을했습니다. 핸들을 제어하는 것은 조금 더 복잡합니다. 이상적인 세상에서 그게 그가 해야 할 유일한 것걱정된다. 그러나 실제 생활에서는 그렇지 않습니다. 비행기가 어떻게 작동하는지 또는 구현 세부 사항에 대한 실제 이해없이 원숭이처럼 비행기를 타면 충돌하여 탑승 한 모든 사람을 죽일 수 있습니다.
실제로 조종사는 많은 중요한 것들에 대해 걱정해야합니다. 모든 것이 추상화 된 것은 아닙니다. 조종사는 풍속, 추력, 공격 각도, 연료, 고도, 날씨 문제, 하강 각도에 대해 걱정해야합니다. 조종사는 올바른 방향으로 가고 있습니다. 비행기가 지금있는 곳입니다. 컴퓨터는 이러한 작업에서 파일럿을 도울 수 있지만 모든 것이 자동화 / 간소화되지는 않습니다.
예를 들어 조종사가 기둥에서 너무 세게 당기면 비행기는 순종하지만 조종사는 비행기를 멈출 위험이 있으며 비행기를 멈 추면 다시 지상으로 추락하기 전에 제어권을 회복하기가 매우 어렵습니다. .
즉, 조종사가 아무것도 모르고 운전대를 조종하는 것만으로는 충분하지 않습니다 ......... nooooo ....... 비행기의 근본적인 위험과 한계에 대해 알아야합니다. 그가 비행기를 타기 전에 ....... 그녀는 비행기가 어떻게 작동하는지, 비행기가 어떻게 날는지 알아야합니다. 그는 구현 세부 사항을 알아야합니다 . ..... 그녀는 너무 세게 당기면 실속으로 이어 지거나 너무 가파르게 착륙하면 비행기가 파괴된다는 것을 알아야합니다.
그런 것들은 추상화되지 않습니다. 많은 것들이 추상화되지만 전부는 아닙니다. 조종사는 스티어링 칼럼과 아마도 한두 가지 다른 것들에 대해서만 걱정하면됩니다. 추상화는 "누수"입니다.
...... 귀하의 코드에서도 마찬가지입니다. 기본 구현 세부 정보를 모르면 모퉁이에서 작업 할 수 있습니다.
다음은 코딩의 예입니다.
ORM은 데이터베이스 쿼리를 처리 할 때 많은 번거 로움을 추상화하지만 다음과 같은 작업을 수행 한 적이 있다면 다음과 같습니다.
User.all.each do |user|
puts user.name # let's print each user's name
end
그러면 사용자가 2 백만 명 이상인 경우 앱을 죽이는 좋은 방법이라는 것을 알게 될 것입니다. 모든 것이 추상화 된 것은 아닙니다. User.all
2,500 만 명의 사용자와 통화 하면 메모리 사용량이 급증하고 문제가 발생할 수 있음을 알아야합니다 . 몇 가지 기본 세부 사항을 알아야합니다. 추상화는 새롭습니다.
사실 그 어떤 시점에서 당신의 규모와 실행에 의해 안내합니다, 당신이 필요합니다은 그것이 행동 그런 식으로 행동 이유를 이해하기 위해 사용자의 추상화 프레임 워크의 구현 세부 사항에 대해 잘 알고 얻을 수 있습니다.
예를 들어 다음 SQL
쿼리를 고려하십시오 .
SELECT id, first_name, last_name, age, subject FROM student_details;
그리고 그 대안 :
SELECT * FROM student_details;
이제는 논리적으로 동등한 솔루션처럼 보이지만 개별 열 이름 사양으로 인해 첫 번째 솔루션의 성능이 더 좋습니다.
사소한 예이지만 결국 Joel Spolsky의 인용문으로 돌아옵니다.
사소하지 않은 모든 추상화는 어느 정도 누출됩니다.
어느 시점에서 작업의 특정 규모에 도달하면 DB (SQL) 작동 방식을 최적화하고 싶을 것입니다. 이를 위해서는 관계형 데이터베이스가 작동하는 방식을 알아야합니다. 처음에는 추상화되었지만 새는 것입니다. 어느 시점에서 배워야합니다.
라이브러리에 다음 코드가 있다고 가정합니다.
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);
}
누수 추상화는 상태 캡슐화에 관한 것입니다. 새는 추상화의 아주 간단한 예 :
$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;
}
}