레이블이 닷넷인 게시물을 표시합니다. 모든 게시물 표시
레이블이 닷넷인 게시물을 표시합니다. 모든 게시물 표시

2010년 10월 28일 목요일

윈7폰에서 SQLLite쓰기

모바일에서 자주 사용했었던 SQLLite가 윈7폰에는 빠져 있지요
안드로이드는 내부 DB가 있는데 윈7폰은 빠져서 여기에 불만인 사람들이 많습니다.
MS에서는 자사의 클라우드 서비스를 사용하라고 이야기 합니다만 개발자들이 꼭 시키는대로 따르지는 않죠.

그래서 SQLLite 소스를 C#으로 완전 포팅하여 IsolatedStorage를 사용할수 있게 한게 나왔습니다. (혹 뒷북인가요?;;)
프로젝트에 DLL을 추가하고 약간 잡다한 설정하나 해주면 끝납니다. 단 주의할것은

1) 에뮬레이터 재부팅 하면 DB가 날아갑니다. 에뮬에서는 IsolatedStorage를 리부팅 할때마다 날려버리는듯..
2) IsolatedStorage가 일반 파일 IO보다 매우 느리기 때문에 성능을 기대하긴 어렵습니다.

간단한 DB 트랜잭션이 꼭 필요하다면 사용할만 합니다. 다운로드는 아래에...

WP7 Sqlite

2010년 10월 12일 화요일

어제출시된 따끈한 윈7폰 테스트 (삼성,LG)

출시된 폰들 비됴입니다.

보신분은 패스

 

안보신 분은 함 대충 느껴보세요

손이랑 크기를 비교해보시면 대략 감이 오실것 같습니다.

 

급하신 분들위한 종합버전 ->

 

 

 

 

 

 

 

 

 


 

 

1) 슬쩍 버벅? 대는 옴니아 7폰...

 

 

2) 옵티머스 7

 

3) 포커스 .. 요건 좀 성실히 테스트 해줬네요

 

2010년 9월 10일 금요일

오토마우스 오토키보드 소스

푸 요청으로 올립니다.

옛날에 짠 소스인데... 아래 SendInput  이라는 API 로 마우스/키보드 흉내를 낼수 있습니다.

오토 마우스/ 키보드가 가능하다는 것이지요...

굳이 복잡한 후킹기술 안써도 아래 소스로 충분합니다.

 

 

[code csharp] using System; using System.Runtime.InteropServices; namespace AutoKeyMouseExample { internal class Win32APIs { [DllImport("user32.dll", SetLastError = true)] public static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize); [DllImport("user32.dll")] public static extern IntPtr GetMessageExtraInfo(); [StructLayout(LayoutKind.Sequential)] public struct MOUSEINPUT { public int dx; public int dy; public uint mouseData; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] public struct KEYBDINPUT { public ushort wVk; public ushort wScan; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] public struct HARDWAREINPUT { public uint uMsg; public ushort wParamL; public ushort wParamH; } [StructLayout(LayoutKind.Explicit)] public struct INPUT { [FieldOffset(0)] public int type; [FieldOffset(4)] //* public MOUSEINPUT mi; [FieldOffset(4)] //* public KEYBDINPUT ki; [FieldOffset(4)] //* public HARDWAREINPUT hi; } /***************************** * EVENT CONSTANTS * *****************************/ public const int INPUT_MOUSE = 0; public const int INPUT_KEYBOARD = 1; public const int INPUT_HARDWARE = 2; public const uint KEYEVENTF_EXTENDEDKEY = 0x0001; public const uint KEYEVENTF_KEYUP = 0x0002; public const uint KEYEVENTF_UNICODE = 0x0004; public const uint KEYEVENTF_SCANCODE = 0x0008; public const uint XBUTTON1 = 0x0001; public const uint XBUTTON2 = 0x0002; public const uint MOUSEEVENTF_MOVE = 0x0001; public const uint MOUSEEVENTF_LEFTDOWN = 0x0002; public const uint MOUSEEVENTF_LEFTUP = 0x0004; public const uint MOUSEEVENTF_RIGHTDOWN = 0x0008; public const uint MOUSEEVENTF_RIGHTUP = 0x0010; public const uint MOUSEEVENTF_MIDDLEDOWN = 0x0020; public const uint MOUSEEVENTF_MIDDLEUP = 0x0040; public const uint MOUSEEVENTF_XDOWN = 0x0080; public const uint MOUSEEVENTF_XUP = 0x0100; public const uint MOUSEEVENTF_WHEEL = 0x0800; public const uint MOUSEEVENTF_VIRTUALDESK = 0x4000; public const uint MOUSEEVENTF_ABSOLUTE = 0x8000; /***************************** * VIRTUAL KEYS * *****************************/ public enum VK : ushort { /* * Virtual Keys, Standard Set */ VK_LBUTTON = 0x01, VK_RBUTTON = 0x02, VK_CANCEL = 0x03, VK_MBUTTON = 0x04, /* NOT contiguous with L & RBUTTON */ VK_XBUTTON1 = 0x05, /* NOT contiguous with L & RBUTTON */ VK_XBUTTON2 = 0x06, /* NOT contiguous with L & RBUTTON */ /* * 0x07 : unassigned */ VK_BACK = 0x08, VK_TAB = 0x09, /* * 0x0A - 0x0B : reserved */ VK_CLEAR = 0x0C, VK_RETURN = 0x0D, VK_SHIFT = 0x10, VK_CONTROL = 0x11, VK_MENU = 0x12, VK_PAUSE = 0x13, VK_CAPITAL = 0x14, VK_KANA = 0x15, VK_HANGEUL = 0x15, /* old name - should be here for compatibility */ VK_HANGUL = 0x15, VK_JUNJA = 0x17, VK_FINAL = 0x18, VK_HANJA = 0x19, VK_KANJI = 0x19, VK_ESCAPE = 0x1B, VK_CONVERT = 0x1C, VK_NONCONVERT = 0x1D, VK_ACCEPT = 0x1E, VK_MODECHANGE = 0x1F, VK_SPACE = 0x20, VK_PRIOR = 0x21, VK_NEXT = 0x22, VK_END = 0x23, VK_HOME = 0x24, VK_LEFT = 0x25, VK_UP = 0x26, VK_RIGHT = 0x27, VK_DOWN = 0x28, VK_SELECT = 0x29, VK_PRINT = 0x2A, VK_EXECUTE = 0x2B, VK_SNAPSHOT = 0x2C, VK_INSERT = 0x2D, VK_DELETE = 0x2E, VK_HELP = 0x2F, /* * VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39) * 0x40 : unassigned * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A) */ VK_LWIN = 0x5B, VK_RWIN = 0x5C, VK_APPS = 0x5D, /* * 0x5E : reserved */ VK_SLEEP = 0x5F, VK_NUMPAD0 = 0x60, VK_NUMPAD1 = 0x61, VK_NUMPAD2 = 0x62, VK_NUMPAD3 = 0x63, VK_NUMPAD4 = 0x64, VK_NUMPAD5 = 0x65, VK_NUMPAD6 = 0x66, VK_NUMPAD7 = 0x67, VK_NUMPAD8 = 0x68, VK_NUMPAD9 = 0x69, VK_MULTIPLY = 0x6A, VK_ADD = 0x6B, VK_SEPARATOR = 0x6C, VK_SUBTRACT = 0x6D, VK_DECIMAL = 0x6E, VK_DIVIDE = 0x6F, VK_F1 = 0x70, VK_F2 = 0x71, VK_F3 = 0x72, VK_F4 = 0x73, VK_F5 = 0x74, VK_F6 = 0x75, VK_F7 = 0x76, VK_F8 = 0x77, VK_F9 = 0x78, VK_F10 = 0x79, VK_F11 = 0x7A, VK_F12 = 0x7B, VK_F13 = 0x7C, VK_F14 = 0x7D, VK_F15 = 0x7E, VK_F16 = 0x7F, VK_F17 = 0x80, VK_F18 = 0x81, VK_F19 = 0x82, VK_F20 = 0x83, VK_F21 = 0x84, VK_F22 = 0x85, VK_F23 = 0x86, VK_F24 = 0x87, /* * 0x88 - 0x8F : unassigned */ VK_NUMLOCK = 0x90, VK_SCROLL = 0x91, /* * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys. * Used only as parameters to GetAsyncKeyState() and GetKeyState(). * No other API or message will distinguish left and right keys in this way. */ VK_LSHIFT = 0xA0, VK_RSHIFT = 0xA1, VK_LCONTROL = 0xA2, VK_RCONTROL = 0xA3, VK_LMENU = 0xA4, VK_RMENU = 0xA5, VK_BROWSER_BACK = 0xA6, VK_BROWSER_FORWARD = 0xA7, VK_BROWSER_REFRESH = 0xA8, VK_BROWSER_STOP = 0xA9, VK_BROWSER_SEARCH = 0xAA, VK_BROWSER_FAVORITES = 0xAB, VK_BROWSER_HOME = 0xAC, VK_VOLUME_MUTE = 0xAD, VK_VOLUME_DOWN = 0xAE, VK_VOLUME_UP = 0xAF, VK_MEDIA_NEXT_TRACK = 0xB0, VK_MEDIA_PREV_TRACK = 0xB1, VK_MEDIA_STOP = 0xB2, VK_MEDIA_PLAY_PAUSE = 0xB3, VK_LAUNCH_MAIL = 0xB4, VK_LAUNCH_MEDIA_SELECT = 0xB5, VK_LAUNCH_APP1 = 0xB6, VK_LAUNCH_APP2 = 0xB7, /* * 0xB8 - 0xB9 : reserved */ VK_OEM_1 = 0xBA, // ';:' for US VK_OEM_PLUS = 0xBB, // '+' any country VK_OEM_COMMA = 0xBC, // ',' any country VK_OEM_MINUS = 0xBD, // '-' any country VK_OEM_PERIOD = 0xBE, // '.' any country VK_OEM_2 = 0xBF, // '/?' for US VK_OEM_3 = 0xC0, // '`~' for US /* * 0xC1 - 0xD7 : reserved */ /* * 0xD8 - 0xDA : unassigned */ VK_OEM_4 = 0xDB, // '[{' for US VK_OEM_5 = 0xDC, // '\|' for US VK_OEM_6 = 0xDD, // ']}' for US VK_OEM_7 = 0xDE, // ''"' for US VK_OEM_8 = 0xDF /* * 0xE0 : reserved */ } } } [/code]

2010년 5월 20일 목요일

HTC의 Windows 7 Phone ROM 유출?

HTC에서 유출된 Phone ROM에 windows 7 Phone OS로 보이는 데이터가 담겨 있었답니다. 이걸로 봐서 올 하반기엔 HTC에서 Mondrian 등의 차기 단말로 Windows 7 Phone이 등장할 확률이 높아졌군요. 다른 제조사의 행보가 주목됩니다. (LG에서 해외를 대상으로 Windows 7 Phone을 샘플로 선보였다고 하는데... 자세한건 두고봐야겠죠?)

 

http://www.engadget.com/2010/05/17/htc-mondrian-with-1-3ghz-snapdragon-detailed-in-leaked-windows-p/

 

 

Blend & Windows 7 Phone 동영상 한점.

 

Microsoft Blend로 App을 만드는 방법에 대한 90초 짜리 동영상입니다.

간단해보이는군요... 시간나는대로 바로 해서 포스팅 해보겠습니다.

개인적으로 이제부터 화면전환이용이 가능하다는게 좋군요.

 

Get Microsoft Silverlight

2010년 5월 10일 월요일

Windows 7 Phone Design 관련 동영상 2점


Windows 7 Phone의 디자인에 관한 동영상이 2개 있어요
흥미있는 분들 보시라고 링크~


Get Microsoft Silverlight

아래는 위 동영상의 독어 버전? 인데 좀더 7 Phone의 디자인 테마에 대해서 이야기하고 있는듯....


Get Microsoft Silverlight


2010년 4월 19일 월요일

Photo Slider

지난 시간에 이어서 이번엔 Win7 phone SDK로
PhotoSlider app을 만들어 보았습니다.

WPF 와는 좀 차이가 나서 삽질이 많았습니다. ;;


대충 삼성 옴니아에 들어있는 1 Finger Zoom을 구현해 보았습니다.
손가락 한개로 줌인/아웃을 할수 있습니다. 원래는 아이팟처럼 두개의 손가락으로 테스트 하고 싶었지만
관련 제스처를 이용할수 있는 방법을 아직 발견못했습니다. ...

(있다고 해도 에뮬레이터 개발환경에서는 test하기 힘들겠군요, 아시는분은 알려주시면 감사하겠습니다.)



다른 이미지로 이동기능들을 구현해 봤습니다.


정말 Silverlight 를 통해서 기존 윈도우폰 개발과는 차별화된 간편함을 제공하는군요;;
좀더 많고 다이나믹한 아이디어를 앱으로 개발할수 있게 되어 기대됩니다.
다만, 실버라이트가 WPF에 익숙한 저로서는 아직 좀 헷갈리는군요....

추가로, 제 욕심입니다만...
이번 앱을 통해서 기존처럼 예제만 제공하는것이 아닌 요구사항-설계-구현이
어떻게 같이 진행되는지 이야기 하고자 합니다.
곧 프로세스/예제와 함께 발전하는 Application을 기대해 주세요~


2010년 4월 8일 목요일

Bottom-up/Top-down 설계

 

'신의 한줄'을 위한 생각 - Bottom-up/Top-down

 

소프트웨어 개발자의 세계에 있어서,

설계와 코딩은 서로 떼놓을수 없는 정말 중요한 작업들입니다.

좋은 설계는 코딩을 편하게 하고, 좋은 코딩은 설계가 유연해지도록 돕습니다.

하지만 다들 코딩은 어떻게든 하겠는데, 설계는 어떻게 해야 할지 몰라서 헤매는 경우가 많습니다.

시중에 나온 책들도 코딩을 잘하는 방법(테크닉)을 가르쳐 줄뿐이지, "설계는 이것이다" 라고

딱히 이야기해주지 않습니다. 그나마 전산학과에선 설계를 가르친다고는 하나, 이들 학교에서

배우는 내용도 매우 두리뭉실할 뿐, 현실에서는 거의 적용하기 힘든때가 많습니다.

 

그렇다면 우리는 설계를 어떻게 시작해야 좋을까요?

저뿐만 아니라 많은 개발자들이 여기에 대해서 수없이 고민해 왔습니다.

그리고 각자 자신만의 결론에 도달하게 되죠, 그것이 옳던 아니던 간에.

(사실 맞고 틀린것은 없습니다, 자기가 좋아하는 방법이 최선인 것입니다.)

 

제가 생각하는 설계는 2 가지가 있습니다.

(여기선 이전단계인 요구사항 분석이 끝났다고 칩시다.)

 

하나는 정말 설계다운 Top-Down방식

다른 하나는 부지런한 리팩토링에 따른 Bottom-Up 방식

 

참고로 아래 예시를 설명함에 있어,

저는 구현과 설계를 병행한다는 것을 고려하시기 바랍니다.

 

 

Top-Down방식

 

Top-Down방식은 두리뭉실한 것을 구체적으로 만들어 나가는 것입니다.

이전에 완료된 요구사항중 공통되는 핵심 기능만을 우선적으로 객체로 모델링을 합니다.

여기서는 개발자라면 많이 사용하는 버튼, 콤보박스, 리스트 등등의 UI Control이

어떻게 설계될수 있는가에 대해서 이야기하도록 하겠습니다.

 

우선 "화면에 보여야 한다"라는 요구사항을 만족시키기 위해서 Visual 이라는 객체를 하나 만들었습니다.

이 Visual은 Draw() 라는 메소드가 있어, 스스로 화면에 그려질수 있습니다.

 

 

 

그리고 여기서 "마우스로 조작할수 있어야 한다." 라는 요구사항을 만족시키기 위해서 아래와 같이

Control 이라는 객체를 만들었습니다.

 

마우스로 조작하려면, 화면에 보여야 하기 때문에 이 Control은 Visual의 특성을 가져야 하므로,

상속을 이용하여 다음과 같이 표현합니다.

 

여기서 좀더 구체적인 요구사항 "마우스로 클릭하면 실행되어야 한다." 를 만족시키기 위해서

Button을 만들었습니다.

 

 

Button은 역시 마우스로 조작되어야 한다는 앞의 요구사항을 만족해야 하기 때문에 Control의

특성을 지녀야 하므로, Control을 상속 받습니다.

그런데 Button으로 만족되지 않는 다른 요구사항 : "클릭하면 다시 클릭될 때까지 눌린 상태(체크)를

유지해야 한다." 가 있습니다. 버튼은 클릭하면 뭘 수행하는 기능만 있기 때문에, 이때쯤 새로운

객체를 하나 더 디자인 합니다. 이를 CheckBox 라 하겠습니다. 역시 화면에 보이고, 마우스로

조작되어야 하기 때문에 Control을 상속 받습니다.

 

여기에 또 다른 요구사항 : "스크롤 해서 항목을 선택할수 있어야 한다." 가 있습니다.

이는 Button, CheckBox 모두와 서로 안맞는 요구사항이므로, Button이나 CheckBox를 상속받는

행위를 하면 안됩니다.(서로 맞는지 아닌지 두리뭉실해서 확신이 안서면 문제에 대한 이해나

요구사항 분석이 잘못된것입니다. 좀더 자세히 해놓을 필요가 있습니다.) 보통 초반에 잘 설계해놓고

마구 상속하고 이게 감당이 안되서 overriding 하여 설계를 망치는 경우가 많습니다. 조심해야 합니다.

 

이러한 실수를 막고자 상속은 3단계 이상 하지말것,

다중 상속 금지 등의 "경험적인 Rule"이 생겨난 것입니다.

 

결국, Button과 CheckBox 모두와도 서로 요구사항이 맞지 않지만, Control이 만족하는 요구사항

"화면에 그려지고, 마우스로 조작될수 있다."라는 조건을 맞추기 위해서 ListBox라는 객체를 만들어

Control을 상속받습니다.

 

이렇게 하여 하나의 Tree 모양의 설계가 일단 완료되었습니다.

더 복잡하게 하면 머리아프고 쓰기도 힘드니, 여기서 더 자세히 나가지는 않겠습니다.

 

이 방식의 경우 추상적인 곳에서 구체적인 곳으로 나아가면서 설계가 이루어지기 때문에

Top-Down = Bottom까지 내려가야 실제 사용할수 있는 구체적인 컴포넌트가 나타나게 됩니다.

 

개발자 입장에서는 차근차근 뭔가 두리뭉실한게 명확해진다, 뭔가 이루어진다는 느낌이지만,

빨리 눈에 보이거나 뭔가 나오는게 없어 성격급한 관리자들이 싫어하는? 방법이기도 합니다.

 

 

 

Bottom-up방식

 

이번엔 Bottom-up 방식의 설계 기법을 보여 드리겠습니다.

역시 위와 마찬가지로 UI Framework 구조를 만들어 나가는 과정입니다.

 

일단 Bottom-up에서는 가장 구체적인 요구사항을 모두 만족하는 객체를 먼저 만듧니다.

(일단 닥치고 만듭니다.)

 

- Button의 경우    

  • 화면에보이고,
  • 마우스로 조작 가능하며
  • 클릭할수 있다

    는 요구사항을 모두 구현합니다.

 

- CheckBox의 경우

  • 화면에보이고,
  • 마우스로 조작 가능하며,
  • 클릭하면 다시 클릭될 때까지 눌린 상태(체크)를 유지해야 한다.

    는 요구사항을 모두 구현합니다.

 

- ListBox의 경우

  • 화면에보이고,
  • 마우스로 조작 가능하며,
  • 스크롤 해서 항목을 선택할수 있어야 한다.

    는 요구사항을 모두 구현합니다.

 

여기서 주의할 것은, 각 기능을 구현하는데 객체 내에 위 요구사항을 만족하는 기능들의 응집도가

높으면 안된다는 것입니다. 응집도가 높으면 리팩토링하기가 너무 힘들고, 한다고 해도 제대로

부작용(Side-Effect)없이 동작한다고 보장하기 힘듭니다.

 디미터 룰(실용주의 프로그래머(인사이트) 참고)을 철저하게 지키던가 아니면 내부 구현을 최대한

간단하게 한다던지 각자의 방법으로 잘 정리해 합니다.

 

 

어쨌든 구현이 끝나고 각 객체의 리팩토링이 끝나면, 위 요구사항중에서 공통되는 요구사항

"마우스로 조작 가능하다" 를 뽑아내어 Control이라는 위 3개 요소를 대표할수 있는 좀더

두리뭉실한 이름의 객체로 만든후, 이 요구사항과 관계된 Code중 공통되는 부분을 뽑아

이 Control 안에 넣습니다. 그리고 3개 컴포넌트가 이 Control을 상속받게 합니다.

 

 

역시 마찬가지로 "화면에 보이다" 라는 공통되는 요구사항을 뽑아 Visual이라는 객체로 표현후

3개 객체에서 화면그리는데 공통되는 Code를 뽑아 내어 집어 넣습니다.

그리고 3개 Control이 이 Visual을 상속받게 합니다.

 

 

여기서 C++등의 언어에서는 이렇게 한 객체가 2개의 상위 객체를 상속받게 허용합니다.

이를 "다중상속"이라고 부릅니다. 하지만 앞에서도 이야기 했듯이, 이 다중상속 때문에

설계 및 디버깅 전체가 점점 더 어려워지는 문제가 있어 C#등 최신 언어들에서는 다중상속을

지원하지 않습니다.

 

(다중상속의 폐해에 대해서는 Scott Myers의 Effective C++ 등의 저서를 참고하세요)

 

저는 C#으로 먹고살기 때문에 다중상속이 가능하지 않습니다.

따라서 Visual과 Control이 같은 Level 선상에 놓여야 하는지 고민해야 합니다.

결국, Control도 화면에 보여야 하기 때문에, 좀더 근본적인 요구사항을 만족시키는 Visual을

최상위 객체로 둡니다. Control은 Visual을 상속받게 됩니다.

 

 

어떻습니까? 앞과 마찬가지로, 결국 하나의 Tree 모양이 완성됩니다.

내부의 구현은 Top-Down과 다를수 있지만 외부에서 보았을때엔 동일한 구조입니다.

 

여기서 "부지런한" 이라는 수식어를 붙인 이유는, 이러한 Bottom-up 설계가

계속 중복된 요소를 잡아내고, 이를 추상화 시키며 정리해 나가는 리팩토링 과정과 함께 하기 때문에

Top-Down보다 매우 바쁘게 움직여야 한다는 것입니다. 마치 정원사가 계속 정원을 다듬듯이

그렇게 다듬어 주어야 차츰차츰 좋은 설계가 나타나는 것입니다.

 

하지만, 이렇게 힘이 많이 드는 대신에 Top-Down 방식에서 일어나기 쉬운

"불필요한 추상화/구체화"가 덜하다는 장점이 있습니다.

 

 

 

실전에선 어떻게 하나?

 

 위에서는 예로 설명하고자 두 방법을 분명히 구분지으려 노력했지만,

실전에서는 두 방법이 서로 보완하면서 번갈아 이용됩니다. 서로 장단점을 보완해 줄수 있기 때문이죠.

예를들어, Top-Down으로 만든 구조에서 다음과 같은 새로운 요구사항이 들어왔다고 합시다.

 

"클릭할수 있지만 클릭하면 푹 들어가 다시 클릭될 때까지 나오지 않는다."

 

뭔가 애매합니다. 클릭도 되고, 푹 들어가서 또 누를때까지 나오지 않는다....

위에서 이야기한 Button과 CheckBox의 성질을 모두 가지고 있지만, 어느것 하나의 성질도

가지고 있지 않은 상황입니다. 아래와 같이 교집합적인 성질을 지니고 있는 것처럼 보입니다.

 

그럼 Top-Down적으로 생각해서, Control을 상속밭는, 완전히 새로운 것을 하나 더 만들어야 할까요?

당장은 이게 가장 쉬운 방법처럼 보입니다. 하지만 이런 식으로 자꾸자꾸 새로운 것을 만들면

아래처럼 잔가지가 수십개나 달리는 = 중복되는 코드가 수십개나 되는 지저분한 구조가 되어

같은 기능을 수정할 때마다 여러 클래스에 있는 기능을 다 수정해줘야 하는 문제가 생깁니다.

경험상 제일 귀찮으며, 손이 많이가고, 제일 야근을 심하게 하게 만드는 요소이죠.

 

 

 

여기서, Bottom-up적인 생각이 적용될수 있습니다.

Bottom-up적인 생각이란, 앞에서 말했듯이 공통되는 부분을 집어내어

이를 묶는 좀더 대표적인 객체를 만드는 = 한단계 추상화 시키는 것입니다.

 

여기서 공통되는 부분은

 

1 클릭(Click)

2 토글(Toggle) - 클릭하면 푹 들어가 다시 클릭될 때까지 나오지 않는다.

 

입니다.

 

앞에서 말했듯이 "다중상속"은 안 쓴다고 했습니다.

따라서 공통되는 Toggle 기능(또는 특성)만을 위한 객체를 따로 만들어서 Control과 함께 상속받게

할수는 없습니다. 하지만 이 공통되는 특성을 두 객체에 강조하고 싶습니다.

이럴때 쓰는게 Interface 입니다. 공통되는 성질을 이용하기 위한 Interface : IToggle을 만들어

CheckBox와 새로 만들 객체 (여기선 요구사항대로 위 1, 2 성질을 모두 표현하는 ToogleButton

이라고 이름 짓습니다.)가 상속받게 합니다. 그리고 IToggle이 요구하는 구현사항을 모두 구현합니다.

 

 만일 ToggleButton의 IToggle구현과 CheckBox의 IToggle 구현이 동일하고, 여기서도 중복을

없애고 싶다면 IToggle을 구현하는 별도의 상위 객체 (예를들어, ToggledControl 등)을 CheckBox와

ToggleButton의 상위 클래스로 두면 되겠지만, 이럴경우 Button의 Click 특성까지 별도 상위 클래스를

두면 ToggledButton은 다중상속이 되어 C# 에선 구현이 안됩니다. 결국 Click과 Toggle 둘중 더

중요한 특성을 상위 클래스로 뽑고, 다른것은 인터페이스로 뽑아 유형만 구현하도록 합니다.

이 예시에서는 Click이 Toggle보다 좀더 중요하며, 근본적인 특성이라고 보고 설계하였습니다.

 

 

따라서 ToggleButton은 Button의 공통 특성인 Click 기능을 가진 ButtonBase 라는

상위 추상 클래스를 하나 만들어, 이를 상속받게 합니다.

ButtonBase가 추상 클래스인 이유는 클래스 자체로는 인스턴스화할 필요가 없이

Click 에 대한 공통 구현만 제공하며,

하위 클래스에서 재정의 하여 사용하기 용이하도록 하기 위함입니다.

(ButtonBase가 추상 클래스이기 때문에, 이 위의 상위 클래스 모두 추상 클래스여야 합니다.)

 

 

이제 Click의 특성을 가진 ButtonBase를 Button 과 ToggleButton이 모두 상속받음으로서

아래와 같이 Tree 형태를 유지하는 깔끔한? 전체적인 구조가 완성되었습니다.

(그리고 이것이 바로 WPF의 UI Control Framework 설계 모습이기도 합니다.)

 

이렇게 Top-Down적인 설계가 한계에 다다랐을때,

아래에서 Bottom-up하는 설계/생각을 도입하여

좀더 Elegant 하게 설계의 문제를 해결할수 있습니다.

 

 

 

결론

 

 

하지만 앞에서 살펴본 설계에는 한가지 꼭 필요한 요구사항이 있습니다.

바로 "전체를 보면서 설계하라" 라는 의미입니다.

전체 클래스들의 배치와 구조 그뿐만 아니라 각 클래스의 중복점을 알지 못하면

객체지향의 요소들의 존재이유와 특징을 음미하지 못하는,

제대로 안된 설계만이 나올 뿐이고, 개발자는 더욱 고생하게 됩니다.

 

그래서 전체를 보는데 도움이 되는 팁을 몇개 정리했습니다:

 

객체지향 설계의 원칙 = 되도록 기능의 책임을 잘게 나눠라 잘라라

전체 설계 구조의 형태 = Tree 모양을 유지하라

끊임없는 문서화와 리팩토링 = 가지치기를 많이 할수록 정원이 좋아진다.

 

 

 

2010년 4월 2일 금요일

Windows Phone 7 - Hello PHOO~


SDK 깔면 같이 깔리는 VS 2010 Expression 버전으로 맛보기 개발이 가능합니다.


공개된 윈7 폰 SDK로 간단한 어플을 만들어 봤습니다.
이름은 Hello PHOO~ 입니다.

Portrait

Landscape


주소창에 주소를 입력하면 그 주소로 쓩~
웹페이지를 보여줍니다.
그냥 누르면 이 블로그를 보여주구요~ ㅋㅋ

XAML. WPF에 익숙한 저로서는
정말 개발이 편해진걸 몸으로 체험할수 있었습니다.
VS 2010도 처음 써봤는데, WPF로 만들었다고 보기 어려울 정도로
사용성이나 성능이 좋구요 ^^

이것말고 다른 프로젝트도 있던데...
기대됩니다.

참고로 아래는 기본 QWERTY 키보드..
시연때 본 키보드는 약간 디자인이 달랐던것 같았는데...흠


2010년 4월 1일 목요일

Windows Phone 7 Information


안녕하세요, 불곰입니다.


윈도폰 7 관련하여 개발을 해보고자 여기저기 자료를 찾아서 몇개 모아봤습니다...

그리고 들리는 이야기로 LG에서 지난달 HW 데모를 내놨다는군요.

(삼성은 안드로이드 올인인데... 과연 Win7 Phone이 나올까요?)

MIX10

MIX10에 나온 윈도폰 관련 내용...

폰에 대포를 연결해서 가속도 센서로 각을 조절해 쏘는군요

(학교에서 공작수업으로 했던 포트리스가 생각납니다. ^^)

http://blogs.msdn.com/eva/archive/2010/03/17/mix10-7-ie9.aspx


이런거 보면  MS가 "재미"를 자꾸 강조하는것 같습니다.

삼성도 좀 "재미"를 강조했음 좋겠습니다.

(당장 "돈" 되는것 이외엔 별로 관심이 없으니...안타까울 따름입니다.)



윈도우폰 7 시리즈 무료 개발툴 다운로드


이 링크에서는 윈도 마켓플레이스 등록이 가능하고

http://developer.windowsphone.com 

이 링크에서는 툴을 직접 다운로드 가능합니다.
http://developer.windowsphone.com/windows-phone-7-series/


 

위트스튜디오


지인들이 모여 만든 닷넷 전문 커뮤니티 - 위트

http://blog.witstudio.net/category/Developer/Windows%20Phone


페졸드 아저씨 책

 

CodeSamples_DRAFTPreview_ProgrammingWindowsPhone7Series.zip

ProgWinPhonePreview.pdf

 

이 아저씨는 정말 대단한것 같습니다.


책 빨리 내는것도 그렇고

쓰면 읽는사람 지치고 지루할 정도로 자세히,

그리고 두껍게! 쓰는것도 그렇고...

 

아마 MS에서 페졸드 아저씨 명성을 이용하려고 하는것도 있겠죠.

 

 

이 글은 스프링노트에서 작성되었습니다.

자동화를 멈출수 없는 이유



자동화 :
반복되는 일을 사람대신 기계가 하도록 만드는 일.

 
 이전에 애자일 컨설팅의 김창준씨가 반복의 중요성에 대해서 쓴 글을 읽은적이 있습니다.
정확한 내용은 기억나지 않지만, 우리 일상의 대부분의 일이 새로운것 보다는 어제, 그저께
또는 한달, 일년전에 하던 일의 반복이라고 합니다. (사실 그렇기도 합니다.)
이 반복들은 매우 일상적이고 하찮아 보이지만 계속 반복되기 때문에
이것들이 쌓여 큰 일을 만들어 나갑니다.

그래서 김창준씨는 "이 하찮은 반복"이 매우 중요하고 큰 힘을 가지고 있다고 이야기 했던것 같습니다.

 학교를 졸업하고 사회에 나와 제가 제일 많이 느꼈던 것은 바로 이 "반복" 이었습니다.
아무리 새로운 일을 한다고 해도, 하던일이 엎어져 버린대도,
저는 매일 반복해야 하는 기본적인 일들을 갑자기 뒤엎은적이 없었던것 같습니다.
그리고 그런 반복되는 일들 때문에 지금까지 큰 탈없이 일들이 진행된것 같습니다.
<- 이런 느낌을 가장 많이 받는때가 바로 며칠간의 업무를 비웠을때라는거 혹시 공감하시는지? ^^

 또 다른 김창준씨의 글에보면,
유능한 개발자로 성장하는 비결중 하나는,
 자신이 하는 일을 효율적으로 만들어 나가는 것이라고 했던것 같습니다. 불필요한 반복을 줄이고,
그만큼 남는 시간에 좀더 창의적인 일을 하는 것이지요.
하지만 이것보다 좀더 중요한 것은 그러한 반복을 줄이는 일
(또는 반복을 사람이 아닌 기계에게 시키는 일)을 진행하는 중에 많은것을 깨닭고 배울수 있다는 것입니다.

이러한 일을 저는 "자동화", 자동화를 통한 깨달음이라고 부르고 싶습니다.

제 경험을 통해 예를들어볼까요?

저의 업무는 수십개 언어로된 수만개의 문장을 관리하는 일입니다.
일명, 다국어 관리라고 (Globalization) 하죠.
영어로 한국어로 된 문장이 30개 언어로 번역되어 오면
이를 지금 있는 문장들에 업데이트 하고
필요없는 것들을 제거하고
종종 고유명사가 바뀌면 일괄적으로 바꿔주는등의 일을 하고 있습니다.
(물론 이게 주 업무는 아닙니다.)

제가 처음 왔을때엔,
이러한 30개 언어 문자열을 관리하고 업데이트 하고 변경하는 일을 일일히 손으로 해 왔습니다.
그러다보니, 회사명 하나 바뀌어도 문장 하나 바뀌어도 일일히 확인하면서 바꿔줘야만 했습니다.
문자 때문에 하루종일 반복작업을 해야 하는게 많았죠.
그러다보니, 업무가 항상 중요한 일이 없는 신입에게만 주어져 왔습니다.

어느날 수백개가 넘는 문장을 바꿔야 하는 업무가 주어지자
더이상 안되겠다고 생각이 들었습니다.
30개 바꾸는 것도 지루하고 힘든데, 계속 문자만 바꾸는 일을 반복하다간
일할맛이 안날것 같았습니다.

게다가 손으로 일일히 바꾸다보니, 제대로 못바꾸는 것도 수두룩 했고
잘못 바꿔서 다시 롤백해야 하는 일도 잦았습니다. (human error)

그래서 그때부터 버튼 하나만, 명령어 한개만 치면 컴퓨터가 알아서 바꿔주는
프로그램을 만들어야 겠다고 생각했습니다.
(사실 엑셀의 매크로를 써서 해결할수도 있었지만 익숙하지도 않았고, 수작업이 다수 필요해서 패스)
그리고 하루를 투자해서 프로그램을 만들고, 이틀이상 걸리던 일을 단 3초만에 끝낼수 있었습니다.

엄청나게 시간을 절약한 셈이죠.

자동화의 첫 목표는 반복업무를 기계에게 시킴으로서 시간을 절약하는데 있습니다.


하지만 "시간을 줄이다" 보다 더 중요한 것은
그 프로그램을 만들면서, .NET  프레임워크의 리소스 관리와 다국어 등의 정책에 대해서 좀더
잘 이해하고 응용할수 있게 되었다는 것입니다. 그리고 그 기간동안 익힌 정규표현식 덕에
확실히 수만개의 문장을 관리하는 실력을 쌓을수 있었습니다. 그리고 최근엔 닷넷의 핵심기능이
되어버린 LINQ로 프로그램을 개선하는 작업을 통해서 LINQ에 대한 확고한 실전지식을 쌓고 있습니다.
(LINQ 의 간결함, 확장성, 그리고 성능에 감탄하면서 말입니다.)

그리고 제가 개인적으로 개발하고 있는
오픈소스 종합 리소스 관리프로그램 Resxus도 좀더 발전시킬수 있고 말입니다.

이러한 "작은 개선을 위한 아이디어와 실천"에서 시작된 "자동화"가
저에게 단순히 업무 퍼포먼스만 향상해 주는것이 아니라,
새로운 것을 배우고 응용하고 더 발전시키는 기회를 줌으로서
저에게 더 실력있는 개발자로 성장하는 기회를 주고 있다는 사실이...
그리고 그 발전이 누가 시키는 것이 아닌,
제 스스로의 의지와 재미를 통해 이뤄지고 있다는 것이 즐겁습니다.

아무리 업무가 바쁘고 힘들어도,
자동화 같은 이러한 개선과 노력 을 통해서 뭔가 나아지는 것을 볼수 있기 때문에
그 과정을 통해서 개발자로서의 보람과 실력을 쌓을수 있기 때문에
저는 자동화를 멈추지 말고 진행해야 한다고 생각하고 있고 그렇게 할 것입니다.


최근 회사에서 강조하는 "창조경영,창의적 기업문화"가 꼭 신규 사업 아이디어만 짜내라고 독촉하는
그런 것이 아니라 현장의 이런 작은 개선들을 찾아 독려하고 인정하고 발전시킬수 있도록
문화와 환경을 만드는 것이어야 하는게 아닌가 생각합니다.


비록 개발자가 아니더라도,
반복되는 야근과 비효율적인 업무에 지쳐 있다면
그냥 체념하고 있기보다
좀더 즐거운 삶을 위해서 생각을 바꾸고
개선해보려 노력한다면
그리고 이를 통해서 좀더 창의적이고
자유로운 시간을 늘릴수 있다면
세상이 그를 통해서 약간이나마
좀더 즐겁지 않을까 생각합니다.



- 만우절 전날밤에 떠오른, 불곰의 생각이었습니다.