스터디/C방장

협업을 위한 코드, 읽기 쉬운 코드 작성하는 법. Top Down, 모듈화 (feat. 소수 구하기)

SW PLAN B 2021. 1. 3. 22:08
728x90

제가 알고 있는 C에 관한 지식을 나눕니다.

카카오톡 오픈 채팅방에서 질문도 받습니다.

궁금한 점들은 댓글 또는 오픈채팅방에서 질문해 주세요.

C방장 오픈채팅방 QR코드
C방장 오픈채팅방 QR코드

C방장한테 질문하러 가기


협업을 위한 코드, 읽기 쉬운 코드 작성하는법 대표이미지

협업을 위한 코드, 읽기 쉬운 코드 작성하는 법. Top Down, 모듈화 (feat. 소수 구하기)

C방장 오픈채팅방 질문 캡쳐내용
C방장 오픈 채팅방의 질문 중 캡쳐

C언어를 공부한지 얼마 안 되었다고 하시며 100 이하의 소수를 출력하는 프로그램에 대해서 질문을 주셨어요.

단순히 소수만 출력하는 프로그램을 구현하는 것은 여러가지 방법이 있습니다. 극단적으로 100 이하의 소수들을 하드코딩해서 직접 2, 3, 5, 7... 을 출력하는 프로그램도 구현할 수 있습니다. (하드코딩에서 하드는 열심히의 hard가 아니라 딱딱한의 hard를 의미하며 하드코딩은 재사용성, 유연성이 떨어지는 코딩 스타일을 말합니다.)

하드코딩 개발방식 예시 플로우 차트와 수도코드
그림 1. 플로우차트와 수도코드 하드코딩 예시

그림 1.은 하드코딩으로 구현할 프로그램의 플로우 차트와 수도코드입니다. 아주 드물겠지만 경우에 따라서 이런 식의 프로그래밍이 필요할 때도 있을 수 있겠죠. 하지만 우리가 궁극적으로 가져야 할 능력은 팀원들과 협업에 유리한 프로그램을 개발하는 능력 그리고 재사용성, 유연성, 확장성이 갖춰진 프로그램을 개발할 수 있는 능력입니다.

어떻게 개발해야 좋은 개발자가 될 수 있을지 지금부터 알아보도록 하겠습니다.


■ 모듈화 - 확장성과 재사용성을 고려한 요구사항 분석

지금 주어진 표면적인 고객의 요구사항은 "100이하의 소수를 출력하는 프로그램"입니다. 하지만 변덕스러운 고객(직장 상사, 교수님, 돈을 지불하는 진짜 고객 등)은 언제 이 요구사항을 바꿀지 우리는 모릅니다. 따라서 우리는 향후 추가될 수 있는 요구사항을 예상해 보고 이를 고려한 프로그램을 개발해야 합니다.

"100 이하의 소수를 출력하는 프로그램"에서 다른 요구사항이 있을 수 있다면 어떤 것들이 있을 수 있을까요?

1. 100이 아닌 "정수 N 이하의 소수를 출력하는 프로그램"으로 요구사항이 바뀔 수 있습니다.

2. 정수 N을 입력받는 방법은 표준 입출력이 될 수 있고 파일 입출력이 될 수 있고 혹은 랜덤 값이 될 수 도있습니다.

3. "N 이하의 소수가 아닌 수를 출력하는 프로그램"으로 요구사항이 바뀔 수도 있습니다.

잠깐 생각해봐도 추가될 수 있는 요구사항은 무궁무진합니다. 사실상 모든 케이스를 커버할 수는 없습니다. 하지만 모듈화를 통해 이런 추가되는 요구사항들을 유연하게 대응할 수 있습니다.

모듈화는 시스템을 이루는 여러 기능들을 작은 단위로 나누는 것을 말합니다. 모듈화를 통해 개발하는 프로그램의 유지보수성, 재사용성, 확장성 등을 향상할 수 있습니다.

"100 이하의 소수를 출력하는 프로그램"에서 우리는 "소수를 판별하는 모듈", "정수 N을 입력받는 모듈" 등을 구현해야 하겠다는 마음을 가지고 다음으로 넘어가보겠습니다.

■ Top Down 개발 - 큰 것에서 작은 것으로 프로세스 중심의 설계

Top Down 개발 방식은 높은 추상화 단계에서부터 점점 구체적인 설계, 개발을 하는 개발 방식을 말합니다. 절차지향 언어는 주로 Top Down 방식을 사용합니다. 그리고 Top Down 방식은 큰 그림에서 시스템을 분석하기 쉽고 모듈화에 용이합니다.

Bottom Up 개발 방식은 작은 단위에서 시작해서 큰 시스템을 만드는 개발 방식을 의미하고 주로 객체지향 단위 언어에서 사용하는 개발 방식입니다.

두 개념은 소프트웨어 공학에서 자세히 다루는 개념입니다. 여기서는 두 방식이 상호 배타적인 내용이 아니고 상호 보완적인 내용이라는 것 정도로 이해하고 넘어가겠습니다.

"100 이하의 소수를 출력하는 프로그램"이라는 요구사항을 Top Down 방식으로 설계 해보겠습니다.

소수 구하기 Top Down 개발 플로우차트, 수도코드 예시
그림 2. 플로우차트와 수도코드 Top Down 방식 예시

Top Down 방식은 높은 추상화 단계에서부터 점점 구체적으로 설계하는 방식입니다. 그림 2. 는 100 이하의 소수 구하기 프로그램의 플로우 차트와 수도코드의 한 예시입니다.

이 프로그램은 2부터 시작해서 100까지의 정수에 대해 소수인지를 판별하고 소수라면 그 값을 출력합니다.

이렇게 가장 Top level의 설계를 하고 나면 N이 소수인지 판단하는 것과 N값을 출력하는 두 기능은 모듈화 할 수 있다는 것을 알 수 있습니다. 그리고 각 모듈들의 구체적인 구현을 생각하기 전에 프로그램 전체의 흐름이 맞는지 먼저 점검할 수 있습니다.

그림 3. 소수 판단하는 프로그램의 플로우차트와 수도 코드

그림 3. 은 N이 소수인지 판단하는 모듈의 구체적 플로우 차트와 수도코드입니다. 이 모듈은 정수 N을 파라미터로 전달받고 소수인지 아닌지를 판단하여 그 값을 반환합니다.

내용을 살펴보면 전달받은 N이 2라면 '소수 o'을 반환합니다. 그렇지 않을 경우 2부터 N/2까지 정수 K에 대해 K가 N의 약수인지 판단하고 K가 N의 약수면 '소수'x'를 반환하고 K가 N/2보다 커지면 '소수 o'를 반환합니다.

소수구하기 프로그램 전체 플로우차트
그림 4. 100 이하의 소수 출력하는 프로그램의 전체 플로우차트

그림 4. 는 "100이하의 소수를 출력하는 프로그램"을 Top Down 방식으로 설계하고 그 과정에 발생한 개발 산출물입니다. 이제 설계한 플로우 차트를 바탕으로 구현을 해보겠습니다.

#include <stdio.h>

#define PRIME_NUMBER_YES 1
#define PRIME_NUMBER_NO 0

int check_prime_number(int N)
{
	int K;

	if (2 == N)
	{
		return PRIME_NUMBER_YES;
	}
	else
	{
		for (K = 2; K <= N / 2; K++)
		{
			if (0 == N % K)
			{
				return PRIME_NUMBER_NO;
			}
		}
		return PRIME_NUMBER_YES;
	}
}

void print_integer(int n)
{
	printf("%d ", n);
}

int main(void)
{
	int N;
	for (N = 2;N <= 100;N++)
	{
		if (PRIME_NUMBER_YES == check_prime_number(N))
		{
			print_integer(N);
		}
	}
	return 0;
}

main() 함수부터 시작해서 앞서 설계한 플로우 차트, 수도코드와 위 코드를 비교해보면 코드를 쉽게 이해하실 수 있을 것입니다.

※ Tip.
if (2 == N) 같은 코드는 if (N==2) 에 비해 휴먼에러를 줄일 수 있습니다. 간혹 if (N=2) 로 오타를 내더라도 문법 오류가 아니기 때문에 디버깅에 오랜 시간을 쓰는 경우가 종종 있습니다.

그런데 만약 프로그램의 요구사항이 "정수 X를 입력받아 N이하의 정수를 출력하는 프로그램"으로 바뀌면 어떻게 해야 할까요?

그림 5. 추가 요구사항을 반영한 플로우 차트와 수도코드

새로운 요구사항을 그림 5에서 확인할 수 있습니다. Top Down 방식으로 미리 설계하고 모듈화 하여 설계, 구현하였기 때문에 새로운 요구사항에 대해 유연하게 대응이 가능해집니다. 소수 구하기처럼 간단한 프로그램이 아니라 복잡한 프로그램일수록 Top Level 설계와 모듈화의 중요성은 커지게 됩니다. 


만약 이런 Top Down, 모듈화 없이 프로그램을 작성하면 어떻게 될까요?

int main(void)
{
	int i, k;
	for (i = 2;i <= 100;i++) 
	{
		for (k = 2; k < i; k++)
		{
			if (0 == i % k)
			{
				break;
			}
			if (k == i - 1)
			{
				printf("%d ", i);
			}
		}
	}
	return 0;
}

위 코드는 먼저 작성한 코드보다 라인수는 적지만 좋지 않은 코드입니다. 모듈화도 되어있지 않고 모든 코드가 main() 함수 안에 구현되어있어 새로운 요구사항이 있을 때 유지보수 측면에서도 불리합니다. 


마무리

좋은 개발자라면 한 줄의 코드를 작성하더라도 협업, 유지보수, 확장성 등을 고려하여 코드를 작성하도록 노력해야 합니다.

읽어주셔서 감사합니다.


C언어 관련 글 보기

sw-daily.tistory.com/category/스터디/C방장

 

'스터디/C방장' 카테고리의 글 목록

일상의 모든것

sw-daily.tistory.com

 

반응형