반응형

Intro

안녕하세요. 이번에는 시리얼 통신에 관한 설명과 간단한 샘플 코드 소개 하겠습니다. 시리얼 통신은 컴퓨터나 다른 장치들 사이에서 데이터를 주고받는 데에 사용되는 일련의 통신 방법입니다. 주로 마이크로컨트롤러, 아두이노, 센서, 모터 등과 같은 장치들을 컴퓨터와 연결하여 데이터를 교환하고 제어하는 데에 많이 사용됩니다. 

시리얼 통신 설명

1. 시리얼 통신의 기본 개념

  • 시리얼 통신은 비트들이 연속적으로 전송되는 방식으로, 병렬 통신과는 달리 하나의 비트씩 순차적으로 전송됩니다. 데이터를 주고받을 때는 두 장치 간에 공통된 데이터 송수신 (TX/RX) 핀을 사용하며, 주로 UART(Universal Asynchronous Receiver/Transmitter) 프로토콜을 기반으로 합니다.


2. UART 프로토콜

  • UART는 가장 일반적으로 사용되는 시리얼 통신 프로토콜 중 하나로, 비동기적으로 데이터를 전송합니다. 비동기적이라는 의미는 클록 신호가 없이 데이터 비트를 전송한다는 것을 의미합니다. UART는 데이터 비트, 정지 비트, 패리티 비트로 구성됩니다.



3. 시리얼 통신의 속도

  • 시리얼 통신에서는 속도를 보드레이트(baud rate)라고 부릅니다. 보드레이트는 초당 전송되는 비트의 수를 나타내며, 일반적으로 흔히 사용되는 보드레이트는 9600, 19200, 38400, 115200 등이 있습니다. 속도는 통신하는 장치들 사이에서 동일해야 정상적으로 데이터를 주고받을 수 있습니다.

4. 시리얼 통신의 연결

  • 시리얼 통신을 위해 두 장치를 연결할 때는 보통 UART 케이블이나 USB 시리얼 어댑터를 사용합니다. 컴퓨터의 경우 UART를 지원하는 시리얼 포트나 USB를 통해 시리얼 통신을 할 수 있습니다.


5. 시리얼 통신의 사용 예

  • 시리얼 통신은 다양한 분야에서 사용됩니다. 예를 들어, 아두이노와 컴퓨터를 연결하여 센서 데이터를 읽거나 제어 신호를 보낼 수 있습니다. 또한, 마이크로컨트롤러를 이용한 로봇 제어, 센서 네트워크 구축, 원격 감시 시스템 등에도 적용될 수 있습니다.

소스 코드(C++)

헤더

#define PORT_COMMUNICATIONSIZE 512
#include<string>
class SerialPort
{
private:
	HANDLE				m_hComm;
	DCB					m_dcb;
	COMMTIMEOUTS		m_CommTimeouts;
	bool				m_bPortReady;
	bool				m_bWriteRC;
	bool				m_bReadRC;
	unsigned long		m_iBytesWritten;
	unsigned long		m_iBytesRead;
	unsigned long		m_dwBytesRead;
public:
	SerialPort();
	~SerialPort();
	bool OpenPort(std::string portname);
	bool ClosePort();
	bool PortConfigure(unsigned long BaudRate, unsigned char ByteSize, unsigned long fParity, unsigned char  Parity, unsigned char StopBits);
	bool SetCommunicationTimeouts(unsigned long ReadIntervalTimeout, unsigned long ReadTotalTimeoutMultiplier,
		unsigned long ReadTotalTimeoutConstant, unsigned long WriteTotalTimeoutMultiplier,
		unsigned long WriteTotalTimeoutConstant);
	bool ReadPortRegister(unsigned char* Register);
	bool WritePortRegister(unsigned char* Register, int length);
};

본문

#include "SerialPort.h"
SerialPort::SerialPort()
{
	m_hComm = NULL;
	m_dcb = { 0 };
	m_CommTimeouts.ReadIntervalTimeout = 0;
	m_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
	m_CommTimeouts.ReadTotalTimeoutConstant = 0;
	m_CommTimeouts.WriteTotalTimeoutConstant = 0;
	m_CommTimeouts.WriteTotalTimeoutConstant = 0;
	m_bPortReady = false;
	m_bWriteRC = false;
	m_bReadRC = false;
	m_iBytesWritten = -1;
	m_iBytesRead = -1;
	m_dwBytesRead = -1;

}
SerialPort::~SerialPort()
{
	CloseHandle(m_hComm);
}
bool SerialPort::OpenPort(std::string portname)
{
	m_hComm = CreateFileA(portname.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL,
		OPEN_EXISTING, 0, NULL);
	if (m_hComm == INVALID_HANDLE_VALUE)
	{
		//OutputLog::LOG("Simulator - Serial Port Open Fail\n", OutputLog::LogLevel::System);
		return false;
	}
	else
	{
		//OutputLog::LOG("Simulator - Serial Port Open Sucess\n", OutputLog::LogLevel::System);
		return true;

	}

}

bool SerialPort::ClosePort()
{
	CloseHandle(m_hComm);
	m_hComm = NULL;
	if (m_hComm == NULL)
	{
		//OutputLog::LOG("Simulator - Serial Port Close Sucess\n", OutputLog::LogLevel::System);
		return true;
	}
	else
	{
		//OutputLog::LOG("Simulator - Serial Port Close Fail\n", OutputLog::LogLevel::System);
		return false;
	}

}

bool SerialPort::PortConfigure(unsigned long BaudRate, unsigned char ByteSize, unsigned long fParity, unsigned char  Parity, unsigned char StopBits)
{
	if ((m_bPortReady = GetCommState(m_hComm, &m_dcb)) == 0)
		return false;
	else
	{
		m_dcb.BaudRate = BaudRate;
		m_dcb.ByteSize = ByteSize;
		m_dcb.Parity = (unsigned char)fParity;
		m_dcb.StopBits = StopBits;
		m_dcb.fBinary = true;
		m_dcb.fDsrSensitivity = false;
		m_dcb.fParity = fParity;
		m_dcb.fOutX = false;
		m_dcb.fInX = false;
		m_dcb.fNull = false;
		m_dcb.fAbortOnError = true;
		m_dcb.fOutxCtsFlow = false;
		m_dcb.fOutxDsrFlow = false;
		m_dcb.fDtrControl = DTR_CONTROL_DISABLE;
		m_dcb.fDsrSensitivity = false;
		m_dcb.fRtsControl = RTS_CONTROL_DISABLE;
		m_dcb.fOutxCtsFlow = false;

		m_bPortReady = SetCommState(m_hComm, &m_dcb);
		if (m_bPortReady == 0)
		{
			CloseHandle(m_hComm);
			return false;
		}

	}
	return true;
}

bool SerialPort::SetCommunicationTimeouts(unsigned long ReadIntervalTimeout, unsigned long ReadTotalTimeoutMultiplier,
	unsigned long ReadTotalTimeoutConstant, unsigned long WriteTotalTimeoutMultiplier,
	unsigned long WriteTotalTimeoutConstant)
{

	if ((m_bPortReady = GetCommTimeouts(m_hComm, &m_CommTimeouts)) == 0)
		return false;
	else
	{
		m_CommTimeouts.ReadIntervalTimeout = ReadIntervalTimeout;
		m_CommTimeouts.ReadTotalTimeoutConstant = ReadTotalTimeoutConstant;
		m_CommTimeouts.ReadTotalTimeoutMultiplier = ReadTotalTimeoutMultiplier;
		m_CommTimeouts.WriteTotalTimeoutConstant = WriteTotalTimeoutConstant;
		m_CommTimeouts.WriteTotalTimeoutMultiplier = WriteTotalTimeoutMultiplier;
		m_bPortReady = SetCommTimeouts(m_hComm, &m_CommTimeouts);

		if (m_bPortReady == 0)
		{
			CloseHandle(m_hComm);
			return false;
		}
		else
			return true;

	}

}
bool SerialPort::WritePortRegister(unsigned char* Register, int length)
{

	bool bStatus = false;
	unsigned long dwBytesWritten = 0;
	bStatus = WriteFile(m_hComm, &Register[0], length, &dwBytesWritten, NULL);
	return bStatus;
}
bool SerialPort::ReadPortRegister(unsigned char* Register)
{

	bool bStatus = false;
	unsigned long dwBytesRead;
	bStatus = ReadFile(m_hComm, &Register[0], PORT_COMMUNICATIONSIZE, &dwBytesRead, NULL);
	return bStatus;
}

위에 코드는 간단한 시리얼 포트 open/close와 read/write를 구현한 부분입니다.

테스트해보려면 main 함수에서 객체 선언해서 사용하시면 됩니다.

마무리

시리얼 통신은 하드웨어와 소프트웨어 측면에서 간단하면서도 다양한 응용 분야에서 활용되는 중요한 통신 방법입니다. 컴퓨터와 다양한 장치들 간의 데이터 교환과 제어에 필수적인 기술이니, 시리얼 통신에 대해 더 알아보고 활용해 보시면 좋을 것 같습니다.

 

 

반응형
반응형

Intro


안녕하세요. 이번 포스팅에서는 Visual studio2019 C++ 프로젝트에서 Unit test framework 중 하나인 Google test 연동 방법에 대해 포스팅하겠습니다. Google Test는 C++ Unit test에서 많이 쓰이는 framework입니다. 잘만 활용한다면 개발자의 실수를 최소화 할 수 있고 경건한 프로그램을 만들 수 있습니다.

Visual studio2019 google test 연동방법


1) 테스트 프로젝트 생성테스트 할 프로젝트를 생성하고 코드를 작성해줍니다. 간단한 테스만 수행하기 위해 math class에 메서드로 sum과 multiply을 구현 하였습니다.


math.h
class math
{
public:
    int math::sum(int a, int b);
    int math::multiply(int a, int b);

}

간단하게 sum함수와 multiply함수를 테스트해보겠습니다.

 math.c

 #include "math.h"
int math::sum(int a, int b)
{
    return a + b;
}
int math::multiply(int a, int b)
{
    return a * b;

}
     (adsbygoogle = window.adsbygoogle || []).push({});

2) lib파일 생성 (구성 형식. exe -> lib 변경)exe파일이 아닌 lib파일로 변경하는 이유는 테스트 할 프로젝트 솔루션의 header만 가져다 쓰기 위해서입니다.

3) Google test 프로젝트 생성

3-1) 새 프로잭트 생성

3-2) Google Test 선택

3-3) 프로젝트 생성

3-4) 프로젝트 생성옵션 선택 (정적 라이브버리(.lib), 동적으로 연결 선택)

3-5) 처음 Google Test 프로젝트 만들었을 때 화면

3-6) 시작 프로잭트 변경. 프로젝트 -> 속성 -> 시작 프로젝트 -> Sample-Test1 변경

3-7) 기본 빌드 결과

4) Test 프로젝트 연동

4-1) 링커 경로 포함 (google test project -> 속성 -> 링커 -> 일반 -> 추가 라이브러리 디렉터리 -> ..\x64\Debug 추가)

4-2) lib파일 추가. 테스트할 프로젝트의 lib파일 추가하기 위한 lib path입니다.링커 -> 입력 -> 추가 종속성 -> 라이브러리 추가 (gtest.lib, gtest_maind.lib, Unit_Test.lib)

gtest.lib와 gtest_maind.lib는 google test에 포함되어 있는 lib입니다. lib path는 개인 마음대로입니다. 저는 따로 만들기 귀찮아서 저 폴더에 넣었습니다.

5) Test case 작성

5-1) test case 작성테스트할 프로젝트의 header을 include 하고 test case를 작성합니다. 결과를 보면 1번 case와 3번 case는 통과하게 하였고, 2번 case와 4번 case는 실패하게 케이스를 작성했습니다. 정상적으로 unit test가 수행됨을 확일 할 수 있습니다.

5-2) 빌드 결과

5-3) 테스크 탐색기 결과 (테스트 -> 테스트 탐색기)

6) 결과물 xml 파일로 만들기

자 이제 마지막입니다. test 한 산출물을 xml 파일로 만들어야 합니다.

6-1) visual studio에서 xml 파일 만들기

속성-> 구성 속성 -> 명령 인수 (--gtest_output=xml:..\x64\Debug\result.xml 입력)

결과

6-2) cmd에서 xml 파일 만들기

xml 파일 만들기는 명령 프롬프트로도 확인이 가능합니다

test실행 파일이 있는 폴더로 이동

Sample-Test 1.exe --gtest_output=xml:result2.xml 커맨드 입력

결과가 똑같이 만들어짐을 확일 할 수 있습니다. 보통 기업에서는 xml파일을 가공해서 산출물을 관리하기도 합니다. git에서 찾아보면 xml을 html코드로 바꾸는 방법이 많이 나와있습니다. 그쪽 참조해보시면 될 것 같습니다.

마무리


이번 포스팅에서는 visual studio 2019에서 Google Unit Test 하는 방법에 대해 알아 보았습니다. Unit test는 실제 개발자의 실수를 줄여줄 수 있는 방법입니다. 그리고 개인적으로 배포 전 꼭 거쳐야 하는 과정이라고 생각합니다.

그럼 이만 포스팅을 마치겠습니다.

감사합니다.

반응형
반응형

Intro


안녕하세요. 이번 포스팅에서는 C++의 장점 중 하나인 캡슐화에 대해 알아보도록 하겠습니다. 캡슐화는 클래스가 갖고 있는 멤버의 일부를 감춰 클래스를 블랙박스 화하는 것입니다. 즉, 사용자에게 가치가 없는 멤버를 감추는 것입니다. 보통 학부 때 교수님들이 캡슐화에 대해 설명할 때 리모컨에 빚대어 설명을 하십니다. 우리가 채널을 바꿀 때 누르는 버튼은 공개되어 있지만, 실제 버튼을 누르고 TV에 신호 주는 건 캡슐화로 감춰져 있습니다. 즉, 리모컨이 TV로 채널 변경 신호를 보내는걸 굳이 알 필요가 없기 때문입니다. 그렇기 때문에 캡슐화의 목적은 불필요한 것은 캡슐화하여 감추고 프로그래밍을 효율화하는 테크닉입니다.

접근 지정어


접근 지정어 : 클래스를 사용하는 측으로부터 멤버를 이용할 수 있는가의 여부를 결정한다. 접근 지정어에는 public; private; protected 3가지가 있다.

  • public : 지정된 멤버 공개
  • private : 지정된 멤버 비공개. 접근 지정어를 생략했을 때 디폴트는 private.
  • protected : 클래스가 사용되는 방법에 따라서 private: 혹은 public: 어느 쪽인가로 이루어지는 것. 클래스의 객체를 만들어 사용한다면 private:와 같은 의미가 되고 클래스를 상속하여 사용한다면 public:과 동일한 의미가 된다.

UML 클래스 다이어그램에 멤버

  • UML의 클래스 다이어그램에서는 public:는 +, private:는 -, protected:는 #으로 나타낸다.

마무리


접근 지정어가 없는 프로그래밍 언어에서는 프로그램 속에 존재하는 변수나 함수를 프로그램 이외의 부분에서 항상 이용할 수 있게 됩니다. 접근 지정어를 사용하는 장점은 특정한 변수나 멤버 함수 이용을 불가능하게 하는 것에 있습니다. 즉, 크래스의 사용자에게 이용할 가치가 없는 멤버를 감추는 것입니다. 멤버를 감추는 것을 캡슐화라고 합니다.

그럼 이상으로 포스팅을 마치겠습니다. 감사합니다.

반응형
반응형

Intro


이번 포스팅에서는 C++의 장점 중 하나인 다형성에 대해 알아보도록 하겠습니다. C++을 공부하다 보면 다형성이라는 단어를 자주 접하게 될 것입니다. 하지만 다형성...이라는 단어를 접했을 때 평소 사용하지 않아서 생소했습니다. 그래서 다형성이라는 국어사전에 나온 의미에 대해 찾아봤습니다.
다형성 : 동일종(同一種)의 생물이면서도 형태나 성질이 다양성을 보이는 상태. 암수에 의한 크기·형태·색깔 등의 차이와 꿀벌에서의 여왕벌과 일벌 같은 것(구글 국어사전 검색).
위에 다형성이라는 국어사전에서 나타내는 의미를 찾아보고 다형성에 대해 학습하니 C++에서의 다형성의 개념의 이해가 잘 갔습니다. 즉, C++에서 다형성이란 동일한 메시지에 대해 복수의 다른 응답을 하는 것입니다.

오버로드 vs 오버라이드


오버로드(overload) : 한 개의 클래스 내에 동일한 이름의 멤버 함수를 복수 정의하는 것입니다.
소스코드를 통해 오버로드에 대해 살펴보도록 하겠습니다.

#include <iostream>
using namespace std;
class Anabebe
{
public:
    int        func(int a);
    double    func(double b);
};
int Anabebe::func(int a)
{
    return a*2;
}
double Anabebe::func(double b)
{
    return b*3.14;
}

int main(void)
{
    Anabebe obj;
    int a;
    double b;
    a = obj.func(10);
    b = obj.func(1.0);
    cout << a << endl;
    cout << b << endl;
}

결과

소스코드를 보면 하나의 클래스에 동일한 이름의 함수가 두개가 있습니다. 두 함수의 차이는 함수의 리턴 타입이 int, double고 함수의 인수도 int, double입니다. 이렇게 하고 main함수에서 호출을 func함수를 호출하게 되면 컴파일러가 알아서 같은 형으로 컴파일이 되기 때문에 오버로드가 실현되고 있다는 뜻입니다.
주의해야 할 점은 C++ 컴파일러는 이름과 인수로 멤버 함수를 식별하지만 반환값은 식별의 대상이 되지 않습니다. 즉, func(인수)에서 인수에 따라 식별이 된고, return타입은 고려되지 않습니다. double b = obj.func(10)이런식으로 호출을 하게 되면 b에는 20이 저장됩니다.

오버로드 활용의 두 가지 패턴
오버로드를 활용하기 위한 패턴으로는 크게 두 가지가 있습니다.
하나는 완전한 동일한 작업 내용에서 인수의 자료형만이 다른 멤버 함수를 오버로드 하는 것입니다.
sample code

class Anabebe
{
public:
    int        func(int a);
    double    func(double b);
};
int Anabebe::func(int a)
{
    return a*2;
}
double Anabebe::func(double b)
{
    return b*3.14;
}

또 다른 패턴은 인수의 수가 다른 동일한 이름의 멤버 함수를 정의하는 것입니다.
sample code

class Anabebe
{
public:
    int        func(int a);
    void    func(char* s, double a);
};
int Anabebe::func(int a)
{
    return a*2;
}
void Anabebe::func(char* s,double a)
{
    cout << s << a << endl;
}

다른 수의 인수를 가진 멤버 함수를 오버로드 할 경우에는 하나의 멤버 함수가 다른 멤버 함수를 호출하게 하면 코드를 효율적으로 설명할 수 있습니다. 호출되는 측의 멤버 함수를 수정하면 그 내용이 다른 멤버 함수에게도 반영되기 때문입니다.

오버라이드(override): 기본 클래스의 멤버 함수 처리 내용을 파생 클래스에서 재정의 하는 것을 오버라이드라고 합니다. 오버라이드는 상속한 멤버 함수의 처리 내용이 파생 클래스의 목적에 맞지 않을 경우 멤버 함수의 원형을 그대로 두고, 처리 내용을 자유롭게 재정의할 수 있다는 점에서 편리합니다. 이 구조를 연구하여 사용함으로 다형성을 실현하고 클래스를 사용하는 측의 코드를 짧고 효율적으로 설명할 수 있게 됩니다.

소스코드를 통해 확인해 보겠습니다.

#include <iostream>
using namespace std;
class Anabebe
{
public:
    virtual void showdata();
};

void Anabebe::showdata()
{
    cout << "Anabebe Class 호출" << endl;
}

class Anabebe2 : public Anabebe
{
public:
    void showdata();


};
void Anabebe2::showdata()
{
    Anabebe::showdata();
    cout << "Anabebe2 Class 호출" << endl;
}

int main(void)
{
    Anabebe2 obj2;
    obj2.showdata();
}

결과

코드를 보면 Anabebe2에서 Anabebe클래스를 상속받아 showdata() 함수를 재정의 했습니다. 코드를 이렇게 보면 정말 아무것도 아닌 것처럼 보이는데 이걸 긴 코드에서 테크닉 적으로 사용하면 코드를 보다 짧고 효율적으로 설명할 수 있습니다.

마무리


이번 포스팅에서 C++에서 다형성을 실현하기 위한 오버로드와 오버라이드에 대해 알아봤습니다. 오버라이드에서 순수 가상 함수와 추상 클래스에 대한 내용이 빠졌는데.. 이걸 추가하다 보면 너무 길어질 것 같아서 다음번에 따로 포스팅을 하도록 하겠습니다.
마지막으로 오버로드, 오버라이드 두 개의 차이를 정리하자면 오버로드는 한 개의 클래스 내에 동일한 이름의 멤버 함수를 복수 정의하는 것이고, 오버라이드는 기본 클래스의 멤버 함수 처리 내용을 파생 클래스에서 재정의 하는 것을 오버라이드라고 합니다.
오버로드, 오버라이드 C++에 다형성을 실현하기 위한 기능이지만, 프로그래머가 코드를 구현할 때 꼭 사용해야 하는 테크닉은 아닙니다. 하지만 두 개념을 이해하고 프로그래밍을 하면 보다 효율적이고 재미를 느낄 수 있을 것입니다.
그럼 이만 포스팅 마치겠습니다. 감사합니다.

반응형
반응형

Intro


이번 포스팅에서는 객체지향의 3가지 특성에 대해 알아보도록 하겠습니다. 객체 지향의 이해 방법의 하나로 "객체지향이란 상속, 캡슐화, 다형성을 사용하는 것"이라는 말이 있을 정도로 객체지향을 이해하는데 핵심 내용입니다.

객체지향의 3가지 특성


  1. 상속(inheritance)
    • 다른 클래스의 멤버를 인계하여 새로운 클래스를 정의하는 것입니다.
    • 같은 특징 있는 클래스를 그대로 물려받아 재사용 가능하기 때문에 효율성을 늘릴 수 있습니다.
    • 하위 클래스는 상위 클래스로부터 상속받은 멤버 외에 새로운 멤버 구성하여 사용할 수 있습니다.

상속의 가장 큰 장점은 재사용에 있다고 생각이 됩니다. 상위 클래스의 멤버를 하위 클래스에서 재사용함으로 소프트웨어 개발에 편의성이 증대된다고 생각이 됩니다.

  1. 캡슐화(Encapsulation)
    • 연관 있는 멤버를 클래스로 묶는 작업을 의미합니다.
    • 클래스의 멤버를 부분적으로 은폐하는 것입니다.
    • 클래스가 지닌 멤버 가운데 클래스를 사용하는 측에서 필요한 것만을 공개하고 클래스 내에서만 사용되는 멤버를 감추는 것입니다.

캡슐화는 외부에 데이터를 은닉하는데 많이 사용이 되는데 멤버의 정의를 접근 지정어로 private, protected, public로 선언을 해줍니다.

  1. 다형성
    • 같은 모양의 함수가 동일한 메시지에 대해 복수의 다른 응답을 하는 것입니다.
    • 하나의 클래스의 내부에 동일한 이름의 함수를 만들어 함수의 타입을 다르게 하거나, 파라미터의 개수를 다르게 하눈 오버 로딩(overloading)의 특성이 있습니다.
    • 상속받은 함수를 재정의 하는 오버 라이딩(overriddng)의 특성이 있습니다.
      멤버의 오버 로딩과 오버 라이딩을 통해 동일한 함수의 다른 메시지를 출력하여 객체지향의 특징인 다형성을 실현할 수 있습니다.

마무리


상속, 캡슐화, 다형성의 목적은 현실 세계를 그대로 모델링하여 프로그래밍의 효율화에 목적이 있습니다. 따라서, 프로그래밍을 할 때 객체지향의 특성을 꼭 사용해야 필수는 아닙니다. 그냥 필요한 상황에 쓰는 테크닉입니다. 필수는 아니지만 아마도 개발을 하시게 되면 분명히 쓰시게 될 거라고 생각합니다. 다음 시간에는 위에 설명했던 객체지향의 특성이 어떻게 사용되는지 자세히 알아보도록 하겠습니다.

반응형
반응형

Intro


절차지향 프로그래밍과 객체지향 프로그래밍의 차이는 많은 책들에서 초기 도입 부분에 많이 설명되고 기업의 신입 면접에서도 가끔 맨 처음 기본이 있는지 알아보기 위해 물어보던 내용입니다. 이번 포스팅을 통해 절차 지향 프로그래밍과 객체지향 프로그래밍의 차이의 비교와 장, 단점을 이해하는 시간을 가져보도록 하겠습니다.

절차지향 vs 객체지향


절차지향 프로그래밍이란?
절차지향 프로그래밍은 일련의 흐름에 의해 진행되는 프로그래밍입니다. 사람들이 폭포에 많이 비교를 하는데 물이 위에서 아래로 떨어지듯 코드의 흐름이 위에서부터 아래로 순서대로 진행되는 방식입니다. 예를 들어 사람을 프로그래밍화 해서 구성할 때 머리->몸통->왼팔->오른팔->왼다리->오른다리 이런 식으로 일련의 순서를 기준으로 잡고 프로그래밍하는 방식입니다. 사람이라는 코드를 만들 때 구성하는 순서는 기준에서 바뀌지 않습니다.

절차지향 프로그래밍 대표 언어

  • C언어
  • 파스칼
  • 코볼

C언어는 아는데.. 파스칼 언어와 코볼은 잘 몰라서 위키에서 찾아봤습니다.
파스칼 언어 : 포인터를 사용한 구조적 프로그래밍과 데이터 구조화(data structuring)를 그 특징으로 한다. 파스칼 참조 링크
코볼 언어 : 사무용으로 설계된, 영어와 같은 컴퓨터 프로그래밍 언어이다. 코볼은 주로 비즈니스, 금융, 회사/정부 관리 시스템에 주로 사용된다.코볼 참조 링크

장점

  • 컴퓨터 구조와 유사하여 처리속도가 빠르다.
  • 개인 프로젝트나 과제 같이 길지 않은 프로젝트에 적합.

단점

  • 유지 보수가 어렵다.
  • 대규모 프로젝트에 적합하지 않다.
  • 실행 순서가 정해져 있으므로 코드의 순서가 바뀌면 동일한 결과를 보장하기 어렵다.

객체지향 프로그래밍이란?
객체지향 언어는 대상에 주목하여 프로그램을 작성하는 프로그래밍입니다. 여기서 대상에 주목한다는 말은 작업의 소유자가 객체이고, 개개의 객체는 작업(함수)을 가지고 객체가 다른 객체의 함수를 호출함으로 프로그래밍을 작동시키는 프로그래밍입니다. 객체지향을 통해 사람을 프로그래밍할 때 절차 지향과는 달리 사람을 구성하는데 순서에 제약이 없습니다.

객체지향 프로그래밍 대표언어

  • C++
  • Java
  • Python

장점

  • 코드의 재사용이 쉽고, 유지 보수가 쉽다.
  • 디버깅이 상대적(절차 지향에 비해)으로 쉽다
  • 직관적인 코드 분석이 가능하다.

단점

  • 코딩의 난이도 증대
  • 실행 속도가 상대적으로 절차 지향 프로그래밍에 비해 느림

마무리


이번 포스팅에서 절차지향 프로그래밍과 객체지향 프로그래밍이 무엇인지와 장, 단점을 비교해봤습니다. 위에 내용만 봤을 때는 객체지향 프로그래밍이 더 좋은 프로그래밍 기법이라고 생각할 수 있습니다. 하지만 객체지향 프로그래밍이 더 우수한 프로그래밍 기법은 아닙니다. 용도의 차이가 있을 뿐입니다. 요즘에는 컴퓨터의 성능이 아주 우수하기 때문에 메모리에 크게 제약을 받지는 않습니다. 하지만 예를 들어 메모리가 작은 아주 저가의 임베디드 보드에 숫자를 카운트할 수 있는 기능을 넣었다고 가정했을 때 절차 지향 프로그래밍은 그냥 숫자를 세는 함수를 호출하면 되는데 객체지향 프로그래밍은 객체를 선언하고 함수를 호출해야 되기 떄문에 메모리 관리 측면에서 절차지향 프로그래밍이 더 유리합니다.
이상으로 포스팅을 마치며 다음 시간에는 객체지향의 특징인 상속, 캡슐화, 다형성에 대해 알아보도록 하겠습니다. 감사합니다.

반응형

+ Recent posts