8.1 프로토 타이핑

구체적인 구현에 앞서 프로그램의 전체적인 흐름만 제어하는 프로토 타이핑을 해 보기로 해요.

콘솔 응용 프로젝트 템플릿으로 프로젝트를 생성하세요. 그리고 3.1.1에서 작성한 ehglobal.h와 ehglobal.cpp 파일을 프로젝트 폴더에 복사한 후에 기존 항목으로 추가하세요.

그리고 진입점을 작성할 program.cpp 파일을 추가한 후에 비어있는 상태의 main함수를 작성하세요.

int main()
{
    return 0;
}

App, Genre, Book 클래스를 추가하세요.

여기에서는 프로토 타이핑만 할 것이며 App에서 메뉴를 선택하면 선택한 기능을 호출하는 부분까지만 구현할 거예요. 실무 프로그램에서 프로토 타이핑을 하는 이유는 이해 관계자의 요구 사항을 잘 파악하였는지 확인하기 위한 용도로 프로젝트 개발 초기 단계에서 프로토 타이핑을 합니다. 이해 관계자와 개발자는 지식 수준이나 사용하는 용어가 다르기 때문에 요구 분석을 잘못할 수 있습니다. 잘못 분석한 상태로 개발하는 것은 전체 개발 비용을 증가하는 요인으로 작용하기 때문에 제대로 분석한 것인지 확인하여 잘못 파악한 부분을 수정하여 제대로 이해 관계자의 요구 사항을 반영하기 위해 프로토 타이핑을 하는 것입니다.

먼저 Book.h 파일에 ehglobal.h를 포함하는 구문을 추가하세요.

#include "ehglobal.h"
class Book
{
public:
    Book(void);
    ~Book(void);
};

그리고 Genre.h 파일에 Book.h와 vector, algoritm을 포함하는 구문을 추가하세요.

#include "Book.h"
#include <vector>
#include <algorithm>
using namespace std;

그리고 Book *형식이 템플릿 인자인 vector를 Books 이름으로 타입 재지정합시다.

반복자도 타입 재지정하세요.

typedef vector<Book *> Books;
typedef Books::iterator BIter;
typedef Books::const_iterator CBIter;

Genre 클래스에 Books 형식 멤버 필드 books를 추가하세요.

class Genre
{
    Books books;
public:
    Genre(void);
    ~Genre(void);
};

App.h 파일에 Gerne.h와 list, map을 포함하는 구문을 추가하세요.

#include "Genre.h"
#include <list>
#include <map>
using namespace std;

Genre *형식이 템플릿 인자인 list를 Genres 이름으로 타입 재지정하세요.

반복자도 타입 재지정하세요.

typedef list<Genre *> Genres;
typedef Genres::iterator GIter;
typedef Genres::const_iterator CGIter;

isbn을 키로 하기 위해 string과 Book * 형식이 템플릿 인자인 map을 BookDic으로 타입 재지정하세요.

반복자도 타입 재지정하세요.

typedef map<string, Book *> BookDic;
typedef BookDic::iterator BDIter;
typedef BookDic::const_iterator CBDIter;

App 클래스에 Genres 형식 genres와 BookDic 형식 bookdic 멤버 필드를 추가하세요. 그리고 사용자와 상호 작용하는 Run 메서드를 추가하세요.

class App
{
    Genres genres;
    BookDic bookdic;
public:
    App(void);
    ~App(void);
    void Run();
};

App.cpp 파일에도 Run 메서드를 빈 상태로 추가하세요.

void App::Run()
{
}

진입점 main에서는 App 개체를 생성하고 Run 메서드를 호출한 후에 소멸하는 코드를 작성하세요.

int main()
{
    App *app = new App();
    app->Run();
    delete app;
    return 0;
}

이제 App의 Run 메서드를 작성합시다.

void App::Run()
{
    int key=NO_DEFINED;

사용자가 종료 메뉴를 선택하지 않으면 반복합니다.

    while((key = SelectMenu())!=ESC)//메뉴 출력 및 선택
    {

사용자가 입력한 키에 따라 약속한 기능을 호출하게 하세요.

        switch(key)
        {
        case F1: AddGenre(); break;//장르 추가
        case F2: ListGenre(); break; //전체 장르 보기
        case F3: AddBook(); break; //도서 추가
        case F4: RemoveBook(); break; //도서 삭제
        case F5: FindBookByISBN(); break; //ISBN으로 도서 검색
        case F6: FindBookAtAGenre(); break; //특정 장르 선택 후 도서 검색
        case F7: ViewAGenre(); break; //특정 장르 보기
        case F8: ListBook(); break; //전체 도서 보기
        case F9: ViewAll(); break; //전체 보기
        default: cout<<"잘못 선택하셨습니다."<<endl; break;
        }

수행한 작업을 확인할 수 있게 키를 입력해야 다시 메뉴 선택할 수 있게 하세요.

        cout<<"아무 키나 누르세요."<<endl;
        ehglobal::getkey();
    }
}

Run에서 작성한 메서드를 App 클래스의 멤버 메서드로 추가하세요. App.h 파일과 App.cpp 소스 파일 모두에 추가해야겠죠.

메뉴 출력 및 선택 기능을 구현하세요.

int App::SelectMenu()//메뉴 출력 및 선택    
{

이전에 출력한 내용을 지우세요.

    ehglobal::clrscr();

그리고 메뉴를 출력합니다.

    cout<<"장르별 도서 관리 프로그램 [ESC]종료"<<endl;
    cout<<"F1: 장르 추가 F2:전체 장르 보기"<<endl;
    cout<<"F3: 도서 추가 F4: 도서 삭제"<<endl;
    cout<<"F5: ISBN으로 도서 검색"<<endl;
    cout<<"F6: 특정 장르 선택 후 도서 검색"<<endl;
    cout<<"F7: 특정 장르 보기"<<endl;
    cout<<"F8: 전체 도서 보기 F9: 전체 보기"<<endl;

사용자로부터 입력받은 키를 반환하세요.

    return ehglobal::getkey();
}

다른 기능에서는 어떠한 기능을 선택했는지 확인할 수 있게 출력문을 작성하세요.

void App::AddGenre() //장르 추가
{
    cout<<"장르 추가"<<endl;
}
void App::ListGenre() //전체 장르 보기
{
    cout<<"전체 장르 보기"<<endl;
}
void App::AddBook()  //도서 추가
{
    cout<<"도서 추가"<<endl;
}
void App::RemoveBook() //도서 삭제
{
    cout<<"도서 삭제"<<endl;
}
void App::FindBookByISBN() //ISBN으로 도서 검색
{
    cout<<"ISBN으로 도서 검색"<<endl;
}

...중략...

다음은 프로토 타이핑에서 작성한 코드입니다.

//Program.cpp
#include "App.h"
int main()
{
    App *app = new App();
    app->Run();
    delete app;
    return 0;
}
//Book.h
#pragma once
#include "ehglobal.h"
class Book
{
public:
    Book(void);
    ~Book(void);
};
//Book.cpp
#include "Book.h"

Book::Book(void)
{
}

Book::~Book(void)
{
}
//Genre.h
#pragma once
#include "Book.h"
#include <vector>
#include <algorithm>
using namespace std;

typedef vector<Book *> Books;
typedef Books::iterator BIter;
typedef Books::const_iterator CBIter;
 
class Genre
{
    Books books;
public:
    Genre(void);
    ~Genre(void);
};
//Genre.cpp
#include "Genre.h"
Genre::Genre(void)
{
}
Genre::~Genre(void)
{
}
//App.h
#pragma once
#include "Genre.h"
#include <list>
#include <map>
using namespace std;
typedef list<Genre *> Genres;
typedef Genres::iterator GIter;
typedef Genres::const_iterator CGIter;
typedef map<string, Book *> BookDic;
typedef BookDic::iterator BDIter;
typedef BookDic::const_iterator CBDIter;
class App
{
    Genres genres;
    BookDic bookdic;
public:
    App(void);
    ~App(void);
    void Run();
private:
    int SelectMenu();//메뉴 출력 및 선택    
    void AddGenre(); //장르 추가
    void ListGenre(); //전체 장르 보기
    void AddBook();  //도서 추가
    void RemoveBook(); //도서 삭제
    void FindBookByISBN(); //ISBN으로 도서 검색
    void FindBookAtAGenre(); //특정 장르 선택 후 도서 검색
    void ViewAGenre(); //특정 장르 보기
    void ListBook(); //전체 도서 보기
    void ViewAll(); //전체 보기
};
//App.cpp
#include "App.h"
App::App(void)
{
}
App::~App(void)
{
}
void App::Run()
{
    int key=NO_DEFINED;
    while((key = SelectMenu())!=ESC)//메뉴 출력 및 선택
    {
        switch(key)
        {
        case F1: AddGenre(); break;//장르 추가
        case F2: ListGenre(); break; //전체 장르 보기
        case F3: AddBook(); break; //도서 추가
        case F4: RemoveBook(); break; //도서 삭제
        case F5: FindBookByISBN(); break; //ISBN으로 도서 검색
        case F6: FindBookAtAGenre(); break; //특정 장르 선택 후 도서 검색
        case F7: ViewAGenre(); break; //특정 장르 보기
        case F8: ListBook(); break; //전체 도서 보기
        case F9: ViewAll(); break; //전체 보기
        default: cout<<"잘못 선택하셨습니다."<<endl; break;
        }
        cout<<"아무 키나 누르세요."<<endl;
        ehglobal::getkey();
    }
}
int App::SelectMenu()//메뉴 출력 및 선택    
{
    ehglobal::clrscr();
    cout<<"장르별 도서 관리 프로그램 [ESC]종료"<<endl;
    cout<<"F1: 장르 추가 F2:전체 장르 보기"<<endl;
    cout<<"F3: 도서 추가 F4: 도서 삭제"<<endl;
    cout<<"F5: ISBN으로 도서 검색"<<endl;
    cout<<"F6: 특정 장르 선택 후 도서 검색"<<endl;
    cout<<"F7: 특정 장르 보기"<<endl;
    cout<<"F8: 전체 도서 보기 F9: 전체 보기"<<endl;

    return ehglobal::getkey();
}
void App::AddGenre() //장르 추가
{
    cout<<"장르 추가"<<endl;
}
void App::ListGenre() //전체 장르 보기
{
    cout<<"전체 장르 보기"<<endl;
}
void App::AddBook()  //도서 추가
{
    cout<<"도서 추가"<<endl;
}
void App::RemoveBook() //도서 삭제
{
    cout<<"도서 삭제"<<endl;
}
void App::FindBookByISBN() //ISBN으로 도서 검색
{
    cout<<"ISBN으로 도서 검색"<<endl;
}
void App::FindBookAtAGenre() //특정 장르 선택 후 도서 검색
{
    cout<<"특정 장르 선택 후 도서 검색"<<endl;
}
void App::ViewAGenre() //특정 장르 보기
{
    cout<<"특정 장르 보기"<<endl;
}
void App::ListBook() //전체 도서 보기
{
    cout<<"전체 도서 보기"<<endl;
}
void App::ViewAll() //전체 보기
{
    cout<<"전체 보기"<<endl;
}