Main Content

객체 지향 설계를 사용하는 이유

MATLAB 프로그램 작성 방법

소프트웨어 애플리케이션을 만드는 과정에는 애플리케이션 데이터를 설계하고 이러한 데이터에 대해 수행되는 연산을 구현하는 단계가 일반적으로 포함됩니다. 절차적 프로그램은 함수에 데이터를 전달하고, 이 함수는 데이터에 필요한 연산을 수행합니다. 객체 지향 소프트웨어는 객체 인터페이스를 통해 서로 상호 작용하는 객체에 데이터와 연산을 캡슐화합니다.

MATLAB® 언어를 사용하면 절차적 기법과 객체 지향 기법을 모두 사용하여 프로그램을 만들고 프로그램에 객체와 일반 함수를 함께 사용할 수 있습니다.

절차적 프로그램 설계

절차적 프로그래밍에서는 설계 시 원하는 상태에 도달하기 위해 실행해야 하는 단계에 중점을 두어야 합니다. 일반적으로, 데이터는 개별 변수나 구조체의 필드로 나타냅니다. 연산은 변수를 인수로 받는 함수로 구현합니다. 프로그램은 대개 일련의 함수를 호출하는데, 각각의 함수는 데이터를 전달받고 수정된 데이터를 반환합니다. 각각의 함수는 데이터에 대해 단일 연산, 또는 다수의 연산을 수행합니다.

객체 지향 프로그램 설계

객체 지향 프로그램 설계 과정에는 다음과 같은 작업이 포함됩니다.

  • 작성하려는 시스템 또는 애플리케이션의 컴포넌트 식별

  • 패턴 분석 및 식별을 통해 반복적으로 사용되거나 특징을 공유하는 컴포넌트 파악

  • 유사성과 차이점을 기준으로 컴포넌트 분류

이 분석을 수행한 후에는 애플리케이션이 사용하는 객체를 설명하는 클래스를 정의하게 됩니다.

클래스 및 객체

클래스는 공통된 특징을 갖는 일련의 객체를 말합니다. 객체는 클래스의 특정 인스턴스입니다. 한 객체의 속성에 포함된 값은 이 객체가 동일한 클래스의 다른 객체와 구분짓는 역할을 합니다. 클래스로 정의되는 함수(메서드라고 함)는 클래스의 모든 객체에 공통된 객체 동작을 구현합니다.

객체 지향 프로그램을 만들어야 하는 경우

간단한 프로그래밍 작업은 단순한 함수로 구현할 수 있습니다. 하지만 작업의 규모와 복잡도가 증가할수록 함수도 더 복잡해지고 관리하기 어려워집니다.

함수가 너무 커지면 크기가 작은 여러 함수로 나누고 함수 간에 데이터를 전달하는 방법이 있습니다. 하지만 함수 개수가 많아지면 함수에 전달되는 데이터를 설계하고 관리하는 일이 더 어려워지고 오류가 발생하기 쉬워집니다. 이런 시점이 오면 MATLAB 프로그래밍 작업을 객체 지향 설계로 전환하는 것을 고려해 보십시오.

객체 차원에서 문제 이해하기

어떤 문제는 객체 차원에서 생각하면 더 간단하고 자연스러운 경우가 있습니다. 어떠한 문제를 기술한 문장에서 명사는 정의할 객체로, 동사는 수행할 연산으로 생각할 수 있습니다.

대출 기관(은행, 담보 대출 업체, 개인 대출업자 등)을 나타내는 클래스를 설계한다고 가정해 보겠습니다. 다양한 유형의 대출업자를 프로시저로 나타내기는 어렵습니다. 하지만 각각 특정 동작을 수행하고 특정 데이터를 포함하는 객체로 나타낼 수는 있습니다. 객체 설계 과정에는 애플리케이션에 중요한 대출업자의 특징을 식별하는 작업이 포함됩니다.

공통점 식별하기.  모든 대출업자가 공통적으로 가지는 특징은 무엇일까요? 예를 들어, 모든 MoneyLender 객체는 loan 메서드와 InterestRate 속성을 가질 수 있습니다.

차이점 식별하기.  각각의 대출업자는 서로 어떻게 다를까요? 한 업자는 기업을 상대로 대출을 제공할 수 있고, 다른 업자는 개인만을 상대로 대출을 제공할 수 있습니다. 따라서 loan 연산이 대출 기관의 유형에 따라 달라야 할 수 있습니다. 기본 MoneyLender 클래스의 서브클래스는 loan 메서드의 서브클래스를 특화할 수 있습니다. 대출업자마다 InterestRate 속성의 값이 다를 수 있습니다.

따라서 공통으로 적용되는 특징을 슈퍼클래스로 추출하고 각 대출업자 유형에 해당하는 특징은 서브클래스에서 구현합니다.

필요한 요소만 추가하기.  이러한 기관들은 애플리케이션과 무관한 활동에 참여할 수도 있습니다. 설계 과정에서 문제 정의에 기반하여 객체가 포함해야 하는 연산과 데이터를 파악해야 합니다.

내부 상태를 관리하는 객체

객체는 구조체와 셀형 배열에서는 사용할 수 없는 여러 유용한 기능을 제공합니다. 예를 들어, 객체는 다음과 같은 기능을 수행할 수 있습니다.

  • 지정된 속성에 할당되는 데이터 값 제한

  • 속성값이 쿼리된 경우에만 계산

  • 속성값이 쿼리되거나 변경된 경우 알림 브로드캐스트

  • 속성 및 메서드에 대한 액세스 제한

중복된 요소 줄이기

프로그램의 복잡도가 증가할수록 객체 지향 설계의 이점이 더 분명해집니다. 예를 들어, 애플리케이션의 일부로 다음 프로시저를 구현한다고 가정하겠습니다.

  1. 입력값 검사

  2. 첫 번째 입력 인수에 대한 계산 수행

  3. 두 번째 입력 인수를 기반으로 하여 2단계에서의 결과 변환

  4. 출력값 및 반환 값에 대한 유효성 검사

이 프로시저를 일반 함수로 구현할 수 있습니다. 하지만 애플리케이션에서 이 프로시저를 다시 사용하되 2단계에서 다른 계산을 수행해야 한다고 가정하겠습니다. 이 경우 첫 번째 구현을 복사하여 붙여 넣은 후 2단계를 다시 작성하는 것도 방법입니다. 또는 어떠한 계산을 수행할지 표시하는 옵션을 받는 함수를 생성할 수도 있습니다. 하지만 이러한 옵션은 코드를 더 복잡하게 만듭니다.

객체 지향 설계에서는 공통 코드를 기본 클래스로 추출할 수 있습니다. 기본 클래스는 사용되는 알고리즘을 정의하고 이 코드를 사용하는 모든 경우에 공통되는 작업을 구현합니다. 2단계는 구문으로 정의하되 구현하지 않고, 특화된 구현을 이 기본 클래스에서 파생하는 클래스로 넘길 수 있습니다.

1단계

function checkInputs()
   % actual implementation
end

2단계

function results = computeOnFirstArg()
   % specify syntax only
end

3단계

function transformResults()
   % actual implementation
end

4단계

function out = checkOutputs()
   % actual implementation
end

기본 클래스의 코드는 복사되거나 수정되지 않습니다. 기본 클래스에서 파생되는 클래스가 이 코드를 상속합니다. 이렇게 상속을 통해 테스트할 코드의 양이 줄어들고 기본 프로시저의 변경에 영향을 받지 않도록 프로그램이 분리됩니다.

일관된 인터페이스 정의하기

어떠한 클래스를 이와 유사하지만 더욱 특화된 클래스에 대한 기반으로 사용하는 것은 객체 지향 프로그래밍에서 유용하게 쓸 수 있는 기법입니다. 이 클래스는 공통 인터페이스를 정의합니다. 이러한 종류의 클래스를 프로그램 설계에 통합하면 다음과 같은 작업을 수행할 수 있습니다.

  • 특정 목적에 대한 요구 사항 식별

  • 요구 사항을 인터페이스 클래스로 프로그램에 부호화

복잡도 줄이기

객체를 사용하면 컴포넌트 또는 시스템을 사용하는 데 알아야 하는 사항이 적어지므로 복잡도가 완화됩니다.

  • 객체는 구현에 대한 세부 정보를 은닉하는 인터페이스를 제공합니다.

  • 객체는 객체의 상호 작용 방식을 제어하는 규칙을 적용합니다.

이러한 이점을 확인하기 위해 이중 연결 리스트라고 하는 데이터 구조에 대한 구현을 살펴보겠습니다. 실제 구현은 클래스를 사용하여 연결 리스트 구현하기 항목을 참조하십시오.

다음은 요소를 3개 가진 리스트를 보여주는 도식입니다.

Three elements of a doubly linked list

리스트에 노드를 추가하려면 리스트에 있는 기존 노드의 연결을 끊고 새 노드를 삽입한 후 노드를 적절하게 다시 연결하십시오. 기본 단계는 다음과 같습니다.

먼저, 노드의 연결을 끊습니다.

  1. n1에서 n2.Prev의 연결을 해제합니다.

  2. n2에서 n1.Next의 연결을 해제합니다.

이제 새 노드를 생성하고 연결한 후 원래 노드에 번호를 다시 지정합니다.

  1. new.Prevn1에 연결합니다.

  2. new.Next를 (이전에 n2였던)n3에 연결합니다.

  3. n1.Next를 (새로 n2가 될)new에 연결합니다.

  4. n3.Prev를 (새로 n2가 될)new에 연결합니다.

Doubly linked list

메서드가 이 단계를 수행하는 방식에 대한 세부 정보는 클래스 설계에 캡슐화됩니다. 각 노드 객체에는 객체 자신을 리스트에 삽입하거나 리스트에서 제거할 수 있는 기능이 있습니다.

예를 들어, 이 클래스의 모든 노드 객체에는 insertAfter 메서드가 있습니다. 리스트에 노드를 추가하려면 노드 객체를 생성한 후 해당 insertAfter 메서드를 호출하십시오.

nnew = NodeConstructor;
nnew.insertAfter(n1)

노드 클래스가 이러한 연산을 구현하는 코드를 정의하기 때문에 이 코드의 특징은 다음과 같습니다.

  • 클래스 작성자에 의해 최적으로 구현됨

  • 클래스의 현재 버전으로 항상 최신 상태로 유지됨

  • 올바르게 테스트됨

  • 이전 버전의 객체를 MAT 파일에서 불러온 경우 자동으로 업데이트 가능함

객체 메서드는 노드의 상호 작용 방식에 대한 규칙을 적용합니다. 이 설계에서는 객체를 사용하는 애플리케이션 측에서 규칙을 적용할 필요가 없어지게 됩니다. 또한, 애플리케이션에서 고유하게 프로세스를 구현할 때 오류가 발생할 가능성이 더 적습니다.

모듈화 조성

시스템을 객체로 분해하면(자동차 –> 엔진 –> 연료 시스템 –> 산소 센서) 자연스러운 경계를 중심으로 모듈이 형성됩니다. 클래스는 코드 모듈화에 대해 다음 세 가지 제어 수준을 제공합니다.

  • 퍼블릭 — 모든 코드가 이 특정 속성에 액세스하거나 이 메서드를 호출할 수 있습니다.

  • 보호 — 이 객체의 메서드와 이 객체의 클래스에서 파생된 객체의 메서드만 이 속성에 액세스하거나 이 메서드를 호출할 수 있습니다.

  • 프라이빗 — 객체 자체의 메서드만 이 속성에 액세스하거나 이 메서드를 호출할 수 있습니다.

오버로드된 함수 및 연산자

클래스를 정의할 때 기존 MATLAB 함수를 새 객체에 사용하도록 오버로드할 수 있습니다. 예를 들어, MATLAB 직렬 포트 클래스는 이 객체가 나타내는 포트에 연결된 장치에서 데이터를 읽어오도록 fread 함수를 오버로드합니다. 데이터를 나타내기 위해 정의한 클래스에 대해 등식(eq) 또는 더하기(plus)와 같은 다양한 연산을 정의할 수 있습니다.

관련 항목