Nextree

디자인 패턴: Abstract Factory와 코드 중복 없애기

Nextree Dec 28, 2013 0 Comments

C 언어로 작성한 프로그램을 Java 언어로 바꾸는 프로젝트에 참여하였다. 단순히 옮겨 적는 일이라 생각했었으나, 실제로는 언어사이의 차이가 있어서 생각만큼 쉽지는 않았다. 그중 가장 큰 작업은 C 프로그램에서 많이 나타난 중복코드 처리였다. 중복 코드를 그대로 옮겨 적어야 할지, 아니면 Java 언어의 특성을 살려 제거를 할 지를 고민 했다. 결국 디자인 패턴(Abstract Factory)을 활용하여 문제를 해결하였다. 단순한 프로그램 언어 변환이 아닌 Java 다운 프로그램으로의 변환이라는 좋은 결과를 얻었다.

먼저 C 프로그램의 프로세스를 분석해보고 문제점을 파악해 보았다.

이 프로그램은 사용자가 요청한 경로를 탐색하면서, 해당 경로의 정보를 옵션 타입에 따라 계산하고 로그로 남기는 프로그램이다. 일(日) 단위로 구분되어 서버에 저장된고, 최근 10개의 데이터를 유지 하기 위해 매번 데이터를 삭제를 한다. 그리고 이 계산된 로그는 차후 가중치 값을 바꾸거나, 링크, 패스, 노드 등의 정보를 튜닝 하는데 사용된다.

프로세스를 분석하고 다음과 같은 문제점을 찾게 되었다.

너무 많은 소스 코드 라인 수
한 개의 클래스에 모든 옵션들이 있으며, 코드의 Line의 수가 8000Line 이상이다. 이 소스코드를 처음 접했을때, 파악히기 힘들었고 소스코드를 수정 할 때, 다른 소스 들도 같이 수정을 해줘야 하는 어려움이 있었다.

과도하게 축약된 변수 / 메소드명으로 인한 가독성 저하
모든 메소드명이 축약되어 메소드명 만으로 무슨 기능을 하는지 파악하기가 힘들었다. 전체 코드를 읽고 분석하는 시간이 꽤 길어졌고, 변수명도 축약형으로 되어있어 무슨 의미인지 알 수 없었다. 예를 들어 .전문가(expert)를 exp, 일반사용자(generator)를 gen 등으로 주석 없이 작성되어서 코드를 작성한 사람만 알 수 있었다.

서로 성격이 다른 기능이 한 클래스에 존재
메소드 마다 fprintf(파일을 열어 한 줄씩 쓰기 위한 C언어 함수)를 사용하여 파일을 핸들링 하고 있어, 파일관련 기능과 업무 프로세스기능이 함께 작성되어있다. 따라서 유지 보수가 어려워지고, 각각의 예외 상황에 영향을 받을 수 있다.

너무 많은 전역변수 사용

한 클래스에서 너무 전역변수를 많이 선언하였고, 그 변수를 많은 곳에서 사용을 하고 있다 보니, 메소드 마다 변소 초기화를 해주었어야 하는데, 초기화를 하지 않아 원하는 값 대신 garbage값이 들어간 버그들을 발견 할 수 있었다.

공통으로 사용되는 계산식의 중복사용

옵션 별로 공통적으로 사용하는 계산식이 메소드에 중복사용 되어 계산식이 바뀔 때마다 10개 이상의 옵션의 계산식을 일일이 수정 해야 하는 번거로운 작업을 해야 된다.

이런 문제점을 Java 언어로 변환 할 때, 어떻게 해결을 해야 할 지 고민을 했다. 나는 먼저 프로젝트의 개발기간과 유지보수의 문제점에 가장 초점을 두었고, 그 다음 C 프로그램의 문제점들을 보안하는 방법을 생각했다.

먼저 C프로그램 소스를 동일한 구조로 적용하는 방법을 생각해 보았다. 장점으로는 프로젝트 일정과 업무량을 고려할 때, 가장 빠른 시간 안에 개발이 가능 했다. 또한 현업 개발자들의 눈에 익은 구조이기 때문에 Java 언어 적응이 빠를 것이라고 생각했다. 그래서 처음 개발을 동일한 구조로 개발을 하고 리펙토링을 계획하고 개발을 했다. 그러나 C 프로그램 소스 분석을 하면서 발견한 문제점이 Java소스에도 나타났다. c언어에서 Java로 변환하면서 어느 정도 개선이 될 줄 알았던 나의 예상과는 달랐다. 개발을 하면서 너무 중복되는 소스가 많다는 것, 많은 메소드로 인하여 계산식이 헛갈린 것, 그로 인하여 많은 버그를 수정하는데 애를 먹었다.

두번째로 Abstract Factory 디자인패턴을 적용하는 방법을 생각해 보았다.

Abstract Factory 디자인패턴이란.
객체를 생성함에 있어 객체를 구성하는 부분을 추상화 하여 여러 서브클래스가 상속/구현 받아서 객체를 구성하는 부분을 동일시 하는 방법. 객체를 구성하는 클래스들이 있을 때 구현내용은 틀리지만 생성 공정이 같다면 그 부분을 추상화 해서 사용하는 것을 말한다.

위 그림은 내가 구현한 Abstract Factory 디자인 패턴을 UML로 표현해 보았다. C프로그램에서 중복된 소스를 제거하기 위해 구조를 변경을 해야 했고, 동일한 구조에, 다양한 계산식을 구현을 해야 했기 때문에 Abstract Factory 패턴을 사용했다. 위 패턴을 적용하여 각 클래스의 역할을 나누었다. Generator 클래스에서는 해당 옵션 타입을 판별하여 Factory에서 생성된 Interface 구현체를 생성하고, Builder에서 해당하는 템플릿에 맞게 결과를 생성하는 기능을 수행하도록 구분했다. 패턴을 사용하면서 동일한 구조를 가진 코드에 다양한 구현방법을 제현 하기에는 유동적이고, 클래스 간의 결합도를 낮춰 다양한 변화를 구현하기에 적합했다.

또한 다양한 옵션에 유틸성 메소드를 abstract 클래스에 포함시켜 중복 코딩을 제거 하였고, 기능별로 클래스를 구분 지어 유지 보수 및 코드 가독성을 높였다. 하지만, 이 디자인 패턴은 업무분석 / 구조 분석이 완벽히 이루어 진 다음 적용 해야 했다. 왜냐하면 이 Abstract Factory 패턴은 변경에 어려움이 있기 때문이다.

여러 옵션 중 계산식이 추가가 필요하다면(구조가 바뀐다면), 공통으로 사용되는 인터페이스 때문에 전체 옵션에 영향을 받는다. 예를 들어 특정 클래스에 사이즈 구하는 계산식이 추가/변경 된다면, Abstract 클래스에 메소드를 추가를 해야 된다. 그렇게 되면 이 클래스를 상속받는 모든 클래스에 필요없는 거리계산식을 구현해야 하는 불필요한 작업이 추가가 된다. 또한 미사용 메소드가 생기게 되어 다른 옵션에는 불필요한 코드가 생기게 된다. 이런 단점이 있기 때문에 전체의 구조를 파악 후 공통으로 뽑을 요소를 추려야 한다.

Abstract Factory 디자인 패턴을 적용하기 까지 많은 시행착오가 있었다. 프로세스를 완벽히 분석을 못하여 소스 추가 / 삭제의 작업을 수 없이 했고, 시간도 많이 소비했었다. 하지만 이런 시행착오 때문에 Abstract Factory 패턴에 대해 더 잘 알 수 있었다. 또한 Abstract Factory 패턴을 찾아보면서 다른 디자인 패턴들도 공부 할 수 있었다.

Nextree

Read more posts by this author.