OOP는 실제로 어떤 절차 적 프로그래밍 문제를 해결합니까?


17

"C ++ Demystified" 책을 공부했습니다 . 이제 Robert Lafore의 "Turbo C ++ 초판 (1 판)의 객체 지향 프로그래밍" 을 읽기 시작했습니다 . 이 책을 넘어서는 프로그래밍에 대한 지식이 없습니다. 이 책은 20 살이 기 때문에 구식 일 수 있습니다. 나는 최신판을 가지고 있는데, 나는 그것을 좋아하기 때문에 오래된 것을 사용하고 있습니다. 주로 저는 Lafore의 책의 첫 번째 판을 통해 C ++에서 사용되는 OOP의 기본 개념을 연구하고 있습니다.

Lafore의 책은 "OOP는"인 경우에만 유용 강조 복잡한 프로그램. 모든 OOP 서적 (또한 Lafore의 서적에서도)에서 절차 적 패러다임은 기능에 의해 쉽게 취약한 글로벌 데이터와 같은 오류가 발생하기 쉽다고합니다. 프로그래머는 실수로 데이터를 손상시키는 기능을 만들어서 절차 언어에서 정직한 오류를 만들 수 있다고합니다 .

: 솔직히 나는 내가이 책에서 주어진 explaination 파악하고 있지 않다 때문에 내 질문에 게시하고 말하기 C ++로 (4 판) 객체 지향 프로그래밍을 내가 Lafore의 책에 기록이 문을 잡고 있지 않다을 :

객체 지향 프로그래밍은 프로그래밍에 대한 초기 접근 방식에서 한계가 발견 되었기 때문에 개발되었습니다 .... 프로그램이 점점 더 복잡해지고 복잡 해짐에 따라 구조화 된 프로그래밍 접근 방식조차 변형의 징후를 보이기 시작합니다 ... .... 이유 분석 이러한 실패는 절차 적 패러다임 자체에 약점이 있음을 보여준다. 구조화 된 프로그래밍 방식이 아무리 잘 구현 되더라도 큰 프로그램은 지나치게 복잡해집니다. ... ... 두 가지 관련 문제가 있습니다. 첫째, 함수는 전역 데이터에 제한없이 액세스 할 수 있습니다. 둘째, 절차 적 패러다임의 기초 인 관련없는 기능과 데이터는 현실 세계의 열악한 모델을 제공합니다.

나는 Jeff Kent의 "dysmystified C ++"라는 책을 연구했습니다.이 책을 매우 좋아합니다.이 책에서는 대부분 절차 적 프로그래밍이 설명되어 있습니다. 절차 적 (structured) 프로그래밍이 왜 약한 지 이해가되지 않습니다!

Lafore의 책은 좋은 예를 통해 개념을 아주 잘 설명합니다. 또한 OOP가 절차 적 프로그래밍보다 낫다는 Lafore의 책을 읽음으로써 직관을 파악했지만 실제로 절차 적 프로그래밍이 OOP보다 얼마나 약한 지 알고 싶습니다.

절차 적 프로그래밍에서 직면 할 실질적인 문제가 무엇인지, OOP가 프로그래밍을 쉽게 만드는 방법을 직접보고 싶습니다. 나는 Lafore의 책을 명상적으로 읽음으로써 대답을 얻을 것이라고 생각하지만 절차 코드의 문제를 내 눈으로보고 싶습니다. 동일한 프로그램이 절차 적 패러다임을 사용하여 작성되었습니다.

OOP에는 많은 기능이 있으며 누군가가 이러한 모든 기능이 절차 스타일로 코드를 작성하여 발생하는 전술 한 오류를 어떻게 제거하는지 설명 할 수 없다는 것을 알고 있습니다.

그래서, 여기 내 질문이 있습니다 :

OOP는 어떤 절차 적 프로그래밍의 한계를 해결하며 실제로 이러한 한계를 어떻게 효과적으로 제거합니까?

특히 절차 적 패러다임을 사용하여 설계하기는 어렵지만 OOP를 사용하여 쉽게 설계 할 수있는 프로그램의 예가 있습니까?

추신 : 십자가에서 게시 : https : //.com/q/22510004/3429430


3
절차 적 프로그래밍과 객체 지향 프로그래밍의 구별은 어느 정도까지는 프레젠테이션과 강조의 문제입니다. 객체 지향으로 광고하는 대부분의 언어도 절차 적입니다. 용어는 언어의 다른 측면을 나타냅니다.
Gilles 'SO- 악의를 멈춰라'

2
나는 지금 질문을 다시 열었다. 어떻게되는지 보자. OOP를 제공하는 모든 처리는 성배이며, 모든 문제를 해결하는 프로그래밍 언어의 메시아는 말도 안되는 소리입니다. 찬반 양론이 있습니다. 당신은 전문가를 요구하고 있습니다. 그것은 공정한 질문입니다. 더 이상 기대하지 마십시오.
Raphael

OOP없이 (현대적인) 데스크탑 GUI를 디자인한다는 생각과 그에 따라 성장한 기술 (예 : 이벤트 / 리스너 패턴)은 무섭습니다. 그렇다고 할 수는 없습니다 (확실히 할 수 있습니다 ). 또한 직장에서 PP의 실패를보고 싶다면 PHP를보고 API를 Ruby와 비교하십시오.
Raphael

1
또한 매우 사실 OOP의입니다 "구조화 된 프로그래밍 접근 방식이 구현 얼마나 잘 상관없이, 큰 프로그램은 ... 지나치게 복잡하게"하지만 기본적으로 더 복잡성을 관리하지 개발자에 의해 규정 된 방법으로 적용하면 ... 및 수행 그것은 더 나은 / 날카로운 범위 경계 / 제한, 즉 일종의 구획화 시스템을 통해 ... APIE : 추상화, 다형성, 상속, 캡슐화
vzn

답변:


9

절차 적 언어에서는 호출자가 지원되는 방식으로 모듈을 사용하고 있음을 증명하는 데 필요한 제한 사항을 반드시 표현할 수는 없습니다. 컴파일러에서 확인할 수있는 제한이없는 경우 문서를 작성하고이를 준수하기를 바라며 단위 테스트를 사용하여 의도 된 용도를 시연해야합니다.

타입 선언은 가장 명백한 선언 제한입니다 (예 : "x가 부동 소수점임을 증명합니다"). 데이터 돌연변이가 해당 데이터를 위해 설계된 것으로 알려진 기능을 통과하도록하는 것은 또 다른 일입니다. 프로토콜 시행 (메소드 호출 순서)은 부분적으로 지원되는 또 다른 제한 사항입니다. "constructor-> othermethods *-> ​​destructor".

컴파일러가 패턴에 대해 알고 있으면 실질적인 이점과 몇 가지 단점이 있습니다. 다형성 유형의 정적 입력은 절차 언어에서 데이터 캡슐화를 에뮬레이션 할 때 약간 문제가됩니다. 예를 들면 다음과 같습니다.

x1 유형은 x의 하위 유형이고, t1은 t의 하위 유형입니다.

이것은 메소드 f 및 g를 사용하여 유형 t를 갖도록 프로 시저 언어로 데이터를 캡슐화하는 한 가지 방법이며 다음과 같은 서브 클래스 t1입니다.

t_f (t, x, y, z, ...), t_g (t, x, y, ...) t1_f (t1, x, y, z, ...)

이 코드를 그대로 사용하려면 호출 할 f의 종류를 결정하기 전에 형식 검사를 수행하고 t의 유형을 켜야합니다. 다음과 같이 해결할 수 있습니다.

타입 t {d : 데이터 f : 함수 g : 함수}

따라서 대신 tf (x, y, z)를 호출하면 메소드를 찾기위한 typecheck 및 switch가 이제 각 인스턴스 스토어 메소드 포인터를 명시 적으로 갖는 것으로 대체됩니다. 유형별로 많은 수의 기능이 있다면 이것은 낭비적인 표현입니다. 그런 다음 모든 멤버 함수를 포함하는 변수 m을 가리키는 것과 같은 다른 전략을 사용할 수 있습니다. 이 기능이 언어의 일부인 경우 컴파일러가이 패턴을 효율적으로 표현하는 방법을 알아낼 수 있습니다.

그러나 데이터 캡슐화는 변경 가능한 상태가 나쁘다는 인식입니다. 객체 지향 솔루션은 메소드 뒤에 숨기는 것입니다. 이상적으로, 객체의 모든 메소드는 잘 정의 된 호출 순서를 갖습니다 (예 : constructor-> open-> [read | write]-> close-> destruct); 때로는 '프로토콜'(연구 : "Microsoft Singularity")이라고도합니다. 그러나 이러한 요구 사항은 일반적으로 구성 및 파괴 외에 유형 시스템의 일부가 아니거나 잘 문서화되어 있습니다. 이런 의미에서 객체는 메소드 호출에 의해 전환되는 상태 머신의 동시 인스턴스입니다. 여러 인스턴스가있을 수 있으며 임의로 인터리브 된 방식으로 사용할 수 있습니다.

그러나 변경 가능한 공유 상태가 나쁘다는 것을 인식 할 때 개체 데이터 구조가 많은 개체가 참조하는 변경 가능한 상태이기 때문에 개체 방향이 동시성 문제를 일으킬 수 있음을 알 수 있습니다. 대부분의 객체 지향 언어는 호출자의 스레드에서 실행되는데, 이는 메소드 호출에 경쟁 조건이 있음을 의미합니다. 비원 자적 함수 호출 시퀀스에서는 물론입니다. 다른 방법으로, 모든 객체는 대기열에서 비동기 메시지를 가져 와서 객체의 스레드 (개인 메서드를 사용하여)에서 모두 서비스하고 메시지를 보내 호출자에게 응답 할 수 있습니다.

다중 스레드 컨텍스트에서 Java 메소드 호출을 비교하여 (불변 값만 참조하는) 메시지를 서로 보내는 Erlang 프로세스와 비교하십시오.

병렬화와 결합 된 무제한 객체 방향은 잠금으로 인해 문제가됩니다. 소프트웨어 트랜잭션 메모리 (예 : 데이터베이스와 유사한 메모리 개체의 ACID 트랜잭션)에서 "통신 (불변의 데이터)에 의한 메모리 공유"(기능 프로그래밍 하이브리드) 접근 방식에 이르기까지 다양한 기술이 있습니다.

내 의견으로는, Object Orientation 문헌은 FAR에 상속에 너무 집중하고 프로토콜 (확인 가능한 메소드 호출 순서, 전제 조건, 사후 조건 등)에는 충분하지 않습니다. 객체가 소비하는 입력에는 일반적으로 유형으로 표현할 수있는 잘 정의 된 문법이 있어야합니다.


OO 언어에서 컴파일러는 메소드가 규정 된 순서로 사용되는지 또는 모듈 사용에 대한 다른 제한 사항을 사용할 수 있는지 확인할 수 있습니까? 왜 "변경 가능 상태가 좋지 않다는 데이터 캡슐화 [...] 인식"입니까? 다형성에 대해 이야기 할 때 OO 언어를 사용한다고 가정합니까?
babou

OO에서 가장 중요한 기능은 모든 액세스가 메소드를 통과 함을 증명하기 위해 데이터 구조를 숨길 수 있다는 것입니다 (예 : this.x와 같은 참조가 필요함). 정적으로 형식화 된 OO 언어에서는 유형에 따라 더 많은 제한을 선언합니다. 메소드 순서에 대한 메모는 단지 OO가 생성자를 먼저 호출하고 소멸자를 마지막으로 호출한다고 말합니다. 이는 나쁜 전화 주문을 구조적으로 금지하는 첫 번째 단계입니다. 쉬운 증거는 언어 디자인에서 중요한 목표입니다.
Rob

8

절차 / 함수 프로그래밍은 튜링 인수 (내 언어가 튜링 파워를 가지고 있고 다른 언어로 할 수있는 일을 할 수 있음)에 들어 가지 않아도 OOP보다 약하지 않습니다. 실제로 객체 지향 기술은 기본적으로 내장되어 있지 않은 언어로 실험되었습니다. 이런 의미에서 OO 프로그래밍은 절차 적 프로그래밍의 특정 스타일 일뿐 입니다. 그러나 프로그램 이해 및 유지 관리에 필수적인 모듈화, 추상화 및 정보 숨기기와 같은 특정 분야를 시행하는 데 도움이됩니다 .

일부 프로그래밍 패러다임은 이론적 인 계산 비전에서 발전합니다. 리스프 (Lisp)와 같은 언어는 람다 미적분과 언어 의 메타 순환 개념 (자연 언어의 반사와 유사) 에서 발전했습니다 . 혼절은 프롤로그 및 구속 조건 프로그래밍의 아버지가되었습니다. Algol 가족은 또한 람다 미적분학에 기인하지만 반사 기능이 내장되어 있지 않습니다.

Lisp는 많은 프로그래밍 언어 혁신의 테스트 베드가 되었기 때문에 흥미로운 예입니다. 이는 이중 유전자 유산으로 추적 할 수 있습니다.

그러나 언어는 종종 새로운 이름으로 발전합니다. 진화의 주요 요소는 프로그래밍 연습입니다. 사용자는 가독성, 유지 보수성, 정확성의 입증과 같은 프로그램의 속성을 향상시키는 프로그래밍 방법을 식별합니다. 그런 다음 프로그램의 품질을 향상시키기 위해 이러한 관행을 지원하고 때로는 시행 할 언어 기능 또는 제약 조건에 추가하려고합니다.

이것은 구식 프로그래밍 언어에서 이러한 관행이 이미 가능하지만이를 사용하려면 이해와 훈련이 필요하다는 의미입니다. 특정 구문을 사용하여 주요 언어로 새로운 언어로 이들 언어를 통합하면 특히 덜 복잡한 사용자 (예 : 대다수)에게 이러한 관행을보다 쉽게 ​​사용하고 쉽게 이해할 수 있습니다. 또한 정교한 사용자에게는 삶이 조금 더 쉬워집니다.

어떤 방식으로, 그것은 서브 프로그램 / 기능 / 프로 시저가 프로그램에 대한 언어 디자인입니다. 유용한 개념이 식별되면 이름과 구문이 주어 지므로 해당 언어로 개발 된 모든 프로그램에서 쉽게 사용할 수 있습니다. 그리고 성공하면 미래 언어에도 통합 될 것입니다.

예 : 객체 방향 재 작성

이제 예를 들어 설명하려고합니다 (시간이 주어지면 더 연마 될 수 있습니다). 이 예제의 목적은 객체 지향 프로그램이 절차 적 프로그래밍 스타일로 작성 될 수 있음을 보여주기위한 것이 아니며, 아마도 책임과 유지 관리 성을 희생합니다. 차라리 OO 기능이없는 일부 언어는 실제로 고차원 함수와 데이터 구조를 사용하여 실제로 객체 지향을 효과적으로 모방하는 수단을 만들어 모듈화, 추상화 및 정보 숨기기를 포함한 프로그램 구성과 관련된 품질의 이점을 얻을 있음을 보여 주려고 노력합니다. .

내가 말했듯이, Lisp는 OO 패러다임을 포함하여 많은 언어 진화의 시험대였습니다. Lisp은 매우 간단하며 기본 인터프리터의 코드는 페이지보다 작습니다. 그러나 Lisp에서 OO 프로그래밍을 할 수 있습니다. 고차 함수 만 있으면됩니다.

나는 표현을 단순화하기 위해 난해한 Lisp 구문 대신 의사 코드를 사용합니다. 그리고 정보 숨기기모듈화 라는 간단한 필수 문제를 고려할 것 입니다. 사용자가 구현에 대부분 액세스하지 못하도록하면서 객체 클래스를 정의합니다.

벡터 추가, 벡터 크기 및 병렬 처리와 같은 메서드를 사용하여 2 차원 벡터를 나타내는 vector라는 클래스를 만들고 싶다고 가정합니다.

function vectorrec () {  
  function createrec(x,y) { return [x,y] }  
  function xcoordrec(v) { return v[0] }  
  function ycoordrec(v) { return v[1] }  
  function plusrec (u,v) { return [u[0]+v[0], u[1]+v[1]] }  
  function sizerec(v) { return sqrt(v[0]*v[0]+v[1]*v[1]) }  
  function parallelrec(u,v) { return u[0]*v[1]==u[1]*v[0]] }  
  return [createrec, xcoordrec, ycoordrec, plusrec, sizerec, parallelrec]  
  }  

그런 다음 생성 된 벡터를 사용할 실제 함수 이름에 할당 할 수 있습니다.

[벡터, xcoord, ycoord, vplus, vsize, vparallel] = vectorclass ()

왜 그렇게 복잡합니까? 함수에서 vectorrec 매개체 구성을 정의 할 수 있기 때문에 모듈화를 유지하기 위해 나머지 프로그램에서 볼 수 없도록하고 싶습니다.

극좌표로 다른 컬렉션을 만들 수 있습니다

function vectorpol () {  
  ...  
  function pluspol (u,v) { ... }  
  function sizepol (v) { return v[0] }  
  ...  
  return [createpol, xcoordpol, ycoordpol, pluspol, sizepol, parallelpol]  
  }  

그러나 두 구현을 모두 무관심하게 사용하고 싶을 수도 있습니다. 한 가지 방법은 모든 값에 유형 구성 요소를 추가하여 동일한 환경에서 위의 모든 함수를 정의하는 것입니다. 그런 다음 반환 된 각 함수를 정의하여 좌표 유형을 먼저 테스트 한 다음 특정 함수를 적용 할 수 있습니다 그것을 위해.

function vector () {  
    ...  
    function plusrec (u,v) { ... }  
    ...  
    function pluspol (u,v) { ... }  
    ...  
    function plus (u,v) { if u[2]='rec' and v[2]='rec'  
                            then return plusrec (u,v) ... }  

    return [ ..., plus, ...]  
    }

내가 얻은 것 : 특정 함수는 (로컬 식별자 범위 지정으로 인해) 보이지 않고 남아 있으며 프로그램의 나머지는 vectorclass 호출로 반환 된 가장 추상적 인 함수 만 사용할 수 있습니다.

한 가지 반대 의견은 프로그램에서 각 추상 함수를 직접 정의하고 좌표 유형 종속 함수의 정의를 그대로 둘 수 있다는 것입니다. 그러면 숨겨 질 것입니다. 사실이지만 각 좌표 유형의 코드는 프로그램 전체에 걸쳐 작은 조각으로 잘립니다.

실제로, 나는 그들에게 이름을 줄 필요조차 없으며, 유형과 함수 이름을 나타내는 문자열에 의해 색인 된 데이터 구조에 익명의 기능 값을 유지할 수 있습니다. 함수 벡터에 국한되는이 구조는 프로그램의 나머지 부분에서는 보이지 않습니다.

사용을 단순화하기 위해 함수 목록을 반환하는 대신 apply라는 단일 함수를 명시 적으로 형식 값과 문자열을 인수로 사용하여 적절한 형식과 이름으로 함수를 적용 할 수 있습니다. 이것은 OO 클래스의 메소드를 호출하는 것과 매우 유사합니다.

객체 지향 기능의이 재구성에서 여기서 멈추겠습니다.

내가하려고했던 것은 상속 및 기타 기능을 포함하여 충분히 강력한 언어로 사용 가능한 객체 방향을 만드는 것이 너무 어렵지 않다는 것을 보여주는 것입니다. 통역사의 metacircularity는 도움이 될 수 있지만, 대부분 문법 수준에서 여전히 무시할 수있는 수준입니다.

객체 지향의 첫 사용자는 이러한 방식으로 개념을 실험했습니다. 그리고 그것은 프로그래밍 언어에 대한 많은 개선에서 일반적으로 적용됩니다. 물론 이론적 분석도 중요한 역할을하며 이러한 개념을 이해하거나 개선하는 데 도움이되었습니다.

그러나 일부 프로젝트에서 OO 기능이없는 언어가 실패 할 것이라는 생각은 단순히 보증되지 않습니다. 필요한 경우 이러한 기능의 구현을 매우 효과적으로 모방 할 수 있습니다. 많은 언어는 객체 지향이 내장되어 있지 않더라도 객체 지향을 매우 효과적으로 수행 할 수있는 구문 및 의미 론적 힘을 가지고 있습니다. 그리고 그것은 튜링 논쟁 이상의 것입니다.

OOP는 다른 언어의 제한 사항을 다루지 않지만 더 나은 프로그램을 작성하는 데 도움이되는 프로그래밍 방법론지원하거나 시행 하므로 경험이 적은 사용자가 더 많은 고급 프로그래머가 해당 지원없이 사용하고 개발 한 모범 사례를 따르는 데 도움이됩니다.

이 모든 것을 이해하기위한 좋은 책은 Abelson & Sussman : 컴퓨터 프로그램의 구조와 해석 일 것입니다 .


8

약간의 역사가 순서대로 있다고 생각합니다.

1960 년대 중반에서 1970 년대 중반까지의 시대는 오늘날 "소프트웨어 위기"로 알려져 있습니다. 1972 년 튜링 상 강연에서 Dijkstra보다 더 나을 수는 없습니다.

소프트웨어 위기의 주요 원인은 기계가 몇 배나 더 강력 해 졌기 때문입니다! 기계가없는 한 프로그래밍은 전혀 문제가되지 않았다. 우리가 약한 컴퓨터 몇 대를 가지고있을 때, 프로그래밍은 경미한 문제가되었고, 이제 우리는 거대한 컴퓨터를 갖게되었고, 프로그래밍도 마찬가지로 거대한 문제가되었습니다.

이것은 최초의 32 비트 컴퓨터, 최초의 진정한 멀티 프로세서 및 최초의 내장형 컴퓨터의 시대였으며, 이들은 미래 프로그래밍에 중요 할 것이라는 것이 연구원들에게 분명했습니다. 고객 수요가 처음으로 프로그래머 기능을 능가했던 것은 역사상 한 때였습니다.

놀랍지 않게도, 프로그래밍 연구에서 놀랍도록 비옥 한 시간이었습니다. 1960 년대 중반 이전에는 LISP와 AP / L이 있었지만 "기본"언어는 근본적으로 절차 적이었습니다 : FORTRAN, ALGOL, COBOL, PL / I 등. 1960 년대 중반부터 1970 년대 중반까지 우리는 Logo, Pascal, C, Forth, Smalltalk, Prolog, ML 및 Modula를 얻었고 SQL과 같은 DSL은 그 이전의 계산에 포함되지 않습니다.

또한 프로그래밍 언어 를 구현 하기위한 많은 핵심 기술 이 개발되고 있는시기이기도합니다 . 이 기간에 우리는 LR 파싱, 데이터 흐름 분석, 공통 하위 표현 제거, 그리고 특정 컴파일러 문제 (예 : 레지스터 할당)가 NP-hard라는 첫 번째 인식을 얻었고 그와 같은 문제를 해결하려고 시도했습니다.

이것이 OOP가 등장한 맥락입니다. 따라서 1970 년대 초반 OOP가 실제로 해결하는 문제에 대한 귀하의 질문에 대한 대답은 첫 번째 답변은 그 시대에 프로그래머가 직면했던 많은 문제 (현대 및 예상)를 해결하는 것으로 나타났습니다. 그러나 OO가 주류가 된 것은 아닙니다. 우리는 곧 그렇게 할 것입니다.

Alan Kay가 "객체 지향"이라는 용어를 만들었을 때, 그가 생각한 그림은 소프트웨어 시스템이 생물학적 시스템과 같은 구조라는 것입니다. 화학 신호 ( "메시지")와 유사한 것을 보내서 서로 상호 작용하는 개별 셀 ( "개체")과 같은 것이 있습니다. 당신은 셀 내부를 들여다 볼 수 없었습니다. 신호 경로를 통해서만 상호 작용합니다. 또한 필요한 경우 각 종류의 셀을 두 개 이상 가질 수 있습니다.

여기에는 몇 가지 중요한 주제가 있음을 알 수 있습니다. 잘 정의 된 신호 처리 프로토콜 개념 (현대 용어, 인터페이스), 외부에서 구현을 숨기는 개념 (현대 용어, 개인 정보) 및 같은 유형의 여러 "사물"을 동시에 가지고 다니는 것 (현대 용어, 인스턴스화).

당신이 주목할만한 한 가지가 빠져 있는데, 그것은 상속이며, 그 이유가 있습니다.

객체 지향 프로그래밍은 추상 개념이며, 추상 개념은 다른 프로그래밍 언어에서 다른 방식으로 구현 될 수 있습니다. 예를 들어, "메소드"의 추상 개념은 함수 포인터를 사용하여 C, 멤버 함수를 사용하는 C ++ 및 메소드를 사용하는 스몰 토크에서 구현할 수 있습니다 (Smalltalk는 추상 개념을 거의 직접 구현하므로 놀랍지 않아야합니다). 이것은 사람들이 (거의) 어떤 언어로든 OOP를 "할 수"있다고 지적하는 것입니다.

반면에 상속은 구체적인 프로그래밍 언어 기능입니다. 상속은 OOP 시스템을 구현하는 데 유용 할 수 있습니다. 또는 적어도 1990 년대 초까지는이 경우였습니다.

1980 년대 중반에서 1990 년대 중반까지의 시간은 또한 상황이 바뀌는 역사의 시간이기도합니다. 이 기간 동안 우리는 값 비싼 유비쿼터스 32 비트 컴퓨터가 등장하여 기업과 많은 가정에서 하루 종일 가장 낮은 메인 프레임만큼 강력한 컴퓨터를 모든 책상에 설치할 수있었습니다. 또한 현대의 GUI와 네트워크 운영 체제의 출현시기이기도했습니다.

이러한 맥락에서 객체 지향 분석 및 디자인이 일어났다.

OOAD의 영향, "three Amigos"(Booch, Rumbar 및 Jacobson)의 작업 및 기타 (예 : Shlaer-Mellor 방법, 책임 중심 설계 등)의 영향을 과소 평가할 수 없습니다. 1990 년대 초 이후로 개발 된 대부분의 새로운 언어 (최소한, 들어 본 대부분의 언어)가 Simula 스타일의 객체를 갖는 이유입니다.

따라서 1990 년대 귀하의 질문에 대한 답변은 도메인 지향 분석 및 설계 방법론을위한 최상의 솔루션을 지원한다는 것입니다.

그 이후로, 우리는 망치를 가지고 있었기 때문에 OOP를 그 이후로 발생한 거의 모든 문제에 적용했습니다. OOAD와 그것이 사용한 객체 모델은 민첩하고 테스트 중심의 개발, 클러스터 및 기타 분산 시스템 등을 장려하고 가능하게했습니다.

지난 20 년 동안 디자인 된 최신 GUI와 운영 체제는 서비스를 객체로 제공하는 경향이 있으므로 새로운 실제 프로그래밍 언어는 최소한 오늘날 우리가 사용하는 시스템에 바인딩 할 수있는 방법이 필요합니다.

따라서 현대의 대답은 현대 세계와의 인터페이스 문제를 해결하는 것입니다. 현대 세계는 1880 년의 세계가 증기를 기반으로했던 것과 같은 이유로 OOP를 기반으로합니다.

물론 여기에서 연구가 중단된다는 것은 아니지만, 새로운 기술이 제한적 사례로 OO가 필요하다는 것을 강력하게 나타냅니다. OO 일 필요는 없지만 근본적으로 호환되지 않을 수 있습니다.


내가 주요 에세이에 넣고 싶지 않은 한 가지 측면은 WIMP GUI와 OOP가 매우 자연스러운 것으로 보인다는 것입니다. 깊은 상속 계층 구조에 대해 많은 나쁜 점을 말할 수 있지만 이것은 일종의 이해가되는 상황 (아마도 유일한 상황)입니다.
가명

1
OOP는 운영 체제의 내부 조직 에서 Simula-67 (시뮬레이션) 에서 처음으로 나타났습니다 (유닉스에서 "장치 클래스"라는 개념은 본질적으로 드라이버가 상속하는 클래스입니다). Parnas의 "시스템을 모듈로 분해하는 데 사용되는 기준" , CACM 15:12 (1972), pp. 1052-1058, 70 년대 Wirth의 Modula 언어, "추상 데이터 유형"은 모두 하나의 방식 또는 다른.
vonbrand

그것은 사실이지만, OOP가 70 년대 중반까지 "절차 프로그래밍 문제에 대한 해결책"으로 여겨지지 않았다고 주장합니다. "OOP"를 정의하는 것은 매우 어렵다. Alan Kay의 원래 용어 사용은 Simula의 모델과 일치하지 않으며 불행히도 세계는 Simula의 모델을 표준화했습니다. 일부 객체 모델에는 Curry-Howard와 같은 해석이 있지만 Simula는 그렇지 않습니다. Stepanov는 상속이 부적절하다고 언급했을 때 아마도 정확했을 것입니다.
가명

6

정말이지 OOP는 실제로 문제를 해결하지는 않습니다. 엄밀히 말하면; 비 객체 지향 시스템으로는 할 수 없었던 객체 지향 시스템으로는 할 수있는 일은 없습니다. 실제로 튜링 머신으로는 할 수 없었던 것에는 할 수있는 것이 없습니다. 결국 모두 머신 코드로 바뀌고 ASM은 확실히 객체 지향적이지 않습니다.

OOP 패러다임의 역할은 변수와 함수를보다 쉽게 ​​구성 할 수있게 해주 며보다 쉽게 ​​서로 이동할 수있게하는 것입니다.

파이썬으로 카드 게임을 만들고 싶다고 가정 해보십시오. 카드는 어떻게 대표합니까?

OOP에 대해 모른다면 다음과 같이 할 수 있습니다.

cards=["1S","2S","3S","4S","5S","6S","7S","8S","9S","10S","JS","QS","KS","1H","2H",...,"10C","JC","QC","KC"]

카드를 직접 작성하는 대신 카드를 생성하는 코드를 작성했을 것입니다.하지만 요점을 알 수 있습니다. "1S"는 스페이드 1을 나타내고 "JD"는 다이아몬드 잭을 나타냅니다. 또한 Joker를위한 코드가 필요하지만 지금은 Joker가없는 것처럼 가장합니다.

이제 덱을 섞고 싶을 때 목록을 "셔플"만하면됩니다. 그런 다음 덱 맨 위에서 카드를 꺼내기 위해 목록에서 맨 위 항목을 꺼내서 줄을주었습니다. 단순한.

이제 플레이어에게 표시 할 목적으로 어떤 카드를 사용하고 있는지 알아 내려면 다음과 같은 기능이 필요합니다.

def card_code_to_name(code):
    suit=code[1]

    if suit=="S":
        suit="Spades"
    elif suit=="H"
        suit="Hearts"
    elif suit=="D"
        suit="Diamonds"
    elif suit=="C"
        suit="Clubs"

    value=code[0]

    if value=="J":
        value="Jack"
    elif value="Q":
        value="Queen"
    elif value="K"
        value="King"

    return value+" of "+suit

조금 크고 길고 비효율적이지만 작동합니다 (매우 비현실적이지만 여기서 요점입니다).

카드를 화면에서 움직일 수있게하려면 어떻게해야합니까? 어떻게 든 그들의 위치를 ​​저장해야합니다. 카드 코드 끝에 추가 할 수는 있지만 조금 다루기 어려울 수 있습니다. 대신, 각 카드의 위치를 ​​다른 목록으로 만들어 봅시다 :

cardpositions=( (1,1), (2,1), (3,1) ...)

그런 다음 목록에서 각 카드의 위치 색인이 갑판의 카드 자체 색인과 동일하도록 코드를 작성합니다.

아니면 적어도 그래야합니다. 내가 실수하지 않으면 내 코드는이 설정을 처리하기 위해 다소 복잡해야하기 때문에 매우 잘 할 수 있습니다. 카드를 셔플하려면 위치를 같은 순서로 셔플해야합니다. 갑판에서 카드를 완전히 꺼내면 어떻게됩니까? 나는 또한 그 입장을 취하고 다른 곳으로 옮겨야 할 것이다.

카드에 대한 더 많은 정보를 저장하려면 어떻게해야합니까? 각 카드가 뒤집혀 있는지 여부를 저장하려면 어떻게합니까? 어떤 종류의 물리 엔진을 원하고 카드 속도도 알아야한다면 어떻게해야합니까? 각 카드의 그래픽을 저장하려면 완전히 다른 목록이 필요합니다! 그리고 이러한 모든 데이터 포인트에 대해 각 카드가 어떻게 든 모든 데이터에 매핑되도록 모든 코드 포인트를 올바르게 구성하려면 별도의 코드가 필요합니다!

이제 이것을 OOP 방식으로 시도해 봅시다.

코드 목록 대신 Card 클래스를 정의하고 그로부터 Card 객체 목록을 작성해 봅시다.

class Card:

    def __init__(self,value,suit,pos,sprite,flipped=False):
        self.value=value
        self.suit=suit
        self.pos=pos
        self.sprite=sprite
        self.flipped=flipped

    def __str__(self):
        return self.value+" of "+self.suit

    def flip(self):
        if self.flipped:
            self.flipped=False
            self.sprite=load_card_sprite(value, suit)
        else:
            self.flipped=True
            self.sprite=load_card_back_sprite()

deck=[]
for suit in ("Spades","Hearts","Diamonds","Clubs"):
    for value in ("1","2","3","4","5","6","7","8","9","10","Jack","Queen","King"):
        sprite=load_card_sprite(value, suit)
        thecard=Card(value,suit,(0,0),sprite)
        deck.append(thecard)

이제 갑자기 모든 것이 훨씬 간단 해졌습니다. 카드를 옮기려면 카드가 어디에 있는지 알아낼 필요가 없습니다. 그런 다음 카드를 사용하여 위치를 배열에서 빼냅니다. 그냥 말해야 해요thecard.pos=newpos 해요. 메인 데크 목록에서 카드를 꺼낼 때 다른 모든 데이터를 저장하기 위해 새 목록을 만들 필요는 없습니다. 카드 객체가 이동하면 모든 속성이 함께 이동합니다. 뒤집을 때 다르게 동작하는 카드를 원한다면, 메인 코드에서 뒤집기 기능을 수정하지 않아도 카드를 감지하고 다른 동작을 수행 할 수 있습니다. 카드를 서브 클래 싱하고 서브 클래스에서 flip () 함수를 수정하면됩니다.

그러나 OO 없이는 할 수 없었습니다. 단지 객체 지향 언어를 사용하면 언어가 당신을 위해 일을 함께 유지하는 많은 일을하고 있습니다. 즉 실수를 할 기회가 훨씬 적고 코드가 더 짧고 읽기 쉽고 쓰기 쉽습니다.

또는 훨씬 더 요약하자면, OO를 사용하면 추상화의 베일 뒤에 데이터를 처리하는 일반적인 복잡성을 많이 숨겨보다 복잡한 프로그램과 동일한 작업을 수행하는보다 단순한 프로그램을 작성할 수 있습니다.


1
OOP에서 빼앗은 유일한 것이 "메모리 관리"인 경우에는이를 잘 이해하지 못했다고 생각합니다. 거기에는 전체 디자인 철학과 "디자인에 따른 올바른"병이 있습니다! 또한 메모리 관리는 객체 지향 (C ++?)에 내재 된 것이 아니며, 그 필요성이 더욱 뚜렷 해지더라도 마찬가지입니다.
Raphael

물론, 그것은 한 문장 버전입니다. 그리고 나는 비표준적인 방법으로이 용어를 사용했습니다. 아마도 "메모리 관리"보다 "정보 처리"라고 말하는 것이 좋습니다.
Schilcote

함수가 무언가에 대한 포인터뿐만 아니라 첫 번째 매개 변수가 같은 종류의 것에 대한 포인터 인 함수에 대한 포인터를 가져 와서 컴파일러가 함수가 적절한 지 확인하도록하는 비 OOP 언어가 있습니까? 전달 된 포인터?
supercat

3

몇 년 동안 장치, 직렬 포트 및 직렬 포트, 네트워크 포트 및 서버 간의 통신 패킷과 같은 것을 관리하는 내장 C를 작성했습니다. 나는 절차 적 프로그래밍 경험이 제한된 훈련 된 전기 기술자 인 나 자신을 발견했다. 나중에 하드웨어에서 내 자신의 추상화를 구체화했다.

서버쪽으로 옮길 때 인스턴스화 할 때 메모리에 각 장치의 객체 표현을 설정하는 팩토리에 노출되었습니다. 나는 단어 나 처음에 무슨 일이 일어나고 있는지 이해하지 못했습니다. 나는 그와 같은 파일에 가서 코드를 작성한다는 것을 알았습니다. 나중에 다시 OOP의 가치를 깨닫게되었습니다.

나는 개인적으로 이것이 객체 지향을 가르치는 유일한 방법이라고 생각합니다. 나는 신입생 1 학년에 OOP (자바) 소개 수업을 받았으며 완전히 내 머리 위로 끝났습니다. 새끼 고양이-> 고양이-> 포유류-> 살아있는-> 물건 또는 잎-> 가지-> 나무-정원분류 한 OOP 설명 은 아무도 겸손한 방법으로 절대 그 말을 해결하려고 시도하지 않기 때문에 절대적으로 어리석은 방법론입니다. 문제 라고 할 수 있다면 ...

나는 '무엇을 해결 하는가'가 아니라 '여기에 문제가 있으며 더 쉽게 만드는 방법'이라는 관점 에서 더 절대적인 용어로 질문에 대답하는 것이 더 쉽다고 생각합니다 . 내 특정 직렬 포트의 경우 직렬 포트를 정적으로 열고 닫는 코드를 추가하고 제거하는 많은 컴파일 타임 #ifdef가 있습니다. 포트 열기 기능은 모든 곳에서 호출되었으며 우리가 가진 100k 라인의 OS 코드 어디에나 위치 할 수 있으며 IDE는 정의되지 않은 것을 회색으로 표시하지 않았습니다. 수동으로 추적해야했습니다. 당신의 머리에 가지고 다니십시오. 필연적으로 다른 쪽 끝에서 장치를 기대하는 특정 직렬 포트를 열려고하는 여러 작업 이있을 수 있으며 방금 작성한 코드가 작동하지 않아 이유를 알 수 없습니다.

추상화는 여전히 C에 있지만 직렬 포트 '클래스'(물론 구조 데이터 유형)로, 각 직렬 포트에 대해 하나의 배열을 가졌으며 대신 [직렬 포트에서 DMA 상당]을 갖습니다. "OpenSerialPortA"는 "작업에서 하드웨어에서 직접 호출 SetBaudRate"등의 기능을, 우리는 당신이 모든 통신 매개 변수 (전송, 패리티 등)에 통과하는 도우미 함수라고 먼저 있는지 확인하기 위해 구조 배열을 확인 포트가 이미 열려있는 경우 (해당되는 경우 어떤 작업을 통해 디버그 인쇄로 알려줄 수 있으므로 비활성화해야하는 코드 섹션으로 즉시 이동할 수 있으며, 그렇지 않은 경우 설정을 계속 진행 함) HAL 어셈블리 기능을 통해 모든 매개 변수를 설정하고 마침내 포트를 열었습니다.

물론 OOP에도 위험이 있습니다. 마지막으로 해당 코드베이스를 정리하고 모든 것을 깔끔하고 깔끔하게 만들었을 때, 해당 제품군의 새 드라이버를 작성하는 것은 계산이 가능하고 예측 가능한 과학이되었습니다. 그는 관리가 용이 ​​한 중간 관리직이었습니다. 어느 것이 나를 많이 빼앗 았습니다 / 나는 매우 낙담하여 직장을 그만 두었습니다. LOL.


1
안녕하세요! 이것은 질문에 대한 답변보다 개인적인 역사와 비슷합니다. 귀하의 예에서, 객체 지향 스타일로 끔찍한 코드를 다시 작성하여 더 좋게 만들었습니다. 그러나 개선이 객체 지향과 관련이 있는지 또는 그 당시에 더 숙련 된 프로그래머 였는지 확실하지 않습니다. 예를 들어, 문제의 상당 부분은 장소에 대해 코드가 흩어져있는 것 같습니다. 객체가 전혀없는 절차 라이브러리를 작성하여 해결할 수있었습니다.
David Richerby

2
@DavidRicherby 우리는 절차 라이브러리를 가지고 있었지만 그것이 우리가 더 이상 사용하지 않는 것입니다. 요점은 우리가 이것을 거꾸로했다는 것입니다. 아무도 아무것도 OOP하려고하지 않았습니다, 그것은 자연스럽게 일어났습니다.
pa :

@DavidRicherby 절차 적 라이브러리 구현의 예를 제공하여 동일한 내용에 대해 이야기하고 있는지 확인할 수 있습니까?
pa :

2
답변과 +1에 감사드립니다. 오래 전에 경험이 많은 다른 프로그래머가 OOP가 어떻게 자신의 프로젝트를보다 신뢰할 수있게 만들 었는지 포럼을 공유했습니다 .
user31782

2

OOP 프로그래밍이 발명자 및 사용자를 포함하여 절차 적 프로그래밍에 비해 장점 / 위치가 무엇인지에 대한 많은 주장의도 가 있습니다. 그러나 디자이너가 특정 목적을 위해 기술을 설계 했기 때문에 해당 목표에서 성공할 것이라고 보장하지는 않습니다 . 이것은 OOP 코딩 혁명에도 불구하고 Brooks의 유명한 에세이 "No silver bullet" 과 데이트를하는 소프트웨어 엔지니어링 분야의 주요 이해입니다 . ( 신기술에 대해서는 Gartner Hype Cycle 도 참조하십시오 .)

두 가지를 모두 사용하는 많은 사람들은 일화 적 경험에 대한 의견 을 가지고 있으며 이것은 가치가 있지만 많은 과학 연구에서 자체보고 분석이 부정확 할 수 있다고 알려져 있습니다. 이러한 차이에 대한 정량적 분석 이 거의없는 것 같거나 존재한다면 그렇게 많이 인용되지 않습니다. 많은 컴퓨터 방법 다소 놀라운 과학자들이 자신의 분야의 중심이 특정 주제에 정식 말을 아직 실제로 인용하지 않는 과학적 연구를 자신의 견해를 지원하고 그들이 실제로에 전달하는 인식하지 못하고 자신의 분야에서 기존의 지혜 (이기는하지만 널리 ).

이 사이트 는 과학 사이트 / 포럼이므로 여기에 많은 의견제시 하고 실제 차이를 정량화 하려는 간단한 시도가 있습니다. 다른 연구가있을 수 있으며 다른 사람들이 들었을 때 지적 할 수 있기를 바랍니다. (젠 질문 : 실제로 큰 차이가 있고 상용 소프트웨어 엔지니어링 분야와 그 밖의 다른 분야에서 많은 노력이 그것을 실현하기 위해 적용 / 투자 된 경우, 왜 이것에 대한 과학적 증거를 얻기가 어려워 야합니까? 차이를 확실하게 정량화하는 분야에서 고전적이고 인용이 많은 참고 자료?)

이 논문은 실험적 / 정량적 / 과학적 분석을 채택 하며, 특히 초보자 프로그래머의 이해가 OOP 코딩 방법 으로 개선 되었지만 다른 경우에는 결정적이지 않다는 것을지지한다 (프로그램 규모에 비해). 이것은 OOP 우위가 다른 답변 및 OOP 옹호자에 의해 진행되고 있다는 많은 / 주요 주장 중 하나 일뿐 입니다. 이 연구는 아마도 "인지 부하 / 오버 헤드" wrt 코딩 이해 로 알려진 심리적 요소를 측정하고 있었다 .

  • 컴퓨터와 상호 작용 하는 초보자 프로그래머에 의한 객체 지향 및 절차 적 프로그램의 이해를 비교 합니다. 수잔 비 덴벡, Vennila Ramalingam, Suseela Sarasamma, Cynthia L Corritore (1999)

    이 논문은 객체 지향 및 절차 스타일의 초보자에 의한 정신 표현과 프로그램 이해를 비교하는 두 가지 실험에 대해보고합니다. 이 과목은 초급 프로그래머로서 객체 지향적 또는 절차 적 패러다임을 가르치는 프로그래밍의 두 번째 과정에 등록했습니다. 첫 번째 실험은 절차 및 객체 지향 스타일로 작성된 짧은 프로그램의 정신 표현과 이해력을 비교했습니다. 두 번째 실험은보다 고급 언어 기능을 통합 한 더 큰 프로그램으로 연구를 확장했습니다. 짧은 프로그램의 경우 정답의 총 수와 관련하여 두 그룹간에 유의 한 차이가 없었지만, 객체 지향 과목은 프로그램 기능에 대한 질문에 대한 답변에서 절차 적 과목보다 우수했습니다. 이는 기능 정보가 프로그램을 정신적으로 표현할 때보다 쉽게 ​​이용할 수 있음을 시사하며 객체 지향 표기법이 개별 클래스 수준에서 기능을 강조한다는 주장을 뒷받침합니다. 긴 프로그램의 경우 해당 효과를 찾지 못했습니다. 절차 적 과목의 이해력은 모든 유형의 질문에서 객체 지향적 과목보다 우수했습니다. 더 큰 프로그램에서 질문에 답할 때 객체 지향적 주제가 경험하는 어려움은 정보 마샬링 및 정보 추론에 문제가 있음을 시사합니다. 이 결과는 객체 지향 스타일의 초보자뿐만 아니라 OO 스타일의 특징 및 특정 OO 언어 표기법과 관련하여 더 긴 학습 곡선과 관련이 있다고 제안합니다.

또한보십시오:


1
나는 실험 연구를 존중합니다. 그러나 그들이 올바른 질문을 다룬다는 것을 확인하는 문제가 있습니다. OOP라고 불리는 것에 너무 많은 변수가 있으며 그것을 사용하는 방법에있어서 단일 연구가 의미 있고 imho입니다. 프로그래밍의 많은 것들과 마찬가지로 OOP는 전문가들이 자신의 요구를 충족시키기 위해 만들어졌습니다 . OOP의 유용성에 대해 논의 할 때 (OP의 주제로 취하지 않았고, 절차 적 프로그래밍의 단점을 해결하는지 여부), 다음과 같은 질문을 할 수 있습니다. 그러면 현장 연구 만 완전히 의미가있게됩니다.
babou

1
일화 경고 : 문제가 작은 경우 (예 : 최대 약 500-1000 줄의 코드) OOP는 내 경험에 차이를 만들지 않으며, 차이가 거의없는 것에 대해 걱정해야 할 수도 있습니다. 문제가 크며 나중에 "추가 가능한 부분"(GUI의 창, 운영 체제의 장치 등)에 추가 할 수 있어야하는 "교환 가능한 부분"형식이있는 경우 OOP 분야가 제공 하는 조직을 피할 수 없습니다. 언어 지원없이 OOP를 프로그래밍 할 수 있습니다 (예 : Linux 커널 참조).
vonbrand

1

조심해. "객체 지향 개념, 데이터베이스 및 응용 프로그램"(Kim and Lochovsky, eds) (ACM, 1989)의 R. King "My Cat is Object-Oriented"고전을 읽으십시오. "객체 지향"은 명확한 개념보다 더 화제가되었습니다.

게다가, 주제에는 공통점이 거의없는 많은 변형이 있습니다. 프로토 타입 기반 언어 (상속은 객체에서 파생되며 클래스는 없습니다)와 클래스 기반 언어가 있습니다. 다중 상속을 허용하는 언어가 있고 그렇지 않은 언어가 있습니다. 일부 언어에는 Java 인터페이스와 같은 아이디어가 있습니다 (물을 여러 번 상속받은 형태로 볼 수 있음). 믹스 인에 대한 아이디어가 있습니다. 상속은 다소 엄격하거나 (C ++에서와 같이 하위 클래스에서 얻는 것을 실제로 변경할 수 없음) 매우 자유롭게 처리 할 수 ​​있습니다 (Perl에서 하위 클래스는 거의 모든 것을 재정의 할 수 있음). 일부 언어에는 상속을위한 단일 루트 (일반적으로 기본 동작을 가진 Object라고 함)가 있으며, 다른 언어에서는 프로그래머가 여러 트리를 만들 수 있습니다. 어떤 언어는 "모든 것이 하나의 개체"라고 주장하고 다른 언어는 개체와 비 개체를 처리합니다. Java와 같은 일부는 "대부분은 객체이지만이 유형은 그렇지 않습니다". 일부 언어는 객체에서 상태의 엄격한 캡슐화를 주장하고 다른 언어는 선택 사항 (C ++ '비공개, 보호, 공개)으로 만들고 다른 언어는 캡슐화가 전혀 없습니다. Scheme과 같은 언어를 직각으로 움켜 쥐면 특별한 노력없이 OOP가 내장되어 있습니다 (일부 로컬 상태를 캡슐화하는 함수를 반환하는 함수를 정의 할 수 있음).


0

간결한 객체 지향 프로그래밍은 절차 적 프로그래밍에 존재하는 데이터 보안 문제를 해결합니다. 이는 데이터 캡슐화 개념을 사용하여 합법적 인 클래스 만 데이터를 상속 할 수 있도록합니다. 액세스 수정자는이 목표 달성을 용이하게합니다. 희망이 있습니다. :)


절차 적 프로그래밍에 존재하는 데이터 보안 문제는 무엇입니까?
user31782

절차 적 프로그래밍에서는 전역 변수의 사용을 제한 할 수 없습니다. 모든 함수는 그 값을 사용할 수 있습니다. 그러나 OOP에서는 변수의 사용을 특정 클래스 단독으로 또는 변수를 상속하는 클래스로만 제한 할 수 있습니다.
manu

절차 적 프로그래밍에서도 변수를 특정 함수로 사용하여 전역 변수 사용을 제한 할 수 있습니다. 즉, 데이터를 전역으로 선언하지 않습니다.
user31782

전역 적으로 선언하지 않으면 전역 변수가 아닙니다.
manu

1
"보안"또는 "정확"은 사양이없는 것을 의미하지 않습니다. 이러한 것들은 타입, 클래스 정의, DesignByContract 등 목표를 향한 코드에 대한 사양을 설정하려는 시도입니다. 개인 데이터 경계를 불가피하게 만들 수 있다는 의미에서 "보안"을 얻습니다. 실행하려면 가상 머신 명령어 세트를 준수해야한다고 가정합니다. 객체 지향은 메모리를 직접 읽을 수있는 누군가로부터 내부 메모리를 숨기지 않으며, 잘못된 객체 프로토콜 디자인은 의도적으로 비밀을 전달합니다.
Rob
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.