Welcome to Dynamic C#(2) - Wanna be a polyglot.

C# 2009. 5. 17. 16:25 Posted by 알 수 없는 사용자

- 자넨 왜 그렇게 언어에 집착하는고?

넵, 확실히 저는 언어에 쫌 집착하는 편이긴 합니다. 우리가 말하고 쓰는언어도 꽤나 집착하는 편입니다. 언어를 제대로 배우려고 노력하다보면, 더 재밌는 걸 많이 접할 수 있게 되고 그 언어뿐만 아니라 언어를 쓰는 사람들의 사고방식도 아주 조금씩 이해하게 되기 때문이죠. 뭔가 보고싶은게 있는데 그게 제가 모르는 언어로 되어 있어서 못보는건 조금 슬픈일인거 같습니다. 개인적으로 부족한 실력이지만, 미드&일드를 아주 재밌게 즐기고 있습니다.

프로그래밍 언어도 비슷한 의미에서 집착하게 되는게 아닐까 싶습니다. 프로그래밍 언어에는 그 언어를 만들고 지지하는 사람들의 사고방식도 같이 배울 수 있게 되고, 점점 재밌게 할수 있는게 늘어나기 때문이죠. 최근에 언어에 대해서 아주 부족한 의견이지만 글을 썼던 적이 있습니다. 관심있으신 분은 보시고 따쓰한 피드백 주시면 완전 감사하겠습니다. 

아무튼 그런의미에서 F#에 C#에 Axum까지 건드려보고 있는거지요. 줏대가 없다거나 바람기가 있다거나 뭐 그런건 아닙니다. 그럼 본론으로 들어가서, 지난번엔 동적C#에 대한 이야기를 조금 드렸었습니다. 하지만 정작 알고 싶은건 dynamic키워드란게 생겼고 대충 오리꽥꽥 어쩌구 저쩌구 하는건 알겠는데, 어디다 써먹는거란 말이더냐? 뭐 그런거겠죠. 그래서 쌩초보이지만, 최대한 그런관점에서 접근해보고자 합니다. 그 첫번째가 실제로 프로젝트를 하다가 하나 느낀게 있어서 그걸 적어보고자 합니다. 



- 시나리오
(제가 모르는 해결방법이 있을수도 있습니다. 그럴땐 따쓰한 피드백을!)

LINQ to SQL(이하 L2S)로 프로젝트를 진행중입니다만, 데이터가 추가되거나, 수정되거나 삭제될때 그 값들의 이전/이후 데이터를 포함해서 그 데이터의 고유번호(seq)를 같이 저장하는 뭐 그런 시나리오입니다. 그래서 L2S에서는 아래와 같은 방법을 제공합니다.

 

ChangeSet changeSet = db.GetChangeSet();

foreach (Customer c in changeSet.Inserts)
{
	.......
}

 

하지만, 위와 같은 코드는 한번의 SubmitChanges로 변경이 일어나는 대상 테이블이 하나라면 Generic파라미터로 처리할 수도 있겠지만(ChangeSet에서 리턴되는 객체의 타입이 object입니다), 주문과 상세주문같이 한번에 여러개의 테이블에 변경이 일어난다면, 그닥 친절하지 못한 시나리오가 되겠습니다. 그래서 그때 들었던 생각이 "아 이거 dynamic키워드를 이용해서 오리꽥꽥타이핑(duck typing)을 이용하면, 쫌 쉽게 될거 같은뎅..." 였습니다. 그래서 한번 살짝 구현해봤습니다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace FirstDynamic
{
    class Customer
    {
        public int Seq{get; set;}
        public string Name {get; set;}        
    }

    class Company
    {
        public int Seq{get; set;}
        public string Name{get; set;}
    }

    class Project
    {
        public int Seq{get; set;}
        public string Name{get; set;}
    }

    class NoneSeqThing
    {
        public string Name{get; set;}
    }

    class Logger
    {
        public void WriteLog(dynamic entity)
        {
            try{
                Console.WriteLine(entity.Seq);
            }
            catch(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
            {
                Console.WriteLine("Exception : " + ex.Message);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {            
            Logger logger = new Logger();

            Customer customer = new Customer
            {
                Seq = 1,
                Name = "Boram"
            };

            Company company = new Company
            {
                Seq = 6,
                Name = "NanoSoft"
            };

            Project project = new Project
            {
                Seq = 108,
                Name = ".NET 99.9"
            };

            NoneSeqThing noneSeqThing = new NoneSeqThing
            {
                Name = "None Seq Thing"
            };

            object[] entities = new object[] { customer, company, project, noneSeqThing };

            foreach (object entity in entities)
            {
                logger.WriteLog(entity);
            }
        }
    }
}

 

위에서는 몇가지 객체를 선언해서 DTO를 흉내냈고, Seq가 있는 타입과 없는 타입이 있는 것을 볼 수 있습니다. 그리고 ChangeSet에서 반환되는 객체를 그냥 dynamic으로 Logger에게 넘겨주고 있습니다. 그리고 Seq멤버변수가 있으면 남기고 없으면 안남기는 식으로 다른 처리를 해주고 있습니다. 그리고 결과는 아래와 같습니다.



그렇습니다, 이런식으로 dynamic을 이용한다면 지난 포스트에서 Paul Graham아자씨가 이야기 했던 나이들고 엄한 이모 컴파일러와 좀더 편하게 대화할 수 있는 법이죠. 써놓고 보니깐 포스트가 별거 없네요. 기분 탓이 아니라 제 내공 탓이겠죠. 여담이지만, 제가 해결한 방식은 리플렉션으로 Seq프로퍼티를 검색해서 유/무를 판별하는 방식을 이용했습니다. 확실히 손이 좀더 많이 가는 방법이죠.

이렇게 여러가지 패러다임에 익숙해지고 잘 활용할 수 있게 되면, 점점 더 빠르고 경쾌한 리듬으로 코드를 작성하는 일도 가능하지 않을까 생각해봅니다. 이제 프로그래밍을 하시는 분들도 세계화에 발맞추는 속도에 걸맞게 프로그래밍언어에 대해서도  ployglot이 되어야 하지 않을까 생각합니다. 다만, 제 생각엔 그러한 노력은 프로그래머에게 족쇄를 채우는게 아니라 오히려 더 큰 자유를 주는 일이라고 생각합니다. 그럼, 또 개발하다가 dynamic의 헬프가 필요한 순간이 오면 나누도록 하겠습니다.

여담이지만, polyglot하니깐 중학교때 "핸들 이빠이 돌려"라는 한문장으로 3개국어를 자유자재로 구사하시던 한문선생님이 떠오르는 군요. ㅋ


-참고자료
1. Pro LINQ: Language Integrated Query in C# 2008, Joseph C. Rattz, Jr. , APRESS.