Altruistic Programmer's Blog (KR)

이타주의 프로그래머의 블로그

Archive for July, 2009

이벤트핸들러에서 예외 던지기

with 2 comments

[옛날 블로그 글입니다. 2009.07.25]

콜백함수나 이벤트핸들러에서 무언가 문제가 생겨서 예외를 던지고 싶습니다. 어떻게 해야 할까요?

그냥 예외를 던지면 콜백함수나 이벤트핸들러를 호출해 준 라이브러리로 예외가 날라가는데, 그 라이브러리는 예외를 처리할 수가 없습니다. 왜냐면 그 라이브러리는 누가 호출되는지 모르고 그냥 등록된 함수만 호출한거지요. 그래서 그 예외를 던진 녀석이 누군지도 모르고, 또 몰라야만 하고, 예외가 어떤 타입이며, 무슨 의미인지 알 수가 없습니다.

이런 고민에 자료를 찾아보니 같은 고민을 하신 분이 계시네요.
해결책을 던져주지는 않지만 훌륭한 통찰을 제공해주고 있습니다.
http://se.informatik.uni-oldenburg.de:30000/346/1/callback.pdf

우선 이 문서를 읽고 내린 결론부터 얘기하면

  • 콜백함수나 이벤트핸들러에서는 예외를 내지 않는다 -_-;;
  • 라이브러리가 아닌, 그 예외를 처리할 수 있는 누군가에게 함수호출등으로 예외를 알린다.

문서에서 말하는 훌륭한 통찰이란, 예외가 어디로 던져져야 하는지에 대한 규칙입니다.

  • 예외의 발생으로 (안좋은) 영향을 받는 곳 (“나쁜 뉴스를 숨기지 말아라”)
  • 예외로 인한 나쁜 결과를 벌충할 수 있는 곳 (“네 문제를 도와줄 수 없는 곳에 가져가지 마라”)
  • 재발생을 막기위해 예외의 원인을 제거할 수 있는 곳 (“증상이 아니라 병을 고쳐라”)

관련해서 좋은 아이디어나, 자료 있으시면 알려주세요~

Written by muscly

July 25th, 2009 at 3:20 pm

Visual Studio에서 gvim 띄우는 스크립트

with 3 comments

[옛날 블로그 글입니다. 2009.07.19]

비주얼 스튜디오용 매크로입니다. 기능은

  • 현재 편집중인 파일을 gvim에서 띄워준다.
  • 현재 편집중인 파일과 짝 파일( .h 혹은 .cpp)을 vs(Vertical Split)로 gvim에서 띄워준다.
  • 현재 편집중인 파일의 짝 파일을 비주얼 스튜디오에서 열어준다.

요새 비주일 스튜디오를 여러 개 띄울일이 많아서 봤더니 Visual AssistReshaper같은 플러그인들이 메모리를 엄청 먹고 있었습니다. 이 참에 정리하자는 생각으로 플러그인을 모두 지워버렸더니, 비주얼 스튜디오가 정말 가볍네요. 5개씩 띄워도 무리가 없습니다.

하지만 역시나 Visual Assist가 없어서 제일 아쉬운 것은 코드 하이라이팅과 h/cpp 전환하기 기능. 코드 하이라이팅은 포기, h/cpp 전환 기능은 아래 매크로로 대체했습니다.

그리고 vim도 가끔 써주면 즐거워집니다. vim에서 편집하고나서 다시 비주얼 스튜디오에 반영해 주는 기능은 없습니다. -_-;; 비주얼 스튜디오가 알아서 바뀐 파일 로딩해주니 크게 문제는 없구요.

아래 함수 중에서 Public으로 된 녀석들에 단축키를 설정해서 쓰시면 좋습니다.

  • EditActiveDocumentWithGVIM
  • EditCoupleFilesWithGVIM
  • OpenMyCoupleFile

아, 안에 보시면 gvim 경로같은 거 하드코딩 되어 있으니 잘 고쳐서 쓰세요. 음. 그리고 설치하는 것은 비주얼 스튜디오에서 매크로 탐색기 여시고, 기본 모듈하나 더블클릭하시면 매크로 편집기(IDE)가 뜨는데요, 거기에 붙여 넣으시면 될 겁니다. -_-;; 뭐 어떻게든 될거에요 ㅎㅎ

소스코드

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics

Public Module muscly
    Private Function FindFileItem(ByVal fileName As String, ByVal collection As ProjectItems) As ProjectItem
        For Each item As ProjectItem In collection
            If item.ProjectItems.Count > 0 Then
                Dim projItem = FindFileItem(fileName, item.ProjectItems)
                If Not projItem Is Nothing Then
                    Return projItem
                End If
            ElseIf item.Name = fileName Then
                Return item
            End If
        Next

        Return Nothing
    End Function
    Private Function GetCoupleFileName(ByVal fileName As String) As String
        'If cpp
        If fileName.ToLower.EndsWith(“cpp”) Or fileName.ToLower.EndsWith(“inl”) Then
            Return fileName.Substring(0, fileName.Length – 3) + “h”
        ElseIf fileName.ToLower.EndsWith(“h”) Then
            ' Try with cpp
            Dim firstTarget = fileName.Substring(0, fileName.Length – 1) + “cpp”
            If Not FindFileItem(firstTarget, DTE.ActiveDocument.ProjectItem.ContainingProject.ProjectItems) Is Nothing Then
                Return firstTarget
            Else
                ' return inl
                Return fileName.Substring(0, fileName.Length – 1) + “inl”
            End If
        End If
    End Function
    Private Function GetFullPathFromFileName(ByVal fileName As String) As String
        Dim projItem As ProjectItem = FindFileItem(fileName, DTE.ActiveDocument.ProjectItem.ContainingProject.ProjectItems)
        Dim a = projItem.Properties.Item(“FullPath”)
        Return projItem.Properties.Item(“FullPath”).Value
    End Function
    Public Sub OpenMyCoupleFile()
        On Error Resume Next

        'Get File Name
        Dim Name As String = DTE.ActiveDocument().Name

        Dim coupleFileName = GetCoupleFileName(Name)
        DTE.ExecuteCommand(“File.OpenFile”, coupleFileName)
    End Sub

    Public Sub EditCoupleFilesWithGVIM()
        Dim curFilePath = DTE.ActiveDocument.FullName

        Dim coupleFileName = GetCoupleFileName(DTE.ActiveDocument().Name)
        Dim coupleFilePath = GetFullPathFromFileName(coupleFileName)

        Dim windowSizeCommand = “-c “”set columns=180″” -c “”set lines=60″”"
        Dim splitCommand = “-c “”vs ” + coupleFilePath + “”"”

        Dim proc = New System.Diagnostics.Process
        proc.StartInfo.FileName = “c:\\Program Files\\Vim\\vim71\\gvim.exe”
        proc.StartInfo.Arguments = curFilePath + ” ” + windowSizeCommand + ” ” + splitCommand
        proc.Start()

    End Sub
    Public Sub EditActiveDocumentWithGVIM()
        'Get File Name
        Dim fullName As String = DTE.ActiveDocument().FullName

        Dim proc = New System.Diagnostics.Process
        proc.StartInfo.FileName = “c:\\Program Files\\Vim\\vim71\\gvim.exe”
        proc.StartInfo.Arguments = fullName
        proc.Start()
    End Sub

End Module

광고 – blog.altprog.com

도메인 또 바꿨습니다. -_-;;
muscly.net 은 계약 기간 끝나면 서비스 종료됩니다~

Written by muscly

July 19th, 2009 at 3:15 pm

Visual Studio Guideline 표시

without comments

[옛날 블로그 글입니다. 2009.06.18]

C++ 코딩하다보면 인자가 많아서 줄을 넘어가버리는 경우가 있지요. 적당히 엔터를 집어넣어서 줄을 맞춰주다가 예전에 Visual Studio에서 컬럼에 가이드라인을 표시했던 기억이 나서 좀 찾아봤습니다.
http://blogs.msdn.com/saraford/archive/2004/11/15/257953.aspx

찾아보니 설정창은 따로 없지만 레지스트리를 수정해서 가이드라인을 표시할 수가 있네요. 줄의 색상과 컬럼 위치를 여러개 설정할 수 있는 것 같습니다. 위 링크에 가면  VS 2005 기준으로 설명하고 있구요, 댓글을 보니 VS 2003 도 된다네요. ( 심지어는 MSSQL의 SQL Manager도 된다는 -_-;; )

가이드라인이 있으니 일정한 기준으로 소스코드를 정리할 수 있어서 좋네요~

Written by muscly

July 18th, 2009 at 2:24 pm

블로그 OS 재설치

with 2 comments

[옛날 블로그 글입니다. 2009.06.07]

블로그 계약기간 다되서 재갱신 하면서 CentOS 5.3으로 바꿔서 설치해봤습니다. Redhat Enterprise 기반이라서 안정성이 있다고 하더라구요. 그게 기본 패키지들이 좀 옛날 것인 면도 있는 것 같네요.

RPM 삽질

첨에는 Fedora8이라서 Fedora10으로 업그레이드해보자고 시작했다가, RPM Hell을 겪게 되었습니다. 몰랐었는데 RPM은 같은 패키지의 여러 버전을 설치할 수가 없더군요. 그래서 디펜던시 트리의 모든 패키지를 한 번에 업데이트 하지 않으면 안되는 문제가 있었습니다. 하루 종일 삽질을 하다가 결국은 OS 재설치로 -_-

Ruby와 Rails 설치

ruby와 rails를 설치하는데도 한참 헤맸습니다. 헤매면서 배운점은 잠시 후로 미루고 결국 선택한 방법을 정리하면,

  • ruby는 1.8대의 안정버전으로 소스코드를 가져다가 빌드한다 (1.9는 아직 실험적인)
  • 주의: 빌드는 단순히 configure, make, make install 외에 해줄 것이 있으니 아래 링크를 참조
  • http://www.catapult-creative.com/2009/02/04/installing-rails-on-centos-5/
  • rubygems는 그냥 최신(1.3.3)으로 소스코드를 가져다가 빌드한다.
  • rails 등의 rubygem들은 gem install로 설치
  • 주의: 예전에 만든 rails 어플을 돌리려면 맞는 버젼을 설치하는 것이 편리
  • (gem install rails -v 2.1.1 과 같이)

가능한 yum을 사용해서 빌드된 패키지만으로 해결하고 싶었는데요, 기본 레포지토리에는 ruby밖에 패키지가 없었구요. RubyWorks는 rubygems와 주요 rubygem들을 패키지로 제공하고 있는데요, 버전 의존성등이 안맞는 문제등이 있었습니다.

또 ruby 1.9 소스를 받아서 해봤더니, 제 어플리케이션이 쓰는 rubygem 중에 아직 1.9를 지원하지 않는 것이 있어서 낭패. 그래서 yum으로 준비된 ruby 패키지를 설치하고, rubygems는 소스코드를 받아서 설치했더니, rubygems가 ruby가 설치된 곳에 설치되는 바람에 기분이 안좋더라구요.

다시 말해서, 소스 받아서 설치한 녀석들은 /usr/local 안쪽에 있어야 yum으로 설치한 녀석들이랑 헷갈리지 않고 관리하기 좋은데요, 소스를 받아서 설치한 rubygems가 /bin, /lib, /lib64 등에 들어가 버려서 참 찝찝하더라구요. 따로 uninstall 지원도 없어서 수작업으로 싹 지우고, 위에 설명한 방법으로 완료했습니다~

Rails 어플리케이션 배포

Rails 어플리케이션을 배포하는 방법이 이렇게 많은 줄은 몰랐습니다. 저는 mongrel_cluster로 rails 어플리케이션을 여러개 돌리고, apache에서 로드밸런서를 써서 연결하는 식으로 돌리고 있었는데요, 이번에 사용해본 Passenger라는 녀석은 설정이 완전 간단하네요.

apache 설정에서 DocumentRoot를 rails 어플리케이션의 public 디렉토리로 맞춰주기만 하면, Passenger가 알아서 rails 어플리케이션인지 알아채고 돌려주는 식입니다. 그냥  php 설정하듯이 간단합니다.

아, 제가 좀 헤맨 부분이 있는데요, Passenger의 apache 모듈을 설치하면 LoadModule, PassengerRoot, PassengerRuby를 apache 설정에 넣으라고 나오는데요, 저는 이 설정을 <VirtualHost *:80> 안쪽에서 넣어줬다가 무척 헤맸습니다. <VirtualHost *:80> 설정 바깥쪽에 넣어주세요.

마무리

리눅스를 막 배웠더니 기초가 부족해서 많이 해맸는데요, 여러 문제 상황에 봉착하면서 해결책을 검색하고, 조금씩 해결하면서, 배워나가는 과정이 무척 재밌었습니다. 아마도 개발자들이 보통 하는 일들과 비슷해서 그런게 아닌가하는 생각이 듭니다. 그리고, 서버가 깔끔하게 정리된 상태이고, 내 제어 범위 안에 들어와 있다는 느낌도 참 기분 좋은 것이네요.

Written by muscly

July 7th, 2009 at 2:19 pm

Protocol Buffer

with 6 comments

[옛날 블로그 글입니다. 2009.07.02]
C++로 네트웍 프로그램을 만드려면 패킷을 정의하고 읽고 쓰는 유틸리티가 필요하지요. 그냥 구조체로 하려고 하면 문자열 같은 것 처리하기가 너무 힘들더라구요. 회사에도 그런 라이브러리가 하나 있기는 한데, 아쉬운 부분이 있어서 좀 찾아봤더니 구글에서 프로토콜 버퍼라는 녀석을 만들어 뒀더라구요. 패킷의 페이로드를 .proto 파일에 정의하고 protoc.exe로 빌드하면  패킷을 읽고 쓰기 쉽도록 코드를 생성해줍니다. c++, java, python을 지원하구요, 네트웍 패킷에 한정된 건 아니고 파일 입출력에도 사용할 수 있는 범용적인 프로젝트입니다. 그래서, 자동으로 패킷 아이디를 생성해준다거나 하는 기능은 없습니다. 아래 링크 보시면 심플하게 설명 잘 해놨습니다. http://code.google.com/p/protobuf/ 프로토콜 버퍼에서 제일 맘에 드는 부분은 패킷을 입출력하는 스트림을 직접 만들어서 넣을 수 있다는 점인데요. 기본적으로 배열, iostream, 파일 등을 기반으로 하는 스트림도 구현해 놓아서, 그냥 이것들을 사용해도 됩니다. 스트림 자체가 zero-copy 컨셉이라 패킷 입출력시에 메모리 복사가 적은 장점이 있구요, 혹시나 어플리케이션에서 자체적으로 사용하는 스트림 클래스가 있다면 어댑터를 만들어 주는 것만으로 프로토콜 버퍼와 함께 사용할 수 있으니 불필요한 메모리 복사를 줄일 수가 있습니다.

마무리

프로토콜 버퍼는 기능도 좋지만 오픈 소스라서 좋네요. 소스 코드를 고치고 할 일은 없겠지만, 오픈 소스라서 누구나 맘 편하게 가져다 쓸 수 있고, 또 그래서 부족한 부분을 채워 줄 파생 프로젝트들이 생겨나니까 좋습니다. 그리고 오픈 소스라서 생명력이 길어지는 점도 있는 것 같구요. 여러 모로 좋네요, 오픈 소스는.

스트림 클래스 분석

여기서부터는 더 깊숙한 얘기라 관심있는 분만 보시는 게 좋겠네요. 이번 프로젝트에 프로토콜 버퍼를 써볼까 하는 생각에 스트림 클래스의 구조를 공부해봤습니다. 스트림은 패턴의 예제로서 많이 나오잖아요, 그런 예제같이 모범적인 구조를 가지고 있습니다. 우선 ZeroCopyInputStream과 ZeroCopyOutputStream이 입출력 스트림의 인터페이스 클래스입니다. 이를 구현하는 클래스가 여럿 있는데요, 배열, 파일, iostream 등을 이용한 구현등이 있습니다.  아래가 그 클래스 다이어그램입니다.

입력스트림 계층 구조

출력스트림 계층 구조

그 다음에 CodedInputStream, CodecOutputStream은 정수나 문자열, 로우 버퍼를 스트림에 넣고 쓰는 스트림 클래스입니다. 데이타를 효율적으로 읽고 쓰기위한 엔코딩 방식을 담당하는 녀석이지요. 내부적으로 ZeroCopyInputStream, ZeroCopyOutputStream을 사용합니다.

Written by muscly

July 2nd, 2009 at 3:10 pm