코드한건데 이자가 추가가안되네요 ㅜㅜ

/연산자가  /100한걸 정수단위로 짤라서 그런가하고 더블자료형으로 소수로 이자해봣는데도 안되네요...

왜이자가안나올까요



 

 잘못된 이유는 다음과 같습니다.  

 

○ Virtual 함수 선언 / 사용에 대해서 다시 확인하세요. Virtual은 상속 하는 상위 클래스에 선언합니다. 

○ Int형 변수에 10/100을 넣으니 0이 되고, 이 때문에 이자 계산이 0이 됩니다. 



   수정된 코드는 아래와 같습니다. 
 


#include
#include

using namespace std;
const int NAME_LEN = 20;


void ShowMenu(void);//메뉴출력
void MakeAccount(void);//계좌생성
void InsertMoney(void);//입금
void ExtractMoney(void);//출금
void OutputInfo(void);//계좌정보출력

enum
{
    MAKE = 1,
    INSERT = 2,
    EXTRACT = 3,
    OUTPUT = 4,
    EXIT = 5
};

class Account
{
private:

    char*username;
    int userid;
    int usermoney;
public:
    Account(char*name, int id, int money)
        :userid(id), usermoney(money)
    {
        int len = strlen(name) + 1;
        username = new char[len];
        strcpy(username, name);
    }

    int getid() const
    {
        return userid;
    }

    virtual void deposit(int money)
    {
        usermoney += (money);
    }
    void withdraw(int money)
    {
        if (usermoney < money)
            cout << "잔액부족" << endl;
        else
            usermoney -= money;
    }
    void showinfo() const
    {
        cout << "성명: " << username << endl;
        cout << "계좌번호: " << userid << endl;
        cout << "잔액: " << usermoney << endl;
    }
    ~Account()
    {
        delete[]username;
    }
};

class NormalAccount : public Account
{
private:
    float userija;
public:
    NormalAccount(char*name, int id, int money, int ija)
        : Account(name, id, money), userija(ija)
    {
    }
    void deposit(int money)
    {
        Account::deposit(money);
        Account::deposit(money*(userija / 100));
    }
};
class HighCreditAccount : public NormalAccount
{
private:
    int userplusija;
public:
    HighCreditAccount(char*name, int id, int money, int ija, int plusija)
        :NormalAccount(name, id, money, ija)
    {}
    void deposit(int money)
    {
        NormalAccount::deposit(money);
        Account::deposit(money*(userplusija / 100));
    }
};
class Handler
{
private:
    Account*Arr[100];
    int accnum;


public:
    Handler() : accnum(0)
    {}
    void showMenu(void)
    {
        cout << "---------Menu----------" << endl;
        cout << "1.계좌개설" << endl;
        cout << "2.입 금" << endl;
        cout << "3.출금" << endl;
        cout << "4.계좌정보 전체 출력" << endl;
        cout << "5.프로그램 종료" << endl;
    }
    void MakeAccount()
    {
        int choice;
        cout << '[' << "계좌종류선택" << ']' << endl;
        cout << "1.보통계좌선택 2.신용계좌선택" << endl;
        cout << "입력:";
        cin >> choice;

        if (choice == 1)
            MakeNormalAccount();
        else
            MakeHighCreditAccount();

    }
    void MakeNormalAccount()
    {
        int id;
        char name[NAME_LEN];
        int money;
        int ija;

        cout << "[보통계좌개설]" << endl;
        cout << "이름을 입력하시오: "; cin >> name;
        cout << "계좌번호를 입력하시오: "; cin >> id;
        cout << "입금액을 입력하시오: "; cin >> money;
        cout << "기본 이자율:"; cin >> ija;
        cout << endl;
        Arr[accnum++] = new NormalAccount(name, id, money, ija);
    }

    void MakeHighCreditAccount()
    {
        int id;
        char name[NAME_LEN];
        int money;
        int ija;
        int choice;
        int plusija;

        cout << "[보통계좌개설]" << endl;
        cout << "이름을 입력하시오: "; cin >> name;
        cout << "계좌번호를 입력하시오: "; cin >> id;
        cout << "입금액을 입력하시오: "; cin >> money;
        cout << "기본 이자율:"; cin >> ija;
        cout << "신용등급[A(1),B(2),C(3)]"; cin >> choice;
        cout << endl;
        switch (choice)
        {
        case 1:
            plusija = 107;
            Arr[accnum++] = new HighCreditAccount(name, id, money, ija, plusija);
            break;
        case 2:
            plusija = 104;
            Arr[accnum++] = new HighCreditAccount(name, id, money, ija, plusija);
            break;
        case 3:
            plusija = 102;
            Arr[accnum++] = new HighCreditAccount(name, id, money, ija, plusija);
            break;
        default:
            cout << "잘못입력하셨습니다" << endl;
        }

    }
    void InsertMoney(void)
    {
        int id;
        int money;
        cout << "[입금]" << endl;
        cout << "계좌번호: "; cin >> id;
        cout << "입금액 : "; cin >> money;
        cout << endl;
        for (int i = 0; i < accnum; i++)
        {
            if (Arr[i]->getid() == id)
            {
                Arr[i]->deposit(money);
                cout << "입금완료" << endl;
                return;

            }
            else
                cout << "잘못입력" << endl;
        }
    }
    void ExtractMoney(void)
    {
        int id;
        int money;
        cout << "[출금]" << endl;
        cout << "계좌번호: "; cin >> id;
        cout << "출금액: "; cin >> money;
        for (int i = 0; i < accnum; i++)
        {
            if (Arr[i]->getid() == id)
            {
                Arr[i]->withdraw(money);
                cout << "출금완료" << endl;
                return;
            }
            else
                cout << "잘못입력" << endl;
        }
    }
    void OutputInfo(void)
    {
        int id;
        cout << "[계좌정보출력]" << endl;
        cout << "계좌번호입력 : "; cin >> id;
        for (int i = 0; i < accnum; i++)
        {
            if (Arr[i]->getid() == id)
            {
                Arr[i]->showinfo();
            }
        }
    }
};
int main(void)
{
    Handler bank;
    int choice;
    while (1)
    {

        bank.showMenu();
        cout << "선택: ";
        cin >> choice;

        switch (choice)
        {
        case MAKE:
            bank.MakeAccount();
            break;

        case INSERT:
            bank.InsertMoney();
            break;

        case EXTRACT:
            bank.ExtractMoney();
            break;

        case OUTPUT:
            bank.OutputInfo();
            break;
        case EXIT:
            return 0;

        default:
            cout << "잘못입력하셨습니다. ";
        }
    }

    return 0;

};



Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절


 

 문제 : 사전순으로 단어를 생성하여 N 번째 올 단어를 찾아라  

 


● 특정 문자열이 주어지고 이 문자열 안에 포함된 단어들을 사전순으로 정렬하라. 그리고 주어진 N 번째 오는 단어가 무엇인지 구하라.

단, 문자열의 최대 길이는 1,000 이고, 모두 소문자 알파벳으로만 되어 있다.

중복되는 단어는 한 단어로 생각한다. 

시간제한이 있다. (빠를 수록 점수가 높다, 1초가 넘으면 실패)


● 사전순이란 것은 알파벳 a ~ z 까지 단어를 정렬하는 것을 의미한다. 


● 예를 들어, melon 이란 문자열이 주어졌을 때, 7번째 오는 단어를 구하라. 

melon 안에 포함된 단어를 사전순으로 정렬하면 다음과 같다. 

1 : e

2 : el

3 : elo

4 : elon

5 : l

6 : lo

7 : lon

8 : m

9 : me

10 : mel

11 : melo

12 : melon

13 : n

14 : o

15 : on


즉, 답은 lon 이 된다. 



 

 일반적인 풀이  

 

● 풀이방법 1 : 위 문제와 같이 알파벳 a부터 문자열 안에 단어를 찾고, 그 뒤로 한글자씩 붙여서 단어를 만들어 나간다.

    

○ 문제점 :  주어진 문자열이 최대 1,000으로 길기 때문에 a가 몇번이고 반복될 수 있다. 예를 들어, a 부터 시작할 경우, 문자열 내의 모든 a 의 위치들을 기록하고, 그 뒤에 오는 단어들을 비교해서 순서를 만들어 나가야 한다. a가 세 번 반복된 경우, 각각의 단어의 뒷글자를 확인해서 순서를 정해야 한다. 위 문제의 예제와 같은 경우는 e가 한 번만 나오지만, e가 계속 반복되는 경우, 또 비슷한 알파벳이 많아지는 경우 문제가 복잡해진다. 


● 풀이방법 2 : 문자열의 첫글자부터 문자열을 만들어 나가면서 이 문자열을 이진 트리 형태로 저장하여 빠르게 정렬한다. 이를 통해 n 번째 아이템을 빨리 찾을 수 있다. 풀이방법 1의 반복적인 검색을 생략할 수 있다.

○ 문제점 : 모든 문자열을 다 만들어보아야 해서 메모리 문제가 있을 수 있다. C++이나 Java로 문제를 푸는 경우는 메모리 이슈를 피할 수 있지만 <STDIO.H> 만 허용된 C언어에서는 어려움이 있다. 트릭을 통해 malloc과 유사하게 푼다 하여도 속도 이슈가 발생할 수 있다. 실제로 C++로 이 문제를 푼 경우 제한 시간에 걸렸다. 



   답이 되는 풀이  
 

● 생각의 전환이 필요하다. 문자열로부터 시작하는 것이 아니라 사전 으로 부터 시작한다. 즉, a가 있는지 검색하고 있으면 다시 aa가 있는지 검색한다. 이 때, 문자열 전체를 보는 것이 아니라 a를 찾은 위치에서 그 바로 뒤에 문자와만 비교하면 된다. a를 찾은 위치의 인덱스를 활용한다. 


● 예를 들어, 주어진 문자열이 kdaabdgga 일 때, 

1) 우선 a 를 찾는다. 인덱스가 2에 a가 있음을 발견한다. 

2) 인덱스 2부터 aa가 있는지 확인한다. 인덱스 2에 aa가 있다.

3) 인덱스 2부터 aaa가 있는지 확인한다. 인덱스 2에는  aaa는 없다

3-1) 문자열 전체에서 aaa가 있는지 확인한다. aaa는 없다. 

4) 인덱스 2부터 aab가 있는지 확인한다. aab는 있다. 

5) 인덱스 2부터 aaba가 있는지 확인한다. 인덱스 2에는 aaba가 없다. 

5-1) 문자열 전체에서 aaba가 있는지 확인한다. aaba가 없다. 

6) aabc, aabd 등을 동일하게 확인한다. 


● 이 방식은 풀이방법 1과 비교할 때, 검색 횟수가 현저하게 줄어든다. 문자열이 랜덤하게 만들어진다는 가정하에 a는 여러번 나오겠지만, aa는 그 숫자가 적어질 것이고, aaa는 훨씬 적을 것이기 때문이다. 



   최상의 풀이  
 

● 답이 되는 풀이도 속도 문제는 있다. aaa가 있는지 확인을 첫번째 a의 인덱스 뒤로는 다 해야 하기 때문이다. 즉, 예를 들어, 주어진 문자열이 aac로 시가된다면, aab 가 있는지 aad가 있는지 문자열 전체를 검사하는 작업을 계속 반복하게 된다. 


● 이 검색 시간을 줄이기 위해서 각 알파벳에 대한 해시를 만들어 놓으면 검색 시간을 대폭 단축시킬 수 있다. 헤시 인덱스를 한단어로 만들어도 되고 두 단어로 만들어도 된다. 두 단어 이상으로 만들면 오히려 효율이 떨어질 것으로 예상된다. 주어진 문자열이 일정길이 이상일 때만 헤시 테이블을 만드는 작업을 수행하는 식으로 프로그램을 완성하면 효율적인 검색이 가능하다. 


● 헤시테이블은 간단한 이중배열로 만들 수 있다. int hash[26][10] 정도로 만들어서, 각각의 알파벳의 10번째 나오는데까지 위치만 미리 기억해놔도 문제가 쉬워진다. 워스트케이시를 대응하기 위해서는 int hash[26][1000] 이 되어야 하는데 이는 메모리 낭비가 심하다.  또는 int hash2[26*26][10] 으로 만들수도 있는데 - (aa ~ zz) 이 경우 해시를 만드는데는 시간이 더 걸리겠지만, 검색 속도는 월등히 빨라질 수 있다. 



   예제 코드  
 

● 추후 업데이트할 예정이다.








'Exercise & Quizz > C' 카테고리의 다른 글

사전 순으로 단어 정렬하기  (0) 2014.07.19
빙고 게임 - 연속되는 숫자 찾기  (0) 2012.06.11
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절


인간, 조직, 권력 그리고 어느 SW 엔지니어의 변
국내도서>컴퓨터/인터넷
저자 : 이종국
출판 : 인사이트 2011.03.11
상세보기



 

 적나라한 대한민국 S/W의 현실  

 


● 그동안 S/W 관련된 에세이 혹은 소설 종류는 거의 다 읽은 것 같다. 안철수 교수의 "지금 우리에게 필요한 것은" 부터 임백준 님의 "나는 프로그래머다", "행복한 프로그래밍", "뉴욕의 프로그래머" 같은 에세이, 소설들, 조엘 스폴스키의 그 유명한 Joel on Software 와 그의 책에서 소개하던 다른 S/W 엔지니어링 관련된 책들, "해커와 화가", "데드라인", "프로젝트가 서쪽으로 간 까닭은" 같은 또 다른 저명한 외국인들의 관련 책들까지. 프로그래밍으로 밥을 벌어먹으면서 관련된 책들은 약간의 의무감까지 느끼며 모두 읽었다. 


● 앞에서 든 책들은 모두 외국의, 특히 미국의 S/W 업계의 현실을 반영한 경우가 많다. 심지어 임백준 님의 책들 조차도 뉴욕의 S/W 회사에서 벌어지는 일이다. 내가 매일 겪는 불합리한 상황들과는 - 지금은 많이 지나갔지만, 옜날에 야근이 극심할 때는, "아 이래서 회사에 창문이 안열리는구나" 란 생각 까지 했었다. - 기본적인 전제 자체가 다르다. 아무리 바쁘고 시간에 쫒기면서 돌아가는 곳이 이 S/W 업계라 하여도 대한민국 SI 업계에서 들려오는 소문들과, 내 사촌 누님이 실제로 겪은 일들과,제조업에 기반을 둔 무늬만 IT회사에서 나와 내 동기들과 동창들이 겪는 일들은 앞서 말한 책들의 저자들은 상상조차 하지 못한 일들이다. 


● 이 책, 대한민국의 SW 현실을 다룬 진짜 첫번째 책인 아닌가 싶다. 이전에 "대한민국에는 S/W가 없다" 가 그나마 대한민국의 현실을 다루려고 했었으나, 역시나 저 높은 곳에서 책상물림이 쓴 느낌이었다면, 이 책은 진짜 PM이 수십년간 프로젝트를 진행하면 겪었던 일들이 정말, 적나라하게 적혀 있다. 


● 예를 들면 이런식이다. 어떤 방법론이나 S/W 엔지니어링 이론에 따른 산출물을 만들어 달라고 요구하면 대충그럴듯하게 만들어주면 된다. 어차피 요구한 사람도 그 자세한 내용은 보지도 않을 뿐 아니라 자기 상사에게 그럴듯 하게 보고하기 위한 용도에 지나지 않기 때문이다. 이런 식으로 신랄하게 깐다. 저자와 같이 프로젝트를 진행했던 몇몇 분들은 책을 읽으면서 자기얘기가 나와서 얼굴이 붉어질지도 모른다. 



 

 대한민국 S/W 업계가 개판인 이유 - 결국 조직내 정치싸움 

 

● SI 업계의 권력 피라미드를 그리면 대충 다음과 같다. 정점에 발주사의 CEO가 있고, 그 밑에 경영진 - IT실무부서(감리부서) - 하청업체 경영진(영업부서) - 하청업체 개발팀 순서다. 일은 하청업체 개발팀이 다 하지만, 생색은 발주사의 경영진이 낸다. 중간에 껴있는 모든 사람들은 어떻게든 자기 때문에 프로젝트가 잘 돌아간 것처럼 보이기 위해서 애를 쓰고, 파워게임을 하고, 쓸데없는 문서를 요구하고, 프로젝트 일정을 압박하고, 결국 개발팀의 누군가를 희생양으로 삼으려고 한다. 이 결과, 개발자와 그 가족들의 삶은 피폐해지고, 프리랜서들은 개발 중간에 회사를 떠나고, 심지어 프로젝트가 일정에 맞춰 성공적으로 끝나는 것을 싫어하는 사람들까지 나타난다. 자신의 공적을 내세울 곳이 없기 때문이다. 


● 돈은 개발부서가 번다. 좀 더 정확히 얘기하면, 위에 권력 피라미드에서 구체적인 부가가치를 창출하는 곳은 제일 밑바닥에 있는 개발부서이다. 그런데, 실제로는 경영, 영업부서다 계약을 통해서 매출을 창출하고, 그 이후 개발부서는 이윤을 까먹는 곳으로 여겨진다. 여기서 현시로가 괴리가 생기고, 문제가 발생하다. 


● 역시, 책상물림들이 S/W 엔지니어링이라는 학문을 만들면서 불필요한 문서들이 엄청나게 늘어났다. 문제는 이 문서 산출물들이 본래의 의도는 잃어버린채, 관리부서의 실적을 입증하는 용도로 전락해 버린다. 문서는 만들어지지만, 누구 하나 내용에는 관심도 없다는 얘기다. 실제 프로젝트와 문서와의 상관관계도 큰 관심이 없다. 결국 개발자들에게 일만 많아지고, 일의 집중력만 흐트러뜨리며, 프로젝트 일정만 늦출 뿐이다. 



 

 프로젝트의 진짜 목적은 무엇인가?

 

● 소프트웨어 개발이나 운영, 유지보수의 최종 목적은 그 안에서 일하는 우리의 행복이어야 한다. 

Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  1. ee
    2012.06.26 02:08
    댓글 주소 수정/삭제 댓글
    사실 맞는듯요 개발이 제일천대받고무시하고 빨리하라고 야근하고 주말출근에 위에선 저렇게갈구죠

문제 : 0~9까지의 정수가 10x10 으로 랜덤하게 배열되어 있다. 가로, 세로, 대각선으로 연속되는 숫자의 갯수를 찾아서, 가장 많이 연속되는 숫자를 출력하라.

 

  흔히 "빙고" 게임으로 불리는, 랜덤하게 배열된 숫자에서 연속된 숫자를 체크하는 문제이다. 가로, 세로 외에 대각선이 두 방향이 있다는 점을 주의할 것. 


  c의 이중배열은 배열은 실제로 손으로 숫자를 나열한 경우와 x, y 좌표가 반대이다. 이 부분은 직접 손으로 해보고 신중하게 검토해 볼 것. 아주 잘 헛갈리는 문제이다. 


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX_NUMBER 10
#define SIZE 10
int test[SIZE][SIZE];
int answerList[MAX_NUMBER];

int getAnswer(int game[SIZE][SIZE], int maxNumber);
int checkTopDown(int game[SIZE][SIZE], int px, int py, int maxNumber);
int checkLeftRight(int game[SIZE][SIZE], int px, int py, int maxNumber);
int checkLeftTopRightDown(int game[SIZE][SIZE], int px, int py, int maxNumber);
int checkRightTopLeftDown(int game[SIZE][SIZE], int px, int py, int maxNumber);

int main(void) 
{
	int i,j;

	/* Init game */
	srand ( time(NULL) );

	for (i = 0; i < SIZE; i++)
	{
		for (j = 0; j < SIZE; j++)
		{
			test[i][j] = rand() % MAX_NUMBER;
		}
	}

	/* print test */
	for (i = 0; i < SIZE; i++)
	{
		for (j = 0; j < SIZE; j++)
		{
			printf("%d", test[i][j]);
		}
		printf("\n");
	}
	printf("\n");
				
	/* init answerList */
	for (i = 0; i< MAX_NUMBER; i++)
	{
		answerList[i] = 0;
	}

	printf ("Longest Number is %d.", getAnswer(test,MAX_NUMBER));

	return 0;	
}

int getAnswer(int game[SIZE][SIZE], int maxNumber)
{
	int i, j;
	int biggestNumber = -1;
	int longestArray = -1;

	for (i = 0; i < SIZE; i++)
	{
		for (j = 0; j < SIZE; j++)
		{
			checkTopDown(game, i, j, maxNumber);
			checkLeftRight(game, i, j, maxNumber);
			checkLeftTopRightDown(game, i, j, maxNumber);
			checkRightTopLeftDown(game, i, j, maxNumber);
		}
	}

	/* Return biggest number */
	for (i = 0; i < MAX_NUMBER; i++)
	{
		if (longestArray <= answerList[i])
		{
			biggestNumber = i;
			longestArray = answerList[i];
		}
	}

	return biggestNumber;
}

int checkTopDown(int game[SIZE][SIZE], int px, int py, int maxNumber)
{
	int i;
	int result = 1;

	if ((py -1 >= 0) &&  (game[py][px] == game[py-1][px]))
		return 0;

	for (i = py; i < SIZE - 1; i++) 
	{
		if (game[i][px] == game[i+1][px])
		{
			result++;
		}
		else
		{
			break;
		}
	}

	if (answerList[game[py][px]] < result)
	{
		answerList[game[py][px]] = result;
	}

	return result;
}

int checkLeftRight(int game[SIZE][SIZE], int px, int py, int maxNumber)
{
	int i;
	int result = 1;

	if ((px -1 >= 0) && (game[py][px] == game[py][px-1]))
		return 0;

	for (i = px; i < SIZE - 1; i++) 
	{
		if (game[py][i] == game[py][i+1])
		{
			result++;
		}
		else
		{
			break;
		}
	}

	if (answerList[game[py][px]] < result)
	{
		answerList[game[py][px]] = result;
	}

	return result;
}

int checkLeftTopRightDown(int game[SIZE][SIZE], int px, int py, int maxNumber)
{
	int i;
	int j = 0;
	int result = 1;

	if ((px -1 >= 0) && (py -1 >= 0) && (game[py][px] == game[py-1][px-1]))
		return 0;

	for (i = px; i < SIZE - 1; i++) 
	{
		if (game[py+j][px+j] == game[py+j+1][px+j+1])
		{
			result++;
			j++;
		}
		else
		{
			break;
		}
	}

	if (answerList[game[py][px]] < result)
	{
		answerList[game[py][px]] = result;
	}

	return result;
}

int checkRightTopLeftDown(int game[SIZE][SIZE], int px, int py, int maxNumber)
{
	int i;
	int j = 0;
	int result = 1;

	if ((px + 1 < SIZE-1) && (py -1 >= 0) && (game[py][px] == game[py-1][px+1]))
		return 0;

	for (i = px; i < SIZE ; i++) 
	{
		if (px - i < 0)
		{
			break;
		}
		else if ((px-j-1 > 0) && (py+j+1 < SIZE) && (game[py+j][px-j] == game[py+j+1][px-j-1]))
		{
			result++;
			j++;
		}
		else
		{
			break;
		}
	}

	if (answerList[game[py][px]] < result)
	{
		answerList[game[py][px]] = result;
	}

	return result;
}

#define을 이용하여 사이즈와 숫자 범위를 조정할 수 있도록 했고, 랜덤하게 만들어진 문제를 출력해서 쉽게 비교해볼 수 있도록 했다. 다시 말하지만, x, y 좌표과 실제로 출력되는 x, y는 x,y 순서쌍이 바뀌어 있음을 유의할 것.


'Exercise & Quizz > C' 카테고리의 다른 글

사전 순으로 단어 정렬하기  (0) 2014.07.19
빙고 게임 - 연속되는 숫자 찾기  (0) 2012.06.11
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

자바스크립트 코딩 기법과 핵심 패턴 JavaScript Patterns
국내도서>컴퓨터/인터넷
저자 : 스테얀 스테파노프 / 김준기,변유진역
출판 : 인사이트 2011.11.03
상세보기

   고급 자바스크립트 코딩을 위하여 공부하자!!  
 


●  자바스크립트는 웹 중심으로 S/W의 트렌드가 이동하는 현 시점에서 가장 Hot 한 프로그래밍 언어이다. 그러나 프로그래밍 언어라고 부르기에는 다른 고급한 객체지향 언어에 비하여 아직 다듬어지지 않은 면이 많다. 배워서 시작하기는 쉽지만, 다른 사람이 짠 큰 코드를 분석하거나 숨어있는 버그를 찾는 일은 결코 쉽지 않다. 


●  고급한 자바스크립트 개발자로 나아가기 위해서 볼만한 책이 그리 많지 않은데, 마춤한 번역서를 찾았다. 특히 좋은 패턴과 안티 패턴을 각각 보여주면서 코딩의 지혜를 설명하는 방식이 마음에 들었다. 내용이 깊이가 있어서 공부하는데 상당히 시간이 걸릴 지도 모르겠다. 


●  아쉬운 점은 순수 자바스크립트만 다루고 있어서 jQuery 라이브러리 관련된 내용이 전혀 언급되지 않았다는 점이다. 다루는 김에 jQuery를 응용하는 부분까지 같이 다루었다면 더 좋았을 것 같다. 그래도, 어렵게 찾은 번역서이니만큼, 감사하며 공부해야지. 

Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절


C++ ESPRESSO
국내도서>컴퓨터/인터넷
저자 : 천인국
출판 : 인피니티북스 2010.11.17
상세보기


   초보자를 위한, 아주 쉬운 책
 

  회사 업무 중, 주사용 프로그래밍 언어가 C에서 C++로 변경되게 되었다. 학교 졸업 후 C++을 한동안 놓고 있었기에, 복습이 필요한 시점에서 책을 사게 되었다. 이책을 고른 첫번째 이유는 가장 최근에 출간된 C++ 책이기 때문이었다. 

  저자 천인국 교수는 현직 순천향대학교의 컴퓨터공학과 교수로 계신다. 아마도 이 책은 수업교재로 쓸 것을 염두에 두고 씌여졌을 것이다. 그만큼 이 책은 매우 쉽고, 예제가 간단명료하며, 아주 깔끔하게 똑 떨어지는 느낌이다. 번역에도 큰 무리가 없고, 억지스러운 번역은 보이지 않는다. C와 C++에 이미 익숙한 사람에게는 지나치게 쉬운 책이 될 수도 있겠다. 

  다소 아쉬운 점은, 쉽게 설명하는 것에 주안점을 두다 보니, 몇몇 부분은 설명을 생략한 부분이 있고 지나치게 정형화한 부분이 있다. 사실, 이전에 나온 많은 C/C++ 책이 C언어 특유의 확장성과 자유로움을 모두 언급하려다 이도저도 아닌, 이해하기 어려운 책이 된 경우가 많은데, 이 책은 복잡한 부분을 아얘 축약하고 생략함으로써 쉽게 넘어간 것이다. 초급자에게는 오히려 이 편이 더 큰 도움이 될 수도 있겠다만, 좀 더 설명을 구할 수 있도록 참고도서 목록나 레퍼런스 사이트를 제공했으면 좋았을 것이다. 

  좋은 과제들이 아주 많이 나온다. 역시 학교 수업을 염두에 둔 것으로 보여지는데, 관련된 샘플코드 들도 공개가 되었으면 좋겠다. (아마도 Copy 우려 때문에 계속해서 미공개 상태로 남을 것 같다.) 

  이 책을 약 두 주안에 완전히 마스터 하려고 한다. 관련된 테크니컬 리뷰를 작성하고, 과제들도 재미있는 것 위주로 좀 풀어서 블로그에 올리려 한다. 아마도 개강 무렵에는 많은 사람들이 블로그를 찾기 시작하지 않을까 싶다. 

Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절


객체지향적으로 생각하라!
국내도서>컴퓨터/인터넷
저자 : 맷 와이스펠드(Matt Weisfeld) / 배선종역
출판 : 정보문화사 2009.05.07
상세보기

   Object Oriented Programing 을 공부하기 전에 필독할 만한 책  

  오늘날 프로그래밍의 주류언어로 자바(Java)가 각광을 받으면서, 대부분의 학교에서도 Java를 가르치고 있다. 자바와 C++을 공부하는데 있어서 C의 포인터 만큼이나 넘기 어려운 부분이 있다면, 객체지향(Object Oriented)의 개념을 이해하고, 설계에 적용하는 부분일 것이다. 어떠한 문제를 해결하기 위한 프로그래밍 방법은 수십가지가 있겠지만, 객체지향의 이념을 잘 살려서 우수한 설계와 구현을 하는 것은 결코 쉬운일이 아니다. 특히나 학부 레벨에서 관련된 내용을 배우기도 쉽지 않다. 대부분 과제에서도 죽지않고 돌아가는 프로그램을 짜기 급급한 수준이다. 

  이 책은 객체지향언어를 공부하기에 앞서 한번 완독할 만한 책이다. 내용이 어렵지 않으면서, 예제 코드도 적절하게, 충분히 있고, 개념 설명과 설계의 의도를 충실히 설명해 주고 있다. 최신 기술과 트렌드들을 다양하게 다루고 있고, 여러 언어의 차이와 특성에 대해서도 비교하여 설명해 주고 있다. 이만한 개념서를 찾아보기가 어렵다. 

  물론, 학부 수준 - 프로그래밍을 공부한지 1 ~ 2 학기 정도 - 된 학생의 입장에서는 모든 내용을 100% 소화하기는 어려울 것이다. 하지만, 이 책은 학기 시작 전에 읽고, 학기를 마친 뒤에 다시 한번 읽어봐도 좋을 만한 책이다. 수학 정석을 한 번 보고 버지리 않듯이, 이 책은 여러번 읽어도 좋을 만큼 내용이 다양하고, 새내기 프로그래머에게 주는 교훈들이 많이 들어있다. 

  충분히 읽어 내용을 이해한다면, 아니 이해하지 못해도 충분히 숙지해 둔다면, 후에 고급 개발자로 나아가는데 큰 도움이 될 만한 책이다. 강추한다. 

Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절


스크럼 Scrum
국내도서>컴퓨터/인터넷
저자 : 켄 슈와버,마이크 비들 / 박일,김기웅 역
출판 : 인사이트 2008.10.01
상세보기

   프로그래밍에서 가장 중요한 것은?
 

  적게는 2~3명, 많게는 300명 이상의 공동작업으로 이루어지는 현재 소프트웨어 프로젝트에서 프로그래밍을 할 때, 가장 중요한 것을 꼽으라면, 단연 "커뮤니케이션 능력" 을 들 것이다. 프로그래밍이란 것이, "언어" 를 이용하여 "창작"을 하는 과정이기 때문에, 일종의 공동 문집을 만들어 나가는 과정이다. 한권의 문집이 군더더기 없는 글의 집합이 되려면 글 한 편 한 편이 올바라야 하지만, 무엇보다 무엇을 위한 문집인지, 어떻게 통일성을 갖는 한 권의 책을 만들어 낼 것인지 의사를 결정하고, 결정된 내용을 모두 함께 따르는 것이 중요하다. 교정은 누가 볼 것이고, 부족한 내용은 누가 보충할 것인지, 퇴고는 어느 방향으로 할 것인지 등을 결정하고, 지시하고, 지시에 따르는 것이 필요하다. 대규모 프로젝트 또한 이와 동일해서, 수백명의 똑똑한 개발자들이 모인 상황에서 가장 중요한 것은 한방향으로 의샇소통을 하는 것이다.

  그럼에도 불구하고, 현실에서는 여전히 군대식 의사소통이 만연해 있는 것이 사실이다. 욕설과 함께 설명이 생략된 일정 제시와, 앞뒤 안재고 무조건 "예 알겠습니다" 를 복명복창하는 중간 관리자들, 그리고 내용은 묻지 않고 무조건 수정하라고 문제를 재지정하는 팀 리더들과 조금이라도 다른 팀과 얽히면 문제를 토스하기에 바쁜 실무자들. 마지막으로 뭘 해야 할지 알지 못하고 헤메고 있는 신입 사원까지. 하나의 개발팀이 제대로 돌아가는 것은 기적에 가깝다.

   우리, 이제 계급장을 떼고 스크럼을 해보자 
 

  특히, 긱(Gig)들이 모여있다는 프로그래머 집단 사이에도 엄청난 권위주의가 팽배해 있다는 것은 정말 신기한 일이다. 군대를 안다녀온 여자들 까지도, 선배라는 타이틀과 함께 목에 힘 딱 주고, 너는 내가 시키는 일이나 해라. 니가 뭘 아냐. 난 니가 대학에서 찌질대고 있을 때, 이 코드를 혼자 다 짰다. 는 식으로 업무지시를 하는 일도 흔하고, 문제를 토스하는 와중에서도 어느쪽이 짬이 높냐가 최종 목적지를 결정짓는 일도 흔하다. 믿기지 않겠지만, 대한민국의 대부분의 조직은 이렇게 경직되어 있고, 이런 문화 자체가 개발자의 창의성을 죽이고, 더 나아가 팀의 생산성을 극도로 떨어뜨린다. 모두 같이 밤을 새고 있지만, 그 사람들이 하고 있는 일이 유럽 필드에서 날아올 메일 한통이라는 사실은 종종 내가 무엇을 위해 이짓을 하고 있나 하는 생각을 들게 한다. 좀더 나아가, 실제로 일은 컴퓨터가 하고 있는데, 사람들이 그 뒤에서 결과를 던져주기만을 두 세시간씩 기다리는 일도 흔하다.

  스크럼의 가장 큰 장점은 각자 어제 한 일, 오늘 할 일, 일을 하는데 막히는 점을 자주 만나 이야기 함으로써 서로의 진행상황을 공유하며, 관리자들에게는 할 일을, 개발자들에게는 해야 할 일을 명확히 한다는 점이다. 무엇보다 상명 하복이 아닌 자유로운 대화는 개발자 한 사람 한 사람의 존엄성을 높여줄 수 있다. 조직을 숨쉬게 만들 수 있다.

  이제 우리 스크럼을 해보자. 되도 않는 직급이니 경력이니 입사 기수 같은거 던져 버리고, 프로그래머 대 프로그래머로 대화하며 일을 해보자. 우리에게 필요한 것은 막무가내식 지시가 아니라 서로의 생각을 공유할 수 있는 통로이다.




Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

logo homepage


  Stack Overflow무료 프로그래밍 Q & A 사이트 입니다. 질문을 올리는 것도 무료이고, 답변을 다는 것도 무료 이고, 글을 읽는 것도 무료, 인덱스를 다는 것도 무료 입니다. 평범하고 전통적인 HTML로 만들어져 있고, 낚시글은 없습니다.(no fake rot13 text on the home page), 쓸데없는 구글 검색에 걸리지 않게하는 기술을 사용하지 않고, 장사꾼도 없고, 질문 당 12.95달러를 요구하는 자바 스크립트 윈도우도 나오지 않습니다. 여러분이 카르마(karma : 지식인의 내공과 비슷한 점수 : 역자 주)를 모으거나 가치있는 명성을 얻어 여러분의 이름 옆에 나타나게 하고 싶다면 사이트에 가입하실 수도 있습니다. 하지만, 그렇지 않다면, 이 사이트는 그냥 무료 입니다. 그리고 빠릅니다. 아주, 아주 빠르지요.

  여러분은 Stack Overflow를 운영하지 않습니다. 정말로요. Stack Overflow는 여러분의 동료 프로그래머들에 의하여 공동으로 만들어지고 유지됩니다. 일단 시스템이 여러분을 신뢰하게 되면, 여러분은 모든 것을 편집(수정)하실 수 있게 됩니다. 마치 위키피디아 처럼요. 여러분의 도움으로, 우리는 좋은 답변들과 상상할 수 있는 모든 프로그래밍 관련 질문들로 이루어진 사이트를 만들 수 있습니다. 어떤 프로그래밍 언어를 사용하지, 혹은 어떤 OS를 여러분이 메인으로 사용하는 지는 중요하지 않습니다. 더 나은 프로그래밍이 우리의 목적입니다.

  우리는 Stack Overflow를 마찰이나 고통없이 사용할 수 있다도록 만들었습니다. 여러분의 프로그래밍 관련 질문들에 대한 정답을 성공의 구덩이에 빠지는 것 만큼 쉽게 (as easy as falling into the pit of success) 찾을  있을 것으로 확신합니다. 아마도 그 길을 따라가는 동안에 약간의 재미도 있을 것입니다.

그래서요? 누가 신경이나 씁니까? 이건 그냥 수없이 많은 다른 웹사이트랑 같은거 아닌가요?

  이 사이트가 뭐가 그렇게 특별하냐고요? 예, 아무것도 없습니다. 정말로요. 이것은 프로그래밍 Q&A 사이트 입니다. 유일한 다른 점은 우리는 위키, 블로그, 포럼, 그리고 디그/레딧 (Digg/Reddit)의 고유한 모든 특성을 통합했다는 것입니다. 혹은, 최소한 우리는 이 사이트를 그렇게 만들었다고 생각합니다.


Venn diagram: Wiki, Digg/Reddit, Blog, Forum

  Stack Overflow는 위 그림에서 가운데 있는 작은 별표(*) 입니다.

  하지만, 희망적이게도, 여러분은 우리가 이야기 하는 것을 스스로 경험하는 동안에 알게 될 것입니다.

당신들은 누구입니까?

  우리는 여러분과 같은, 대단한 소프트웨어를 만드는 일을 사랑하는 소프트웨어 엔지니어입니다. Stack Overflow team은 다음과 같습니다.

picture of Joel Spolsky
Joel Spolsky
New York, NY
picture of Jeff Atwood
Jeff Atwood
El Cerrito, CA
picture of Jarrod Dixon
Jarrod Dixon
Morganton, NC

picture of Geoff Dalgas
Geoff Dalgas
Corvallis, OR
picture of Jeremy Kratz
Jeremy Kratz
Little Rock, AR
picture of Brent Ozar
Brent Ozar
Whitehall, MI


당신의 이야기와 사진은 정말 매력적이네요. 더 알 수 있을까요?

  Stack Overflow FAQ를 확인하십시요. 우리에게 연락하실 필요가 있다면, team@stackoverflow.com 으로 하시면 됩니다.

(끝)

PS. 프로그래밍 하시다가 막히는 부분이 있다면 질문을 올려보세요. 현재 세계에서 가장 유용한 프로그래밍 관련 사이트 입니다. 물론, 영어로 올리셔야 겠지요.

Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  1. 2013.09.12 14:28
    댓글 주소 수정/삭제 댓글
    안녕하세요! 검색을 통해 방문하게 되었습니다.
    Stackoverflow.com 의 장점을 그대로 가져온 한국어 사이트 Codeflow를 소개합니다.

    만들어진지 얼마 안 된 개발 관련 Q&A 사이트입니다 :) 한 번 들러주세요~
    http://codeflow.co.kr/

  새로운 프로젝트가 시작되면서 협력업체의 도움을 받기로 했다. 인력이 부족하다는 판단에서 상부에서 결정한 것이지만, 맨먼스 미신의 신봉자로써, 이번에도 결과는 별로 좋지 않을 것으로 생각된다. 내가 직접 하는 것보다 더 일이 빨리 될 것 같지도 않고, 오히려 커뮤니케이션에 문제만 있을 것 같은데... 위에서 시키는 일이라 어쩔 수는 없다. 

  사실, 협력업체분이 제대로 준비되지 않은 상태에서 일을 시작하는 것과, 평소에 하던 일을 하던 사람이 투입되서 일을 하는 것은 속도와 효율에 차이가 클 수 밖에 없다. 작업결과에 대한 머지는 결국 내일이 될 것이고... 나중에 정말 급한 문제가 생기면 또 내가 수정하게 될 것이고... 인력을 이런식으로 투입한다고 더 효율이 올라가지 않는 다는건 이미 수없이 많은 프로젝트에서 증명된 명제 아닌가. 이러니 IT가 아니고 제조업이라고 자꾸 투덜대는 일이 생긱는거다.

  위에서 야근 시키면 열라 짜증내던 난데, 이젠 야근을 강요하고 강제하는 입장이 되버리는 거다. 참 불합리한건데, 장비 하나 제대로 갖추지 못해서 일 시키는데만 일주일 가까이 딜레이가 된거다. 시뮬레이터도 없어서, 다운 받아가면서 확인하면 작업이 얼마나 비효율 적인지 알면서도 "몇일 까지 하라고 팍팍 쫘요" 라고 위에서 날 쪼는데, 참. 이건 아닌데...  그러잖아도 "하청은 IT의 막장"이라는 말이 나오는데, 미안하게도 거기에 내가 일조하게 된 것 같아 기분이 좋지 않다.

  언젠가는, 나도 과장이되고 (잘하면) 부장이 되서 개발에서 손 떼고 인력관리에 집중하라는 압박을 받을 텐데, 벌써부터 걱정이된다. "우리팀은 애자일 방식으로 8시간 근무 철저히 준수하고, 매일 스크럼 하고 코딩은 반드시 패어로 합니다" 라고 말하고 팀을 운영한다면, 위에서는 "왜 니네팀은 다른 팀 다 남아있는데 집에 가냐?" 는 질문을 받을테고 밑에 사람들한테는 "일하기도 바빠 죽겠는데 무슨 놈의 스크럼이냐"  혹은 "둘이 나눠 짜도 다 못하는데 언제 둘이 같이 짜고 있냐" 같은 말을 들을 것 같아서 그렇다. 그럼 난 뭐라고 둘러대야 하지?

  아니면, 그냥 내 선배들이 그랬던 것 처럼 나도 짜증나는 또 한명의 과장이 되는 것이 필연인가... (바둑에서 말하는 필연 말이다. 이 행마를 진행할 수 밖에 없는 필연적 국면같은...)

  아 이런일 하기 정말 싫은데... 정말 싫은데... 그냥 내가 야근하고 말지. 이건 정말 아니다.
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  1. 2009.05.10 13:07 신고
    댓글 주소 수정/삭제 댓글
    사실 야근을 직접 하는것 보다도 시키게 되는 입장이 더 난감하죠. 물론 좀 지나면 내성이 생깁니다만 ㅎㅎ
    뭐랄까..한국 IT는 오히려 다른곳보다 더 경직된 곳이 아닐까 싶어요.
    하드웨어는 최신기술을 만지고 있지만 소프트웨어와 시스템 자체는 예전껄 고집하죠.

프로그래밍 원리(2ND EDITION)
카테고리 컴퓨터/IT
지은이 HISAO YAZAWA (성안당, 2009년)
상세보기

  내용이 생각보다 많이 간략하고 단순합니다. 프로그래밍과 컴퓨터공학의 기초적인 내용들을 설명하고 있는데, 어려운 내용들은 일단 많이 생략을 하고 있습니다. 사실, 대학교에서 전공을 하면서 이책을 읽고 새롭게 배운 것이 있다는 것은 공부를 안했다는 뜻일겁니다. 내용 자체는 1학년때 배우는 개론과 전공교양과목에서 다 설명되는 부분입니다. (어셈블리가 커리큘럼에서 빠져서 그부분은 새로왔습니다.) 대학교 1학년을 마치고 이책이 새롭게 다가왔다면 반성하셔야 할겁니다.

  그럼에도 불구하고 컴퓨터에 관심이 없는 분이 읽고 뭔가 얻을 수 있을만큼 쉬운 책은 아닙니다. 대학교 1학년 개론서 정도로는 적당하지만 비전공자가 읽어서는 도통 무슨 내용인지 알기 힘들 것 같네요. 광고의 내용보다는 내용이 많이 적습니다. 종이가 두껍고 편집이 넉넉하게 되있고, 삽화와 코드, 도표까지 있어서 그렇겠지만 말입니다.

Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  지금 진행하는 작업은 세 개의 테이블이 서로 얽히고 섥혀서 돌아가는 어플리케이션이다. 좀더 상세하게는, 특별한 복사본을 갖고있는 두 개의 테이블과, 테이블 간의 관계를 관리하는 테이블 한개를 포함해서 여섯개의 테이블이 맞물려 있다. 특히 어려운 점은, 이 테이블들이 동시에 설계된 것이 아니고 전혀 별개의 기능들을 구현하면서 설계된 테이블인데다 이 기능을 위한 특화된 테이블 들도 아니라는 점이다.

 이런 상황에서 문제를 해결하기 위해, 복잡한 알고리즘을 고안하기 보다는, 끊임없이 테이블간의 싱크를 맞추는 방법을 선택했다. 어떤 동작을 할 때 마다, 화면의 갱신이 있을 때 마다 가장 최신의 정보를 모든 테이블이 동일하게 갖을 수 있도록 쿼리를 짰다. DB를 사용하면 편한점이, 일일이 루프를 돌려서 경신할 필요가 없이 쿼리를 DB에 던져주는 것 만으로도 모든 열들의 갱신이 이루어진다는 점이다.

  내 설계는 DB의 갱신이 일어날 때 마다 모든 테이블의 상태를 일치시켜주는 방식으로 진행이 되었다. 이 방식의 장점은 명확한 동작과 기능간의 인터랙션 설계가 없는 상태에서 안정된 구현이 가능하다는 점이다. 각각의 기능 중 한쪽에만 수정 사항이 보이는 일은 일어나지 않고, 혹시나 놓질 수 몇몇 예외상황에 대해서도 곧 회복이 되어 정상동작으로 돌아간다는 점이다. 구현도 어렵지 않았고, 무엇보다 핵심 기능을 쿼리들이 수행해 주기 때문에, 나중에 컨셉이 바뀌거나 세부 요구사항이 변경될 때도 수정이 쉽다는 장점이 있다.

  문제는 이런 방식은 임베디드 디비에서 동작하기에는 부하가 크다는 점이다. 더구나 각각의 기능들의 엔트리가 Max 1000개 까지 지원되는 상황에서 이 기능들이 Full Sync가 일어나는 상황에서는 약 30초 정도 화면이 멈춘 듯이 보이기도 한다. (모래시계를 돌려야 한다.) 이를 방지하기 위해서 쿼리 최적화에 굉장히 공을 많이 들였지만, 한계가 있었다. 특히 날짜 계산에서 여러가지 예외상황과 추가 요구사항에 대응하기 위하여 더 복잡한 쿼리를 사용하게 되었다. (이 쿼리에 관한 내용은 다음에 글을 쓸 기회가 있을 것이다.)

  결론을 이야기 하면, 결국 대부분의 코드를 최근에 추가되거나 수정된 엔트리만 다른 테이블에도 업데이트하도록 수정을 할 수 밖에 없었다. 가장 큰 이유는 Full Sync 동작에서 메모리 부족으로 리셋이 나는 것이 발견되었고, 그 오류가 서드 파티 라이브러리 내부의 문제라서 내가 손을 댈 수 있는 영역 밖이었다. 둘째는 속도 문제였는데, 이 또한 라이브러리 내부에서 가비지 콜렉션이 부족해서 발생하는 것으로 실험 결과 증명되었다. 서드 파티 라이브러리를 쓰는 것이 이런 문제를 안고 가기 때문에 항상 쉽지 않다.

  결국, 내가 구현한 기능이 아닌 다른 기능의 흐름을 철저하게 분석할 수 밖에 없었고, 그 상황에서 필요한 동작에서 최소한의 업데이트만 수정하도록 쿼리와 함수를 고쳤다. 참고로, 난 다른 기능의 구현 상황을 전혀 알지 못했고, 더군다나 이번에 처음 분석을 한 기능은 두 가지였다.

  처음에는 Full Sync 방식이 쉽게 쉽게 가면서 동작에서의 오류를 최소할 수 있는 종은 방법이라고 생각했지만, 결과적으로 기능 분석을 통해 최소한의 부하를 갖는 방식으로 갈 수 밖에 없었다. 지금길로 간다고 생각했지만, 거대한 삽질을 했던 것에 불과하다. 3월 한달이 이 엄청난 튜닝작업에 소모되었다. 특히 막판 수정으로 이틀을 날렸다. 토요일에 풀타임 근무를 할 수밖에 없었다.

  교훈 : 쉬운 길이 문제가 아니다. 결국은 최고 효율을 낼 수 있는 제대로된 설계와 구현이 필요하다.

  더 큰 교훈 : 이 프로젝트의 시작에 요구사항 분석과 설계가 결여되어 있었을 뿐 아니라, 함께 연동되는 기능들 간에 의사소통이 너무 적었다. 젠장.
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절



원문보기
By: Joel Spolsky

  Published March 2009


  새로운 비지니스는 단파 라디오와 같습니다. 여러분은 신호가 잡힐 때까지 인내심을 가지고 주파수를 맞춰야 합니다.

  공항 서점의 기업사(business-hagiography) 섹션의 책들 - 아마존(Amazon), 델(Dell), 구글(Google) 그리고 스타벅스(Starbucks)같은 회사들이 다른회사들이 왼쪽(zigged)으로 갈 때 어떻게 오른쪽(Zagging)으로 갔으며 어떻게 그렇게 막대한 수익을 거뒀는지에 관한 이야기들이죠 -  많이 읽다보면 한가지 패턴을 발견하게 됩니다. 이런 책들에 소개되는(profiled) 회사들의 대부분 엄청난 성공을 거둔 케이스이고, 몇몇은 엔론(Enron)같은 종류의 비웃음 거리가 될 정도엄청난 실패  케이스 입니다.

  문제는 이런 기업들중 한가지 모델을 따라하는 것은 쓸데없는 일입니다. 스타벅스의 성공공식 중 어떠한 부분이 수많은 라이벌 회사들이 실패하는 가운데 성공을 이끌어 냈는지 알기 어렵기 때문입니다. 스타벅스의 성공은 정확히 시기에 정확한 방법으로 여러 요소들이 합쳐져서 이루어진 결과입니다. 이중 어떤 요소가 가장 중요한 것인지 알아내는 것은 불가능에 가깝습니다. 아마도 수백 개의 성공하지 못한 커피 체인들의 실패사례를 관찰하고 나서야 무엇이 스타벅스를 구별되게 했는지 관찰할 가능성이 있을 것입니다. 

   투자에 있어서, 성공은 너무 가까이에서 관찰하면서 실패는 전혀 보지 않는 현상은 "패자 배제" (Survivorship Bias : 금융관련 통계에서, 망해버린 회사나 펀드는 더 이상 존재하지 않는 다는 이유로 통계에 넣지 않는 정책을 말한다. 일반적으로, 통계 그래프를 상향 조정, 왜곡하게 된다)으로 알려져 있습니다. 예를 들어, 어디에선가 "펀드 평균 수익률 8.3%" 라는 글을 읽을 때- 제가 방금 만든 겁니다 - 여러분은 이 수익률을 계산할 때 일반적으로 손해가 너무 심해서 파산해 버린 펀드는 계산에 넣지 않는다는 사실을 기억하셔야 합니다.

  몇달 전에는 제 마음속에도 기업에 관한 패자 배제 정책이 있었습니다. 제 회사는 보스톤에서 컨퍼런스를 가졌는데, 저는 제 친구인 제시카 리빙스톤(Jessica Livingston)을 강사로 초청했습니다. 제시카는 작은 앤젤 투자회사인 Y Combinator의 공동 창업자입니다. 이 회사는 두 세명의 괴짜들이 기술 벤처 회사를 시작할 수 있도록 몇천달러의 자금을 제공하는 일을 합니다. 그녀는 30여명의 성공한 벤처사업가를 인터뷰한 "일하는 창업자들" (Founders at Work)란 책을 썼습니다. 그녀가 제게 강연 주제에 관하여 물어왔을 때, 저는 성공한 사람들로 부터 얻을 수 있는 일반적인 교훈이 아닌, 벤처회사가 실패하게 되는 다른(잘못된) 방법들에 대하여 이야기 해주기를 요청했습니다.

  "그건 좀 지루할거에요" 그녀가 말했습니다. "그들은 모두 같은 이유에서 실패했습니다. 그들은 단지 그들의 사업분야에서 일하기를 멈춘거에요." 음, 예. 물론, 그렇겠지요. 대부분의 사람들은 그들의 심장이 뛰기를 멈출 때 죽으니까요. 하지만, 어떤 죽음은 여전히 주당 40시간의 프로그래밍(40 hours a wwek of prime-time programming)을 할 만큼 흥미롭습니다. (역자주 : 마지막 문장은 좀 이상하지요? 주당 40시간의 프로그래밍은 글쓴이의 관점에서 모든 업무를 제쳐둘 만큼 가치가 있다는 뜻으로 쓰인 것 같습니다.)

    그렇지만, 이 문제에 관해서 생각하면 할수록, 제시카가 이야기 한 것을 알 것 같습니다. 왜 벤처회사가 실패할까요? 그녀가 지적했듯이, 그 이유는 일반적으로 의욕(Motivaton)이 상실입니다. 모두들 일상생활도 돌아가고, 벤처회사는 끝입니다. 뻥 소리도 없이, 작은 소리와 함께  사라집니다.

  제시카의 남편이자 Y Combinator의 파트너인 폴 그래함(Paul Graham) 이 주제에 관하여 그의 웹사이트에서 태클을 걸었습니다. "창업자들이 그들의 벤처회사 사업을 접는 가장 큰 이유는 그들이 사기(Morale, 士氣)를 잃기 때문입니다" 그가 웹사이트에 적은 글입니다. "어떤 사람들은 끊임없이 스스로 사기 충만해 집니다.  이런 사람들은 거의 대부분 언제나 성공합니다. 이런 사람들의 반대편 끝에는, 스스로 사기 충만해질 능력이 전혀 없는 사람들이 있습니다. 중간에는 어느정도 사기가 있지만 무한하지는 않은 사람들의 넓은 구간에 있습니다. 이런 사람들은 사려깊은 사기 관리(Morale management) - 와 약간의 행운 - 이 필요합니다.

 - 2부에서 계속 -


 

Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

  문제가 굉장히 심각하다.

  맡은 기능을 구현함에 있어서, 요구사항 문서를 명확하게 확인하지 못한게 문제의 시작이었다. 이미 납품된 레퍼런스 폰이 있어서, 문서 분석을 등한시하고 작업을 시작한 것이 일을 크게 만들었다. 문제는, 납품되었던 레퍼런스 폰이 요구사항을 자의적으로 해석해서 잘못 적용한 폰이었다는 것이다. 그걸 따라한 나도 바보가 되어 버렸다.

  요구사항 분석은 모든 구현 작업에 선행되어서 꼼꼼하게 진행되어야 함에도 불구하고, 난 가장 기본을 무시하고 진행을 했던 것이다. 프로젝트 시작 몇달 전에 문서를 읽어본 것이 다고, UI 문서는 몇번 더 읽었지만 정작 요구사항 문서가 뭔지, 어떤 의미를 갖는지, 뭐가 더 중요시되야 하는 문서인지 전혀 배경지식도 없이 일을 진행하고 있었다. 이건 시말서를 쓰라고 해도 할 말이 없고, 욕을 먹어도 할 말이 없는 상황이다.

  토요일 집에서 쉬고 있는데도 뭔가 미심쩍고 마음이 무거워서 (사실 마음이 무거웠던 이유는 퍼포먼스 문제가 해결이 덜 된 상태였기 때문이다) 사무실에 나가서 갑 쪽의 피드백과 초기 요구사항 문서를 다시 뒤져 보았다. 이런 젠장. 내 잘못이다. 빼도 박도 못할 정도로...

  지난 주에 처음 이슈가 올라왔을 때, 레퍼런스 폰 개발팀에 확인 요청 메일을 보냈었는데, 거기도 요구사항에서 그런 내용 본적 없다는 뻘 답변을 보내왔던 것도 웃기는 상황이지만, 어쨌든 재대로 요구사항 분석을 하지 못했던 내 탓이다. 내 문제다. 끙...

  입사 4년차. 한껏 잘난 척하고 우쭐대던 내 모습이 부끄럽기 그지없다. 그동안 읽은 소프트웨어 엔지니어링 관련 책들과 문서들은 도대체 무엇을 위함이었던가. 처음으로 단덕으로 맡은 업무를 이따위로 해놨으니...

  월요일에 사수님 만나서 자아비판 부터 해야겠다. 아 완전 바보가 된 느낌이다.

  오늘의 교훈 : 절대로, 구현 완료된 상황을 믿지 말라. 업체 요구사항 문서만을 신뢰하고 미심쩍은 부분은 바로 피드백하라. 문서로 시작해서 문서로 끝나야 한다. 스스로 판단하기에는 아직 어리숙하다는 점을 다시금 깨달았다.

 
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

// Written by rinehart

// rinehart@naver.com

//2007. 6. 8

/* Note :  This code will be better if get map text from file. (I'm lazy...)

Maybe, some part of main function need to seperate to another functions */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAP_MAX 100
#define Type_New_map    1
#define Type_Read_map  2
#define Type_Exit               3


int Get_String(char *input_buf, int *m, int *n);


int Get_Result(char **map, char **result, int m, int n);


int Print_Result(char** result, int m, int n);


int Set_Mark(char* target);


int main()
{
        char buf[MAP_MAX];       
        char **map;
        char **result;
        int m = 0, n = 0, line_counter = -1;
        int Type = 0;
        int loop;

        while (1)
        {
                Type = Get_String(buf, &m, &n);

                if (Type == Type_Exit)
                        break;
                else if (Type == Type_New_map)
                {
                        map = malloc(sizeof(char*) * m);
                        result= malloc(sizeof(char*)*m);
                       
                        for (loop = 0; loop < m; loop++)
                        {
                                map[loop] = malloc(sizeof(int*)*n);
                                result[loop] = malloc(sizeof(char*)*n);
                        }
                               
                        line_counter = 0;
                }
               
                for (loop = 0; loop < n; loop++)
                {
                        Type = Get_String(buf, &m, &n);
                        if (line_counter >= m)
                        {
                                // Get the Result
                                m = 0;               
                        }
                        else
                        {
                                strcpy(map[line_counter], buf);
                                line_counter++;               
                        }
                }

                Get_Result(map, result, m, n);
                Print_Result(result, m, n);
        }
       
        printf ("\nEnd of Program\n");
       
        return 0;
}


int Get_String(char *a_buf, int *m, int *n)
{
        int result_Type = Type_New_map;
        int t_m, t_n;
        char *token;

        memset (a_buf, 0x00, sizeof(a_buf));
        gets(a_buf);

        if (a_buf[0] == '.' || a_buf[0] == '*')
        {
                result_Type = Type_Read_map;
        }
        else
        {
                token = strtok(a_buf, " \n");
                t_m = atoi(token);
                token = strtok(NULL, " \n");
                t_n = atoi(token);
                if(t_m ==0 && t_n == 0)
                        result_Type = Type_Exit;
                else
                {
                        *m = t_m;
                        *n = t_n;
                        result_Type = Type_New_map;
                }
        }

        return result_Type;
}


int Get_Result(char **map, char **result, int m, int n)
{
        int loop1, loop2;

        for (loop1 = 0; loop1 < m; loop1++)
        {
                for (loop2 = 0; loop2 < n; loop2++)
                {
                        result[loop1][loop2] = '0';
                }
        }

       
        for (loop1 = 0; loop1 < m; loop1++)
        {
                for (loop2 = 0; loop2 < n; loop2++)
                {
                        if (map[loop1][loop2] == '*')
                        {
                                result[loop1][loop2] = '*';

                                if (loop1 != 0)
                                {
                                        Set_Mark(&(result[loop1-1][loop2]));
                                        if (loop2 != 0)
                                                Set_Mark(&(result[loop1-1][loop2-1]));                                        
                                        if (loop2 != n-1)
                                                Set_Mark(&(result[loop1-1][loop2+1] ));
                                }
                                if (loop1 != m-1)
                                {
                                        result[loop1 +1][loop2] ++;
                                        if (loop2 != 0)
                                                Set_Mark(&(result[loop1 +1][loop2-1]));
                                        if (loop2 != n-1)
                                                Set_Mark(&(result[loop1 +1][loop2+1]));
                                }

                                if (loop2 != 0)
                                        Set_Mark(&(result[loop1][loop2-1]));                                   
                                if (loop2 != n-1)
                                        Set_Mark(&(result[loop1][loop2+1]));   
                        }
                }
        }

        return 0;
}


int Print_Result(char** result, int m, int n)
{
        int loop1, loop2;
        for (loop1 = 0; loop1 < m; loop1++)
        {
                for (loop2 = 0; loop2 < n; loop2++)
                {
                        printf ("%c", result[loop1][loop2]);
                }
                printf("\n");
        }
        printf("\n");

        return 0;
}


int Set_Mark(char* target)
{
        if (*target != '*')
                *target = *target+1;
        return 0;
}

Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

x,y의 좌표가 주어졌을때

각도 구하는 코딩 가르쳐주세요!!

x, y 좌표를 이용해서 좌표축에 만들어지는 삼각함수를 이용하면 됩니다.

각도를 A 라고 하면, tan(A)  = y/x 가 되지요.  반대로, x, y 좌표를 이용해서 각도 A를 구하는 것은 역함수 아크탄젠트를 이용하면 됩니다. 자세한 수학적 이론은 정석의 삼각함수를 찾아보세요.

C 언어 라이브러리 중에 math.h 가 있습니다. 삼각함수를 제공합니다.

함수 설명은 http://www.cplusplus.com/reference/clibrary/cmath/atan2.html 여기를 참조하시고요, 예제코드는 아래 있습니다.

Example

/* atan2 example */
#include
#include

#define PI 3.14159265

int main ()
{
double x, y, result;
x = -10.0;
y = 10.0;
result = atan2 (y,x) * 180 / PI;
printf ("The arc tangent for (x=%lf, y=%lf) is %lf degrees\n", x, y, result );
return 0;
}

Output:


The arc tangent for (x=-10.000000, y=10.000000) is 135.000000 degrees.
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절

안녕하세요. 컴공과 1학년 블로그 과대표 로엔그린 입니다.

네이버에 본래 블로그를 운영하고 있었으나, 좀더 전문적인 내용으로 바꾸기 위하여 컴퓨터 관련된 내용을 새로운 블로그로 독립하여 운영합니다. 기존 블로그는 본의 아니게 지나치게 정치색(?)을 띠게 되어버렸습니다.

과대표 소개를 간단하게 드리면, 최초로 베이직으로 프로그램을 짠지 한 16년 정도 되었습니다. 컴공과에 입학하여 C언어를 배운지 10년 정도 되었습니다. 그리고, 지금도 프로그램을 만드는 것을 업으로 하고 있습니다.

어떤 개그맨은 "16년 정도 하면 달인이다" 라고 주장합니다만, 아직 짠 프로그램의 수가 5만 6천개가 안되서인지... 아직 달인이라고 부르기는 부끄러울 정도의 수준입니다.

프로가된 지금 돌아보면 항상, "그 때 배울 때 이런건 왜 안가르쳐 줬을까?" 란 아쉬움이 남습니다. 이 고민을. 후배들에게는 그 고민을 물려주고 싶지 않아서 새로운 스타일의 C/C++ 스터디를 시작해 보려 합니다.

좀더 실용적이고, 실질적이며, 생각할 거리를 던지는 그런 C언어 공부를 시작해 봅시다.

C / C++ 관련 질문이 있으시다면 방명록을 이용해 주세요.

PS. 이 블로그의 Post 들이 유익하셨다면, 올블로그 link의 클릭을 부탁드립니다.

'Studies' 카테고리의 다른 글

게시판별 용도  (0) 2008.08.10
[개강공지] Computer Engineering 1st year. Blog just opend and Welcome!  (0) 2008.08.08
Posted by 지그프리드 지그프리드

댓글을 달아주세요:: 네티켓은 기본, 스팸은 사절


BLOG main image
일상, 프로그래밍, IT 그리고 직장생활, Dive, 여행 by 지그프리드

카테고리

Class List (402)
Studies (30)
Exercise & Quizz (10)
Term Project (0)
ECIM list (Help!) (10)
Issues & News (0)
Gossip about IT & Job (22)
Tools (2)
Think about the Justice (23)
Book Review (170)
조엘 온 소프트웨어(번역) (28)
Diary (87)
Vacations (9)
Clash of clans 클래시 오브.. (11)

글 보관함

달력

«   2019/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
Total : 315,601
Today : 3 Yesterday : 22