추상화를 통해 세부 사항을 숨기면 어떤 가치가 있습니까? 투명성에 가치가 없습니까?


30

배경

나는 큰 추상화 팬이 아닙니다. 나는 인터페이스 등의 적응성, 이식성 및 재사용 성으로부터 이익을 얻을 수 있음을 인정할 것이다. 거기에는 실질적인 이점이있다. 그리고 나는 그것을 의심하고 싶지 않으므로 무시하자.

추상화의 다른 주요 "혜택"이 있는데,이 추상화의 사용자로부터 구현 로직과 세부 사항을 숨기는 것입니다. 논쟁은 당신이 세부 사항을 알 필요가 없으며이 시점에서 자신의 논리에 집중해야한다는 것입니다. 이론적으로 이해가됩니다.

그러나 대기업 응용 프로그램을 유지 관리 할 때마다 항상 자세한 내용을 알아야합니다. 매번 무언가가 무엇을 하는지를 정확히 알아 내기 위해 매번 추상화에 깊고 깊이 파고 드는 것은 엄청난 번거 로움입니다. 즉, 사용 된 저장 프로 시저를 찾기 전에 약 12 ​​번 "공개 선언"을 수행해야합니다.

이 '세부 정보 숨기기'사고 방식은 방해가되는 것 같습니다. 나는 항상 더 투명한 인터페이스와 더 적은 추상화를 원합니다. 나는 높은 수준의 소스 코드를 읽고 그것이 무엇을하는지 알 수 있지만, 그것이 어떻게되는지, 그것이 어떻게되는지, 내가 정말로 알아야 할 것임을 결코 알지 못할 것입니다.

무슨 일이야? 내가 작업 한 모든 시스템이 (적어도이 관점에서) 잘못 설계 되었습니까?

내 철학

소프트웨어를 개발할 때 필자는 필자가 ArchLinux 철학과 밀접한 관련이있는 철학을 따르려고 한다고 생각합니다 .

Arch Linux는 GNU / Linux 시스템의 고유 한 복잡성을 유지하면서 체계적이고 투명하게 유지합니다. 아치 리눅스 개발자와 사용자는 시스템의 복잡성을 숨기려고하면 실제로는 훨씬 더 복잡한 시스템이 만들어 지므로 피해야한다고 생각합니다.

따라서 추상화 계층 뒤에 소프트웨어의 복잡성을 숨기려고 시도하지 않습니다. 나는 추상화를 남용하려고 노력하지만, 그것의 노예가되지는 않는다.

마음에 질문

  1. 세부 사항을 숨기는 데 진정한 가치가 있습니까?
  2. 우리는 투명성을 희생하지 않습니까?
  3. 이 투명성이 중요하지 않습니까?

7
잘못된 디자인의 형태로 추상화가 남용 될 수 있습니다. 그러나 이것이 추상화가 원칙적으로 가치가 없다는 것을 의미하지는 않습니다.
Bernard

4
나는 거기에 좋은 질문이 있다고 생각하지만, 추상화에 대한 분노와 비슷합니다. 그것을 강조하지 않고 실제 질문을 더 많이 이끌어 낼 수 있습니까?
PersonalNexus

4
"세부 정보 숨기기"의 올바른 정의를 사용하고 있습니까? 이러한 맥락에서, 그것은 당신이 무언가의 내부 작용을 배우는 것을 막는 것이 아니라 결합을 줄이는 것에 관한 것입니다.
Andres F.

24
책상에 전압계와 오실로스코프를 사용하여 프로그래밍하지 않는 한 추상화 위의 추상화 위의 추상화에 대해서만 프로그래밍합니다. 실제로 비트가 아니라 전압을 조작하는 세부 사항을 숨기는 데 가치가 있습니까? 그렇게하면 투명성이 희생됩니까? 그 투명성이 가치가 있습니까?
Eric Lippert

8
나는 당신이 문제를 겪고있는 것은 추상화가 아니라 실제로 아무것도 추상화하지 않는 빈 간접 레이어입니다. 그렇습니다. 대기업 시스템에서 종종 발견되며 좋지 않습니다.
Michael Borgwardt

답변:


47

세부 사항을 숨기는 이유는 세부 사항을 숨기지 않기 때문입니다. 종속 코드를 위반하지 않고 구현을 수정할 수 있습니다.

객체 목록이 있고 각 객체에 Name속성 및 기타 데이터 가 있다고 상상해보십시오 . 그리고 많은 경우 목록 Name에서 특정 문자열과 일치 하는 항목을 찾아야 합니다.

확실한 방법은 각 항목을 하나씩 반복 Name하고 문자열과 일치 하는지 확인하는 것 입니다. 그러나 목록에 수천 개의 항목이있는 것처럼 시간이 너무 많이 걸리는 경우 문자열 개체 사전 조회로 바꾸고 싶을 수 있습니다.

이제 목록을 검색하고 반복하여 모든 조회를 수행 한 경우이 문제를 해결하기 위해 엄청난 노력을 기울여야합니다. 라이브러리에 있고 타사 사용자가 라이브러리를 사용하는 경우 훨씬 더 어려워집니다. 당신은 나가서 그들의 코드를 고칠 수 없습니다 !

그러나 FindByName이름 조회 프로세스를 캡슐화하는 방법이 있다면 구현 방식과 해당 코드를 호출하는 모든 코드가 계속 작동하고 무료로 훨씬 빠르게 얻을 수 있습니다. 이것이 추상화와 캡슐화의 진정한 가치입니다.


나는 이것에 동의하지만 이것은 문제의 핵심이 아닙니다. 특정 기능을 캡슐화하는 방법이 유용하다는 데 완전히 동의 할 수는 있지만 이것이 항상 동기가 아니라고 생각합니다. 내가 잘못?
user606723

3
@ User606723 : 그래야합니다. 즉, 항상 의미하지 않는다 이다 . 어떤 사람들은 요점을 이해하지 못하고 더 많은 층 위에 더 많은 층을 쌓고 물건을 혼란스럽게 만듭니다. 그렇기 때문에 숙련 된 프로그래머는 새로운 개발자가 새로운 기술이나 기법을 이해하기 전에는 절대 채택하지 말라고 조언합니다.
메이슨 휠러

3
@ user606723 : 투명성은 타이트한 커플 링을 권장하므로 항상 나쁘지는 않지만 대개는 그렇지 않습니다.
Malfist

3
화물 컬트 프로그래밍의 형태로 레이어를 쌓는 사람들에 대한 Mason의 설명 문제는 내가 너무 많은 상속을 의심하는 이유와 상속보다 구성이 선호되는 이유입니다. 특히 Java 프로그래머에게는 문제가되는 것 같습니다.
jhocking 2018 년

2
아니요, 타이트한 커플 링이 항상 나쁜 것은 아닙니다 . 자주 나쁘지만 피하기 위해 많은 시간을 투자하면 소프트 코딩
메이슨 휠러

16

방금 Code Complete에서 추상화에 대한 섹션을 읽었으므로이 소스의 대부분이 여기에 있습니다.

추상화의 요점은 "어떻게 구현 되었습니까?"라는 질문을 제거하는 것입니다. 당신이 호출 할 때 user.get_id(), 당신은이 것을 알고 id다시받을거야 것입니다. "이것은 어떻게 사용자 아이디를 얻습니까?" 그때는 아마 어느 쪽인가를 필요로하지 않는 id, 또는 get_id()예기치 못한 가난하게 설계되어 뭔가를 돌려줍니다.

추상화를 사용하여 디자인 할 수 있습니다.

a house with doors and windows

디자인이 아님

a box with four walls,
    with 3 holes,
        two of which fit panes of glass surrounded by wood frames,
        one that fits a large plank of wood with hinges and a metal knob,
etc.

나는이 인터페이스에 대해 이야기하고 있지 않습니다. 이 인터페이스는 괜찮습니다. 여러 가지 추상화로 나뉘어 진 거대한 복잡한 시스템에 대해 이야기하고 있습니다.
user606723

9
@ user606723 그렇다면 귀하의 질문은 추상화보다는 복잡한 디자인에 관한 것입니다.
Andres F.

3
코드 완성의 경우 +1 여기에는 추상화가 디자인에 필요한 이유와 왜 잘못된 수준 의 추상화가 설계를 방해 하는지에 대해 다룹니다 . 구역 지정 사무소에서 일하고 있다면 더 자세히 설명하기 위해 세부 사항을 숙지하지 않고 집에 대해 생각하고 싶습니다. 하지만 집에 대해 내가 생각하는 방식으로 생각하면 집을 지을 수 없었습니다.
스펜서 Rathbun

이 질문은 종료되거나 제목이 변경되어야합니다.
Jake Berger

8

세부 사항을 숨기는 데 진정한 가치가 있습니까?

예. 추상화를 제공함으로써 더 높은 수준에서 사고하고 프로그래밍 할 수 있습니다.

미적분 또는 행렬 대수가없는 물리 시스템 모델링을 상상해보십시오. 완전히 비현실적입니다. 마찬가지로 스칼라 수준에서만 프로그래밍 할 수 있으면 흥미로운 문제를 해결할 수 없습니다. 비교적 간단한 웹 응용 프로그램이라도 태그 라이브러리와 같은 추상화의 이점을 크게 누릴 수 있습니다. 네 개의 텍스트 필드와 선택 상자를 반복적으로 생성하는 것보다 "주소 입력 필드"를 의미하는 태그를 삽입하는 것이 훨씬 쉽습니다. 해외로 확장하기로 결정한 경우 국제 주소를 처리하기 위해 모든 양식을 수정하는 대신 태그 정의를 수정하면됩니다. 추상화를 효과적으로 사용하면 일부 프로그래머는 다른 프로그래머보다 10 배 더 효과적입니다.

인간에게는 작업 기억력이 제한되어 있습니다. 추상화는 우리가 큰 시스템에 대해 추론 할 수있게합니다.

Aren't we sacrificing transparency?

추상화를 사용하지 않으면 소프트웨어 구성 요소의 목적이 반복적으로 자세하게 묻 힙니다. 개발자는 다음과 같은 코드를 통해 하루를 보내 게됩니다.

for (i = 0; i < pilgrim.wives.size(); ++i) {
  wife = pilgrim.wives[i];
  for (j = 0; j < wife.sacks.size(); ++j) {
     sack = wife.sacks[i];
     for (k = 0; j < sack.cats.size(); ++j) {
        cat = sack.cats[k];
        for (m = 0; m < cat.kits.size(); ++m) {
           ++count;
        }
     }
  }
}

생각하지 않고 "아, 키트 위에 또 다른 4 단계 루프"라고 생각하고

pilgrim.kits.each { ++count; }

이 투명성이 중요하지 않습니까?

지적한 바와 같이 간접 비용이 있습니다. "경우에 따라"레이어를 생성 할 필요는 없습니다. 중복을 줄이고 코드를 명확하게하기 위해 추상화를 사용하십시오.


7

사람들이 추상화가 구현 세부 사항을 숨기고 있다고 말할 때 실제로 찾기가 어렵다는 의미에서 "숨기기"를 의미하지는 않습니다. 의미하는 것은 인터페이스를 단순하고 간결하며 관리하기 쉽게 유지하기 위해 공용 인터페이스와 별도의 구현 세부 정보입니다. 자동차가 중요한 부분을 대부분 숨기고 조작 할 수있는 상당히 기본적인 컨트롤 세트 만 제공하는 것처럼 소프트웨어 모듈은 대부분의 기능을 창자 깊이에 숨기고 제한된 수의 액세스 방법 만 노출합니다. 그것을 운전하십시오. 모든 엔진 내부를 수동으로 조작 해야하는 자동차를 상상해보십시오 (그리고 많은 괴물이 있습니다). 교통을 주시하고 길을 찾는 것이 정말 힘들 것입니다.

그러나 인터페이스를 단순하게 유지하는 것은 단지 미적인 것이 아닙니다. 성공적인 프로젝트와 죽음의 행진간에 차이를 만들 수 있습니다. 악마의 옹호자를 잠시 동안 놀자. 추상화가 전혀없는 소프트웨어 프로젝트를 상상해보십시오. 값을 유지해야하는 경우 전역 변수를 사용합니다. 기능을 두 번 이상 사용해야하는 경우 복사하여 붙여 넣습니다. 특정 코드 섹션의 두 가지 버전이 필요한 경우 복사하여 붙여넣고 if명령문으로 랩핑 한 다음 두 가지를 모두 수정하십시오. 기술적으로 말하면 작동하지만 몇 달 동안 몇 가지 심각한 문제가 발생합니다.

  • 버그를 찾아서 고치면 비슷한 코드의 다른 복사-붙여 넣기 인스턴스에도 존재할 가능성이 높으므로 버그를 찾아서 고치는 것 외에도 다른 경우를 찾아서 고쳐야합니다.
  • 버그를 찾거나 변경을 구현하려면 유지 보수 프로그래머가 관련 코드를 이해할 수 있어야합니다. 이 작업을 수행하는 데 어려움은 관련 코드 섹션의 크기에 따라 증가하지만 그 범위에 따라 더 커집니다. 정신적으로 일부 코드를 단계별로 실행하면서 머리에 십여 개의 변수를 유지하는 것이 가능합니다. 그러나 수백 개가 있다면 생산성에 심각한 영향을 미칩니다 (사고 과정을 실제 RAM이 부족하고 스왑 파일에 담그는 프로그램과 비교하고 싶습니다. 한 번에 코드를 유창하게 읽는 대신 프로그래머는 물건을 찾으려면 앞뒤로 움직여야합니다.
  • 코드의 범위는 버그를 찾기 위해 파헤쳐 야하는 코드베이스의 크기에도 영향을줍니다. 두 개의 매개 변수가 있고 전역이없는 열 줄 함수가 있고 입력 값과 충돌하는 줄을 알고 있으면 버그를 찾는 것이 일반적으로 사소한 것이며 종종 코드를 보는 것 이상이 필요하지 않습니다. 수백 줄, 20 개의 매개 변수, 15 개의 전역이 있고 비슷한 특성의 몇 가지 다른 함수를 호출하면 심각한 고통에 처하게됩니다.
  • 적절한 추상화가 없으면 변경 될 코드에 실제로 영향을 줄 수 있으므로 변경 사항이 코드베이스의 많은 부분에 영향을 줄 수 있습니다. 이러한 코드베이스의 일반적인 증상은 작고 무해한 것처럼 보이고 완전히 관련이없는 기능이 갑자기 중단된다는 것입니다. 추상화를 사용하면 변경으로 인한 피해량을 제한 할 수 있으며 영향을보다 예측 가능하게 만들 수 있습니다. 개인 필드의 이름을 변경하면 확인할 소스 파일이 하나만 있습니다. 전역 변수의 이름을 변경하면 전체 코드베이스를 실행해야합니다.

잘못 요약 된 코드베이스에서 영향은 일반적으로 코드베이스의 크기에 따라 기하 급수적으로 증가합니다. 즉, 일정한 양의 코드를 추가하면 유지 보수 노력이 일정한 요인만큼 증가합니다. 설상가상으로, 더 많은 프로그래머를 프로젝트에 추가한다고해서 생산성이 선형 적으로 증가하지는 않지만 대수적으로는 최고입니다 (팀이 클수록 커뮤니케이션에 더 많은 오버 헤드가 필요함).


2

필요한 경우 어떻게 작동하는지 이해해야한다고 생각합니다. 일단 당신이 생각한대로 행동한다고 ​​판단되면 마음의 평화를 누리게됩니다. 나는 그 목표가 영원히 숨길 것이라고 생각하지 않았다.

자신이 작동 할 것이라고 확신하는 시계에 알람을 설정하면 코레 트 시간에 알람이 울리면 잠을 잘 수 있습니다. 한 시간 일찍 깨우면 초가 똑딱 거리는 것을 볼 수 있습니다.


1
물론, 종종 알람 시계의 작동 방식을 변경하거나 다른 사람들에게 변경 사항을 완전히 알리지 않고 알람 시계의 작동 방식을 변경하도록 요청받지는 않습니다.
user606723

1
지금까지 사용한 모든 프레임 워크에 대한 코드 변경이 보입니까?
JeffO

1
아니요,하지만 내가 사용한 모든 프레임 워크에 대한 코드 변경 사항은 유지되지 않습니다.
user606723

3
당신은 JeffO의 요점을 거의 증명했습니다. 알람 시계를 유지 관리하는 사업도 아닙니다. 하나를 구입하고 어떻게 작동하는지에 대한 완전한 분해 및 분석을 수행하지 않고 사용하기 시작하면 내부가 추상적이라는 것을 인정한 것입니다. 그것이 어떻게 작동하는지 알아보기 위해 그것을 찢을 는 없지만 아무리 자주 필요하다는 것을 알 수 있습니까?
Blrfl

2

구체적으로 질문에 대답하려면 :

세부 사항을 숨기는 데 진정한 가치가 있습니까?

예. 질문의 첫 줄에서 인정합니다.

우리는 투명성을 희생하지 않습니까?

실제로는 아닙니다. 잘 작성된 추상화는 필요한 경우 세부 사항을 쉽게 이해할 수있게합니다.

이 투명성이 중요하지 않습니까?

예. 필요할 때 원하는 내용을 쉽게 이해할 수 있도록 추상화를 설계하고 구현해야합니다.


마지막으로 내가 좋아하는 대답.
user606723

1

숨겨진 것들이 작동 할 때 세부 사항을 숨기는 것이 좋습니다.

예를 들어, 버튼 클릭이나 무언가를 통해 사용자가 시작하는 두 가지 기능인 동작 (예 : GetListItems, SendListItem)을 정의하는 인터페이스를 개발한다고 가정 해 보겠습니다. 이제 각 사용자는 고유 한 "ListItemStore"를 가질 수 있습니다. 하나는 페이스 북에 있고, 하나는 myspace에 있습니다. (예를 들어) .. 그것은 사용자 속성으로 저장되고 사용자 선점을 통해 응용 프로그램의 어딘가에 설정되어 있다고 말합니다. 앱 개발자가 과정에서 추가 ListItemStore를 추가 할 수 있다고 말합니다. 시간 (mybook, facespace 등)

이제 페이스 북에 연결하고 항목을 가져 오는 데 많은 세부 사항이 있습니다. 그리고 myspace에 연결할 때에도 같은 세부 사항이 있습니다.

이제 초기 "저장소 액세스"코드를 작성한 후에는 코드를 수정할 필요가 없습니다 (페이스 북에서는 변경 사항을 따라 잡기 위해 풀 타임 개발자가 필요할 수 있습니다).

따라서 코드를 사용할 때 다음과 같습니다.

    new ItemManager(user) //passes in user, allowing class to get all user properties
    ItemManager.GetListItems()

그리고 지금 당신은 그들이 저장 한 곳에서 사용자의 데이터를 얻었습니다. 걱정하는 것은 항목 목록을 가져 와서 무언가를하는 것입니다. 어떻게 든 상관없이 2 줄 밖에 걸리지 않기 때문에 더 많은 매장이 추가되었습니다. 스택에 질문에 답변 / 게시 할 수 있습니다 ... lol ..

따라서 모든 배관 작업은 "숨겨져"있으며 올바른 항목 목록을 얻는 한 실제로 어떻게 처리해야하는지에 대해 관심이 있습니다. 단위 테스트가 있으면 결과가 더 쉬워지기 때문에 더 쉬울 수 있습니다. 이미 수량화되었습니다 ..


예, 그러나 유지 관리해야 할 부분은 결코이 두 줄이 아닙니다. 그것들은 망쳐 놓을 수 없습니다. 항상 2, 3, 4 레벨 아래로 변경해야합니다. API 가 있으면 안정적이라고 믿을 수 있지만 이것이 비즈니스의 복잡성으로 인해 안정적이지 않다면 어떨까요?
user606723

1
@ user606723 당신 API가 안정되지 않은 경우, 다음은 가능성 중 하나 미성숙, 또는 가능성이 잘못된 추상화
SDG

@ user606723-사실이며,이 경우 명명 규칙 자체는 실제 프로그래밍 논리 / 세부 사항을 숨기는 투명성 형태를 정의해야합니다. 실제 소스를 수정해야하는 경우 추가 정보 및 아이디어를 정보 명명으로 표현해야합니다. 본질적으로 투명성은 적절한 이름을 사용하여 달성 할 수 있지만 실제로는 자주 내려갈 필요는 없습니다.
hanzolo

@sdg 또는 시스템 요구 사항이 항상 변경되기 때문입니다. 법률이 바뀌기 때문에 다른 사람의 API가 바뀌기 때문에 우리가 통제 할 수 없습니다.
user606723

1
@ user606723-나는 실제로 재무 SaaS 시스템에서 일하고 있으며 매 릴리스주기마다 추상화가 충분하지 않은 함정을 봅니다. 그 중 일부는 디자인이 좋지 않은 결과이지만 일반적으로 원래 의도하지 않은 코드를 입력 한 결과입니다. 주석, 이름 및 캡슐화가 없으면 체인을 내려가는 것이 어려울 수 있습니다 . 내가했던 일은, 과부하를 추가하고 적절한 계산에 도착하거나 새로 추가 할 다른 논리 지점을 통해 읽는 것보다 훨씬 더 좋은 일 것 다음 Remeasurements.GetRemeasureType (부여), 및 reMeasure.PerformCalc () 인 경우
hanzolo

1

"숨기기"라고하는 것은 많은 사람들이 우려를 분리하는 것으로 간주합니다 (예 : 구현과 인터페이스).

내 생각에 추상화의 주요 이점 중 하나는 개발자의 제한된 뇌 공간에서 불필요한 세부 정보의 혼란을 줄이는 것입니다.

구현 코드가 난독 화되면 투명성을 방해하는 것으로 볼 수 있지만 추상화는 좋은 조직입니다.


1

첫째, 단일 머신 코드 명령어 이외의 것은 본질적으로 추상화입니다. while...do루프는 조건이 충족 될 때까지 일련의 명령어를 반복하는 데 필요한 비교 및 ​​주소 호출을 나타내는 일관된 상징적 방법입니다. 마찬가지로 int 유형은 (시스템에 따라) X 비트 수에 대한 추상화입니다. 프로그래밍은 모두 추상화에 관한 것입니다.

아마도 이러한 기본 추상화가 매우 유용하다는 데 동의 할 것입니다. 글쎄, 자신의 것을 만들 수 있습니다. OOAD와 OOP가 전부입니다.

사용자가 화면에서 데이터를 구분 된 텍스트, Excel 및 pdf와 같은 다양한 형식으로 내보내고 자하는 요구 사항이 있다고 가정합니다. DelimitedTextExporter, ExcelExporter 및 PDFExporter를 빌드 할 수있는 방법에 따라 export (data) 메소드를 사용하여 "Exporter"라는 인터페이스를 작성하는 것이 편리하지 않습니까? 각 인터페이스는 특정 출력을 작성하는 방법을 알고 있습니다. 모든 호출 프로그램은 export (data) 메소드를 호출 할 수 있으며 사용 된 구현이 수행 할 것입니다. 또한 구분 된 텍스트 규칙이 변경되면 ExcelExporter를 망칠 필요없이 DelimitedTextExporter를 변경할 수 있습니다.

OO 프로그래밍에 사용되는 잘 알려진 모든 디자인 패턴은 추상화에 의존합니다. 추상화가 좋은 이유에 대해 더 나은 느낌을 얻으려면 Freeman과 Freeman 's Head First Design Patterns 를 읽는 것이 좋습니다.


1
심지어 기계 코드는 프로그래머가 실제, 물리적, 논리 아래도 디지털 전자를 진행 프로세스가 무엇을 통해 추상화, 추상화입니다 정말 증언 할 수있는 칩을 오버 클러킹의 해시했다 사람으로 발생
JK합니다.

기계 명령 수준에서 더 구체적으로 보이지만 너무 사실입니다.
Matthew Flynn

1

나는 이것에 대한 당신의 느낌을 이해한다고 생각하며, 비슷한 의견이 있다고 생각합니다.

50 코드 라인 클래스를 이해하기 쉽기 때문에 50 개의 코드 라인 클래스를 3 개의 클래스와 3 개의 인터페이스로 바꾸는 Java 개발자와 협력했습니다. 그리고 나는 참을 수 없었다.

문제는 이해하기 어려웠고 디버깅이 거의 불가능했으며 "구현을 전환"할 필요가 없었습니다.

반면에, 여러 객체가 비슷한 동작을 공유하고 한 곳에서 사용되는 코드를 보았으며 메서드가 공통 인터페이스를 통해 노출되었을 경우 공통 정렬 / 처리 루프를 실제로 사용할 수 있습니다.

따라서 유사한 시나리오에서 사용될 수있는 핵심 개체 인 IMHO는 일반적으로 인터페이스를 통해 액세스 할 수있는 일반적인 동작의 이점을 얻습니다. 그러나 그것이 옳기 때문에 간단한 것을 추상화하거나 구현을 전환 할 수있게하는 것은 코드를 혼란스럽게 만드는 방법 일뿐입니다.

다시 말하지만, 나는 모든 평생 관리 문제가있는 폭발적인 작은 클래스보다 더 똑똑한 클래스를 선호하며 관계 및 스파게티 호출 그래프를보기가 어렵습니다. 그래서 어떤 사람들은 저와 동의하지 않을 것입니다.


1

숨기고 추상화하는 지침 은 사용자를 구현에서 분리 하여 독립적으로 변경할 수 있어야 합니다. 소비자가 구현 세부 사항과 결합되면 내부와의 조정으로 인해 둘 다 돌로 주조되어 새로운 기능을 도입하기가 더 어려워집니다 또는 미래에 더 나은 알고리즘.

모듈을 작성할 때 구현의 숨겨진 부분은 생각할 수없는 다른 코드를 손상시키지 않고 모듈을 변경할 수있는 마음을줍니다.

불투명 한 인터페이스를 제공하는 또 다른 이점은 서브 시스템 사이의 표면적을 크게 줄인다는 것입니다. 상호 작용할 수있는 방법의 양을 줄임으로써 예측 가능하고 테스트하기 쉬우 며 버그가 줄어 듭니다. 모듈 간 상호 작용도 모듈 수에 따라 2 차적으로 증가하므로 이러한 복잡성 증가를 제어하는 ​​데 가치가 있습니다.


즉, 너무 많이 숨기고 인터페이스를 너무 깊게 중첩하는 것이 가능합니다. 복잡성을 최소화하고 유지 관리 성을 최대화하면서 최대한 유용하도록 시스템을 설계하는 것은 지능적인 인간으로서 프로그래머의 임무입니다.


0

많은 경우에, 당신 은 일이 어떻게 구현되는지 알 필요 가 없습니다 . 나는 당신이 이와 같은 코드를 people.Where(p => p.Surname == "Smith")하루에 여러 번 작성할 것이라고 거의 보장 할 수 있지만 "이 Where()방법이 실제로 어떻게 작동합니까?" 라고 생각하지 않을 것입니다. 당신은 신경 쓰지 않습니다-당신은이 방법이 있고 당신이 원하는 결과를 얻는다는 것을 알고 있습니다. 작동 방식에 관심이있는 이유는 무엇입니까?

이것은 사내 소프트웨어와 동일합니다. Oracle, Microsoft 등이 작성하지 않았다고해서 구현 방법을 찾아야한다는 의미는 아닙니다. 합리성 GetAllPeopleWithSurname(string name)을 가진 사람들의 목록을 반환하기 위해 호출 된 메소드를 합리적으로 기대할 수 있습니다 . 그것은 목록을 반복하고, 사전을 사용하고, 완전히 미친 것을 할 수 있지만 걱정하지 않아도됩니다 .

물론이 규칙에는 예외가 있습니다 (법칙이 없으면 규칙이 아닙니다!).이 방법에 버그가있는 경우입니다. 당신이 3 사람들과 목록을 가지고 당신이 알고있는 경우에 따라서 위의 예에서, 그들 중 하나는 성 스미스를 가지고 그들은 목록에 반환되지 않습니다 다음 이 명확하게 세분화되어 있기 때문에 해당 메소드의 구현에 관심 .

추상화는 올바르게 수행하면 나중에 읽을 때 유용하지 않은 모든 내용을 필터링 할 수 있기 때문에 훌륭합니다. 코드를 작성하는 것보다 코드를 읽는 데 더 많은 시간이 걸리므로 잊지 말고 가능한 한 쉽게 해당 작업을 수행해야합니다. 또한 추상화는 팔만큼 객체의 계층 구조를 의미한다고 생각할 수도 있지만 100 줄 방법을 10 줄씩 10 줄로 리팩토링하는 것만 큼 간단 할 수 있습니다. 따라서 한 번에 10 단계를 모두 묶은 것은 이제 10 개의 별도 단계로,이 성가신 버그가 숨어있는 곳으로 곧장 갈 수 있습니다.


Eh,하지만 구현을 유지 관리하는 사람이라고 가정하겠습니다. 누군가 구현에 관심이 있고 그 사람이 당신이라는 것을 의미합니다. 당신은 또한 구현의 사용자가되었습니다. 비즈니스 요구 사항이 (예측할 수없는 방식으로) 변경되어 여러 계층에있는 변경 사항이 발생합니다. 내 요점은 버그가 그 규칙에 대한 유일한 예외는 아니라는 것입니다.
user606723

문제는PeopleFactory.People.Strategy.MakePeople.(CoutryLaw.NameRegistry.NameMaker.Make()) as People.Female
Coder

@ user606723 항상 코드베이스에있는 모든 한 줄의 코드에 신경 쓸 필요는 없습니다. 거기 구현의 버그 또는 재 작성 될 필요가있는 것으로서 최대의 신고 인 경우 (이 느린 때문에, 심하게 서면 또는 무엇이든) 당신이 그것을 다시 쓰고있어, 다음, 당신은 그것에 대해 신경. 그렇지 않으면 방해가되지 않아야합니다. 어쩌면 문제는 항상 모든 코드를 소유하려고한다는 것입니다. 내 의견으로는 특정 시간에 작업중 인 코드에 집중해야합니다.
Stuart Leyland-Cole

@Coder 분명히 그것은 극단적 인 추상화 형태입니다! 처음에는 그것이 OP와 반대되는 것이라고 생각했지만 나머지 답장을 읽음으로써 모든 추상화가 나쁜 나쁜 것으로 보입니다 . 그렇기 때문에 답변에서 다른 수준의 추상화를 설명하려고 시도했습니다.
Stuart Leyland-Cole

0

추상화로 인해 정보가 숨겨집니다. 이것은 더 낮은 커플 링으로 끝납니다. 이로 인해 변경 위험이 줄어 듭니다. 이것은 코드를 만질 때 긴장하지 않는 행복한 프로그래머로 이어질 것입니다.

이러한 아이디어는 소프트웨어 아키텍처에서 세 가지 필수 법률을 통해 표현됩니다.

사이먼의 법칙 : "계층 구조는 복잡성을 줄입니다." (계층 구조는 추상화를 도입합니다)

파나의 법칙 : "숨겨진 것만 위험없이 바꿀 수 있습니다."

콘스탄틴의 법칙 : 견고한 프로그램은 낮은 결합력과 높은 응집력이 필요합니다


"계층 구조는 복잡성을 줄입니다." -반드시 사실은 아닙니다.
Coder

결정론적인 설계 방법론은 없습니다. 이 법은 IT / CS에서 나온 것이 아니며 훨씬 넓은 의미로 공식화되어 있으며 수학, 물리학 자 등이 언급하고 있습니다. 이는 유효한 교장이지만 아무도 감각이없는 계층을 만드는 것을 막을 수는 없습니다.
ins0m

0

나는 엔터프라이즈 응용 프로그램 사업에도 종사하고 있으며, 같은 질문을 가지고 있기 때문에이 질문은 내 관심을 끌었습니다. 지금까지 나의 경력 과정에서 추상화 문제에 대한 통찰력을 얻었지만 통찰력은 결코 보편적 인 대답이 아닙니다. 나는 새로운 아이디어와 생각을 계속 배우고 듣고 있습니다. 그래서 지금 믿는 것이 바뀔 수 있습니다.

내가 크고 복잡한 의료 응용 프로그램을 유지 관리 할 때 방금 당신을 좋아했을 때 나는 모든 추상화를 싫어했습니다. 모든 코드가 어디로 가는지 파악하는 것은 목의 통증이었습니다. 다른 수업을 뛰어 다니는 것은 어지러워졌습니다. 그래서 나는 스스로에게 "추상적 인 짜증, 물건을 디자인 할 때 추상화를 최소화 할 것"이라고 말했다.

그런 다음 처음부터 응용 프로그램 (상대 소규모 웹 서비스 구성 요소)을 디자인해야했습니다. 모든 고통을 기억하면서 구성 요소를 꽤 평평하게 디자인했습니다. 문제는 요구 사항이 바뀌었을 때 여러 다른 장소로 변경해야한다는 것이 었습니다 (요구 사항은 매우 유동적이었고 이에 대해 아무것도 할 수 없었습니다). 너무 나빴고 기본적으로 초기 디자인을 버리고 추상화로 다시 디자인했으며 상황이 좋아졌습니다. 요구 사항이 더 이상 변경 될 때 많은 장소를 변경할 필요가 없었습니다.

응용 프로그램을 제공하고 몇 주 동안 앉아 응용 프로그램 유지 관리를 시작하라는 지시를 받았습니다. 나는 잠시 동안 모든 것을 기억하지 못해서 내 자신의 코드를 이해하기 위해 조금 어려움을 겪었고 추상화는 도움이되지 못했습니다.

나는 나중에 다른 많은 프로젝트에 참여했으며 추상화 수준으로 조금 더 놀 수있는 기회를 가졌습니다. 내가 실제로 찾은 것은 내 개인적인 의견 일뿐입니다. 추상화는 개발에 많은 도움이되지만 코드를 작성하지 않고 응용 프로그램의 가장 깊은 수준까지 모든 것을 이해하려고 할 때 부정적인 영향을 미칩니다. 당신은 다른 수업을 뛰어 다니며 연결을 시도하는 데 더 많은 시간을 할애합니다.

필자는 개발 시간 동안 추상화가 매우 귀중하여 코드를 이해하려고 할 때 관리자로서 겪는 문제는 가치가 있다고 생각합니다. 비즈니스 문제를 해결하기위한 소프트웨어가 존재하며, 비즈니스 문제는 시간이 지남에 따라 발전합니다. 따라서 소프트웨어는 시간이 지남에 따라 발전해야합니다. 추상화없이 소프트웨어를 진화시키는 것은 매우 어렵습니다. 코드 구조의 패턴을 확인한 후 관리자가 코드베이스를 쉽게 탐색 할 수있는 방식으로 추상화를 설계 할 수 있으므로 초기 학습 곡선 만 좌절됩니다.


0

다른 사람들이 말했듯이 추상화 뒤에있는 "숨김 세부 정보"를 사용하면 사용자에게 영향을 미치지 않고 세부 정보를 변경할 수 있습니다. 이 아이디어는 Parnas의 모듈을 시스템으로 분해하는 데 사용되는 기준 (1972) 에서 비롯되었으며 ADT (abstract data types) 및 객체 지향 프로그래밍 아이디어와 관련이 있습니다.

거의 동시에, Codd의 대규모 공유 데이터 뱅크 (1970)대한 관계형 데이터 모델 (1970) 은 데이터베이스 사용자에게 영향을주지 않고 데이터베이스의 내부 스토리지 표현을 변경하고 싶었습니다 (추상 및 소개 참조). 그는 약간의 스토리지 변경에 대처하기 위해 프로그래머가 정기적으로 며칠이 걸리고 코드 페이지를 수정하는 것을 보았습니다.

즉, 추상화를 사용하기 위해 내부에 무엇이 있는지 알아야하는 경우 추상화는 그다지 유용하지 않습니다. 잘 디자인하기가 매우 어려울 수 있습니다. 좋은 추상화의 예는 덧셈입니다. 마지막으로 언제 일어날 일에 대해 생각해야 했습니까? (그러나 오버플로 등의 경우).

중요한 문제 (IMHO)는 (파르 나스의 관점에서) 모듈을 잘 설계하려면 무엇이 바뀌고 무엇이 바뀌지 않을지 예측해야한다는 것입니다. 미래를 예측하는 것은 어렵습니다.하지만 무언가에 대해 많은 경험이 있고 그것을 명확하게 이해한다면, 꽤 좋은 예측 작업을 수행 할 수 있습니다. 따라서 잘 작동하는 모듈 (추상)을 설계 할 수 있습니다.

그러나 모든 추상화의 운명, 심지어 가장 좋은 것은 결국 추상화를 깨야하는 예측할 수없는 (그리고 틀림없이 예측할 수없는) 변화가있을 것입니다. 이 문제를 해결하기 위해 일부 추상화에는 이스케이프 처리가되어있어 실제로 필요한 경우 더 깊은 수준에 액세스 할 수 있습니다.

이 모든 것이 매우 부정적으로 보입니다. 그러나 나는 진실로 우리가 잘 작동하는 추상화로 둘러싸여 있으며 그것들을 눈치 채지 못하거나 숨어있는 것을 깨닫지 못한다고 생각합니다. 우리는 불완전한 추상화만을 발견하므로 황홀한 견해를 가지고 있습니다.


0

추상화는 주로 소비자 (예 : 응용 프로그램 프로그래머)의 이익을위한 것입니다. 시스템 (디자이너) 프로그래머는 아름답고 유용하게 만들기 위해 더 많은 노력을 기울여야하므로 초보자는 보통 좋은 디자인을하지 않습니다.

추상화가 항상 복잡성을 추가하기 때문에 추상화를 좋아하지 않습니까? 어쩌면 당신이 작업 한 시스템에 추상화 사용 (추상 사용에 비해)이 있습니까? 그들은 만병 통치약이 아닙니다.

유용한 추상화의 추가 작업과 복잡성은 보상이되지만 확실하게 알기는 어렵습니다. 추상화를 피벗 포인트로 생각하면 소프트웨어 디자인이 어느 쪽에서 나 유연해질 수 있습니다. 추상화 구현은 클라이언트 코드를 손상시키지 않고 수정 될 수 있으며 새로운 클라이언트는 추상화를 쉽게 재사용하여 새로운 것을 만들 수 있습니다.

추상화의 투자 수익률은 시간이 지남에 따라 상대적으로 고통이없는 구현 변경 및 추가 신규 클라이언트 중 하나 또는 두 방향으로 시간이 지남에 따라 "유연"되었음을 보여줌으로써 거의 투자 수익을 측정 할 수 있습니다.

예를 들어, Java에서 Socket 클래스의 추상화를 사용하면 Java 1.2의 응용 프로그램 코드가 Java 7에서 여전히 잘 작동한다고 확신합니다 (일부 성능 변경이있을 수 있음). Java 1.2 이후로,이 추상화를 사용한 새로운 클라이언트가 많이있었습니다.

추상화에 대한 불행에 관해서 는 Socket 클래스 뒤에서 코드를 유지 관리하는 개발자와 이야기 하면 Socket을 사용하여 재미있는 응용 프로그램을 작성하는 클라이언트만큼 인생이 어리 석고 장미 빛이 아닐 수도 있습니다. 추상화 구현 작업은 반드시 사용하는 것보다 더 많은 작업입니다. 그러나 그것은 나쁘지 않습니다.

투명성에 관해서는 하향식 설계 전략에서 전체 투명성이 나쁜 설계를 만듭니다. 똑똑한 프로그래머는 자신이 원하는 정보를 최대한 활용하는 경향이 있으며 시스템은 밀접하게 결합됩니다. 똑똑한 프로그래머가 그 정보를 사용하여 유용한 정보를 사용했기 때문에 모듈에서 가장 작은 세부 사항 변경 (예 : 데이터 구조에서 바이트 순서 변경)으로 인해 일부 코드가 다른 곳에서 중단 될 수 있습니다. David Parnas는 1971 년의 기사에서이 문제를 지적 하여 디자인에 정보 숨기기를 제안했습니다.

운영 체제의 "내부"가 운영 체제에서 실행되는 응용 프로그램에 대한 OS 인 추상화의 복잡한 구현으로 간주하면 ArchLinux에 대한 참조가 의미가 있습니다. 추상화의 장에서 간단하게 유지하십시오.


0

질문으로 질문에 대답하겠습니다. 오늘 아침에 일하러 운전했을 때 (실제로 그렇게했다고 가정합니다), 엔진이 연료-공기 혼합을 허용하기 위해 밸브를 어떻게 열고 어떻게 점화했는지주의를 기울였습니까? 아냐 상관 없어 . 도로를 주행 할 때 자동차 엔진이 어떻게 작동 하는지 . 당신은 것을 걱정 하지 작업.

언젠가 차가 작동하지 않는다고 가정 해보십시오. 시작하지 않고, 막대를 던지거나, 벨트를 부러 뜨리고, 문자 메시지가 바쁠 때 자신의 잘못없이 그 콘크리트 장벽으로 쟁기질을 할 수 있습니다. 이제 새 차가 필요합니다 (적어도 일시적으로). 이 새 차가 어떻게 작동하는지 정확히 신경 쓰십니까? 아니요. 관심있는 것은 먼저 작동한다는 것입니다. 둘째는 오래된 차를 운전할 때 사용한 것과 동일한 지식과 기술을 사용하여 새 차를 운전할 수 있다는 것입니다. 운전하는 차량에 변화가없는 것이 이상적입니다. 현실적으로이 새로운 자동차의 작동 방식은 가능한 한 "놀람"을 줄입니다.

이러한 기본 원칙은 캡슐화 및 추상화의 핵심 원칙입니다. 객체가 어떻게 행동하는지에 대한 지식은 객체로 무엇을 하는가에 필요한 것이 아니어야합니다. 컴퓨터 프로그래밍에서도 프로그램을 실행하는 CPU 내의 전기 경로에 대한 세부 정보는 최소한 6 개 이상의 I / O 명령어, 드라이버, OS 소프트웨어 및 런타임 계층 뒤에 추상화되어 있습니다. 많은 성공적인 소프트웨어 엔지니어는 정확한 하드웨어 아키텍처 또는 심지어 OS 빌드에 대해 걱정하지 않고 완벽하게 좋은 코드를 작성합니다. 나를 포함해서.

캡슐화 / 정보 숨기기는 "어떻게하는지 신경 쓰지 말고 그냥 신경 쓰십시오"라는 정신을 허용합니다. 소비자는 소비자가 쉽게 소비 할 수있는 방식으로 소비자에게 유용한 것을 노출시켜야합니다. 현실 세계로 돌아가서 자동차가 사용자에게 내부 작업에 대한 정보를 제공해서는 안되거나 자동차가 사용자에게 점화, 스티어링 휠, 페달. 모든 차량에는 속도계와 연료 게이지, 타코미터, 바보 등 및 기타 피드백이 있습니다. 사실상 모든 자동차에는 헤드 라이트, 회전 신호, 라디오, 좌석 조정 등과 같은 다양한 독립 서브 시스템을위한 스위치가 있습니다. 모든 경우에 충분한 지식이 있다면 당신은 그것을 열고 약간 다른 방식으로 작동하도록 물건을 변경할 수 있습니다. 그러나 대부분의 경우 아마도 어쩌면 사용자가 실내에서 연료 펌프를 직접 독립적으로 제어 할 수 없어야합니까? 아마도, 아마도 사용자는 실제로 브레이크 페달을 밟지 않고 브레이크 라이트를 작동시킬 수 없어야합니까?

추상화는 "이것과 같지는 않지만 둘 다 XI이기 때문에 X와 같이 사용할 수 있습니다"라는 사고 방식을 허용합니다. 객체가 추상화를 상속하거나 구현하는 경우 소비자는 구현에서 다른 알려진 추상화 구현과 동일하거나 유사한 결과를 생성해야합니다. Toyota Camry와 Ford Fusion은 모두 "자동차"입니다. 따라서 스티어링 휠과 같은 일반적인 예상 기능 세트가 있습니다. 시계 반대 방향으로 돌리면 자동차가 왼쪽으로갑니다. 시계 방향으로 돌리면 자동차가 오른쪽으로 이동합니다. 미국 내 어느 차 에나 탑승 할 수 있으며, 자동차에는 스티어링 휠과 최소 2 개의 페달이있을 것으로 예상됩니다. 하나는 오른쪽에 "car goes"페달이고 가운데 하나는 "car stops"페달입니다 .

추상화의 목록은 "최소한 놀랍게도의 이론"입니다. 시운전을 위해 새 차의 바퀴를 타고 운전대를 시계 방향으로 돌리고 차를 왼쪽으로 돌리면 가장 말이 놀랍습니다. POS 판매자를 고발 한 판매자를 비난 할 수 있으며, 새로운 행동이 익숙한 것보다 "더 나은"이유 또는이 행동이 "문서화 된"것 또는 " 투명 "제어 시스템입니다. 이 새 차와 당신이 운전했던 다른 모든 차에도 불구하고, 여전히 "차"인이 차를 운전할 때 새 차를 성공적으로 운전하기 위해 차를 어떻게 운전해야하는지에 대한 몇 가지 기본 개념을 바꿔야합니다. 그것은 일반적으로 나쁜 일입니다. 새로운 패러다임에 직관적 인 이점이있는 경우에만 발생합니다. 안전 벨트를 추가하는 것이 좋은 예일 것입니다. 50 년 전에 방금 들어 와서 갔지만 이제는 사고를 당했을 때 앞 유리창이나 조수석에 들어 가지 않는다는 직관적 인 이점이 있습니다. 그럼에도 불구하고 운전자들은 저항했다. 많은 자동차 소유자가 법률에 따라 사용이 의무화 될 때까지 안전 벨트를 차에서 자릅니다.

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