2016년 11월 24일 목요일

struct vs class in C#

https://msdn.microsoft.com/ko-kr/library/ms173109.aspx

struct

: https://msdn.microsoft.com/ko-kr/library/0taef578.aspx

- argument가 없는 default constructor, destructor 생성 불가
 : argument가 있는 constructor는 생성 가능
- struct는 value type이므로 복사 시 동일한 데이터의 별도 복사본시 생성됨.
 : new 연산자를 사용하지 않고 인스턴스화 할 수 있음.
- 상속 지원하지 않으나 인터페이스를 구현할 수 있음.


 public struct CoOrds
    {
        public int x, y;

        public CoOrds(int p1, int p2)
        {
            x = p1;
            y = p2;
        }
    }

    // Declare and initialize struct objects.
    class TestCoOrds
    {
        static void Main()
        {
            // Initialize:   
            CoOrds coords1 = new CoOrds();
            CoOrds coords2 = new CoOrds(10, 10);

            // Display results:
            Console.Write("CoOrds 1: ");
            Console.WriteLine("x = {0}, y = {1}", coords1.x, coords1.y);

            Console.Write("CoOrds 2: ");
            Console.WriteLine("x = {0}, y = {1}", coords2.x, coords2.y);

            // Keep the console window open in debug mode.
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
    /* Output:
        CoOrds 1: x = 0, y = 0
        CoOrds 2: x = 10, y = 10
    */
    // Declare a struct object without "new."
    class TestCoOrdsNoNew
    {
        static void Main()
        {
            // Declare an object:
            CoOrds coords1;

            // Initialize:
            coords1.x = 10;
            coords1.y = 20;

            // Display results:
            Console.Write("CoOrds 1: ");
            Console.WriteLine("x = {0}, y = {1}", coords1.x, coords1.y);

            // Keep the console window open in debug mode.
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
    // Output: CoOrds 1: x = 10, y = 20

class

: https://msdn.microsoft.com/ko-kr/library/x9afc042.aspx

- 클래스는 reference type, 복사본은 원 변수의 개체를 참조함.
- 상속 제한을 위해서는 sealed 사용.
- 파생 클래스는 기본 클래스의 virtual, abstract 선언 멤버함수를 재정의 가능
- 파생 멤버는 override를 명시적으로 사용
- 같은 이름이지만 상속 관계가 아닐 경우 new 사용

    public class Person
    {
        // Field
        public string name;

        // Constructor that takes no arguments.
        public Person()
        {
            name = "unknown";
        }

        // Constructor that takes one argument.
        public Person(string nm)
        {
            name = nm;
        }

        // Method
        public void SetName(string newName)
        {
            name = newName;
        }
    }
    class TestPerson
    {
        static void Main()
        {
            // Call the constructor that has no parameters.
            Person person1 = new Person();
            Console.WriteLine(person1.name);

            person1.SetName("John Smith");
            Console.WriteLine(person1.name);

            // Call the constructor that has one parameter.
            Person person2 = new Person("Sarah Jones");
            Console.WriteLine(person2.name);

            // Keep the console window open in debug mode.
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
    // Output:
    // unknown
    // John Smith
    // Sarah Jones



2016년 11월 23일 수요일

object vs var vs dynamic in C#

Object

: https://msdn.microsoft.com/ko-kr/library/9kkx3h3c.aspx
object 형식의 변수에는 모든 형식의 값을 할당할 수 있음.

- boxing : 값 형식의 변수를 object 형식으로 변환하는 경우

            int i = 123;
            // The following line boxes i.
            object o = i;  
- unboxing : object 형식의 변수를 값 형식으로 변환하는 경우

            o = 123;
            i = (int)o;  // unboxing

class ObjectTest
{
   public int i = 10;
}

class MainClass2
{
   static void Main()
   {
      object a;
      a = 1;   // an example of boxing
      Console.WriteLine(a);
      Console.WriteLine(a.GetType());
      Console.WriteLine(a.ToString());

      a = new ObjectTest();
      ObjectTest classRef;
      classRef = (ObjectTest)a;
      Console.WriteLine(classRef.i);
   }
}
/* Output
    1
    System.Int32
    1
 * 10
*/

var

: https://msdn.microsoft.com/ko-kr/library/bb383973.aspx


* 메서드 범위 내에서 선언된 변수로서 암시적 형식인 var를 가질 수 있음
* 컴파일 시점에 컴파일러에서 형식을 결정함
* 선언과 동시에 초기화 되어야 하며 이후 type 변경 불가

아래는 기능면에서는 동일함.
var i = 10; // implicitly typed  
int i = 10; //explicitly typed  

주로 다음 예시 처럼 사용할 것 같음.

                  // Example #1: var is optional because
            // the select clause specifies a string
            string[] words = { "apple", "strawberry", "grape", "peach", "banana" };
            var wordQuery = from word in words
                            where word[0] == 'g'
                            select word;

            // Because each element in the sequence is a string, 
            // not an anonymous type, var is optional here also.
            foreach (string s in wordQuery)
            {
                Console.WriteLine(s);
            }

            // Example #2: var is required because
            // the select clause specifies an anonymous type
            var custQuery = from cust in customers
                            where cust.City == "Phoenix"
                            select new { cust.Name, cust.Phone };

            // var must be used because each item 
            // in the sequence is an anonymous type
            foreach (var item in custQuery)
            {
                Console.WriteLine("Name={0}, Phone={1}", item.Name, item.Phone);
            }

var 형식은 annonymous 형식을 위해 사용 되어 짐.
: https://msdn.microsoft.com/ko-kr/library/bb397696.aspx

  
var v = new { Amount = 108, Message = "Hello" };  
  
// Rest the mouse pointer over v.Amount and v.Message in the following  
// statement to verify that their inferred types are int and string.  
Console.WriteLine(v.Amount + v.Message);  
- 익명 형식은 object에서 직접 파생되고 object를 제외한 모든 형식으로 캐스팅 될 수 없는 class 형식으라고 함. 다른 reference 형식과 같음.
- 익명 형식은 필드, 속성, 이벤트, 메서드 반환 형식으로 선언될 수 없다고 함.



dynamic
: https://msdn.microsoft.com/ko-kr/library/dd264741.aspx

솔직히 직접 안써봐서 모르겠음.

* 형식 검사를 컴파일 타임이 아니라 런타임 때 수행 함.
* 대부분 환경에서 object와 동일하게 동작하고 실제 컴파일 시점에 object 형식 변수에 컴파일 된다고 하여 dynamic 형식은 컴파일 시점에만 존재한다고 함.
* COM API, IronPython 라이브러리 같은 동적 API 및 HTML DOM에 대한 액세스를 간소화 한다고 함.(??)

    class Program
    {
        static void Main(string[] args)
        {
            dynamic dyn = 1;
            object obj = 1;

            // Rest the mouse pointer over dyn and obj to see their
            // types at compile time.
            System.Console.WriteLine(dyn.GetType());
            System.Console.WriteLine(obj.GetType());
        }
    }
WriteLine 문은 dyn  obj의 런타임 형식을 표시합니다. 이 시점에서는 모두 동일한 형식 정수입니다. 다음 출력이 생성됩니다.
System.Int32
System.Int32
컴파일 시간에 dyn  obj 사이의 차이를 확인하려면 앞의 예제에서 선언과 WriteLine 문 사이에 다음 두 줄을 추가합니다.
dyn = dyn + 3;  
obj = obj + 3;  
  

 obj + 3에 정수와 개체를 추가하려고 시도한 경우 컴파일러 오류가 보고됩니다. 그러나 dyn + 3에 대해서는 오류가 보고되지 않습니다.dyn이 포함된 식은 dyn의 형식이 dynamic이기 때문에 컴파일할 때 확인되지 않습니다.

var와의 차이점
* 속성, 매개변수, 반환값, 지역 변수 등에서 사용 가능
* 초기화 이후 type 변경 가능
* 런타임 시점에 타입을 확장하여 runtime error가 발생 할 수 있음.




2016년 11월 2일 수요일

소프트웨어 장인 : 프로페셔널리즘, 실용주의, 자부심

http://m.yes24.com/Goods/Detail/20461940

소프트웨어 장인 : 프로페셔널리즘, 실용주의, 자부심
산드로 만쿠소 저/권오인 역 | 길벗



서점가서 처음에 표지보고 이게 뭥미 하고 무시했었는데 지인이 추천해서 보게 되었음.
책 저자가 너무 말이 많은듯해서 읽기가 지지부진했었는데 다른 사람들도 읽는 거 보고 궁금해서 완독함.

읽다 보면 뭐 이건 당연한 것 아닌가 했던 내용이 있어 읽으며 동의하며 줄줄 읽었음. 다만 저자의 다양하고 오랫동안 경험들이 책의 내용이라 아주 알차다. 너무 알차서 읽다가 질릴 정도로 아주 자세하고 유익하다.

솔직히 읽는 중에 장인이라는 용어가 좀 거슬렸었다. 사실 소프트웨어 엔지니어, 개발자, 코더 등등 같은 용어를 써도 별 상관이 없이 맡은 일에 대한 열정과 자부심을 가지고 대하면 된다는 생각을 하는 터라 왠지 모를 의도가 있을 것 같은 장인이라는 호칭이 좀 부자연스러웠었다. 하지만 책의 appendix를 보면 저자의 의도와 관련된 오해를 풀 수 있었다. 책을 읽을 때 장인이라는 단어에 집착하기보다 그 호칭을 부르기 위한 조건, 태도, 의도에 집중하는 것이 좋을 것 같다.

저자가 영국 컨설팅회사에서 근무하는 것 같아 국내와 좀 다른 환경에서 근무하지 않을까 생각했었는데 생각외로 국내의 환경이 열악한 쪽으로 더했으면 더했지 덜하지는 않을 것 같다.
그리고 저자가 제시하는 방법들 가령 애자일방법론, 오픈소스활동, 스터디 등도 관심만 있다면 국내에서 충분히 가능한 것 같다.

공감된 부분들이 상당히 많지만 몇 가지 발췌하자면 다음과 같다. 단 책의 일부이므로 온전하게 읽어보는 것을 추천

“네 커리어와 프로페셔널로서의 미래는 누구의 책임인가?” 그날의 대화가 있은 지 몇 년이 흘렀지만 아직도 그의 당혹스런 눈빛을 기억한다.
: 맞는 말이다. 회사에서 최선으로 일해야하지만 환경과 여건을 핑계로 자기개발을 게을리하면 안된다. 결국 자기 손해인 것 같다.

"보통 어떤 개념이나 행동양식을 다룬 책들이 혁명적인 책이 될 때가 대부분이다. 『실용주의 프로그래머』, 『The Mythical Man-Month』, 『디자인 패턴(GoF)』, 『테스트 주도 개발』, 『익스트림 프로그래밍』, 『클린 코더』, 『소프트웨어 장인정신』, 『리펙토링』과 같은 책들이 있다. 이러한 종류의 책들을 완전히 이해하려면 몇 년 이상이 걸리기도 한다."
: 이 책들은 기본 필독서다.

"차드 파울러Chad Fowler는 저서 『열정적인 프로그래머』에서 그저 실망시키지 않기 위해 말하는 ‘네’는 거짓말에 지나지 않는다고 했다. 그냥 거짓말이 아니라 중독적이고 파괴적인 습관이다. 양의 탈을 쓴 나쁜 습관이다."

"관리자는 팀의 한 부분이다. 관리자도 팀과 동고동락해야 한다. 팀원 모두가 야근을 한다면 관리자도 야근을 해야 한다. .... 그렇게 하면 팀원 모두가 같은 배를 탔다는 공동체 의식이 강화되고 프로젝트의 고통과 희열을 함께 느낄 수 있다. 무엇이 되었든 성과를 낼 수 있는 것에 몰입하는 분위기가 조성된다. 좋은 관리자는 외부의 압력으로부터 개발자를 보호하고 팀이 가진 장애요소들을 제거한다."

아무도 참여하려 하지 않는다면
  무언가에 관심을 갖도록 사람들의 행동을 변화시키기는 어려운 일이다. 불가능하다고 말하는 사람들도 있다. 당신의 열정과 책에서 얻은 지식으로 조직 전체를 바꿀 생각이라면 그냥 잊는 게 좋다. 그런 일은 일어나지 않는다. 몇몇 사람들로 하여금 개발자로서의 자부심과 즐거움, 열정을 되찾도록 돕는 것은 가능하다.

모범을 보여 사람들을 이끌라
  기술적 변화를 추진할 때, 특히 TDD 처럼 태도에 대한 변화까지 필요로 하다면, 직접 보여 주면서 따라하게 하는 것이 가장 좋은 방법이다. "


대략적인 목차는 다음과 같다.

1부 이념과 태도

1장 21세기의 소프트웨어 개발
2장 애자일
3장 소프트웨어 장인정신
4장 소프트웨어 장인의 태도
5장 영웅, 선의 그리고 프로페셔널리즘
6장 동작하는 소프트웨어
7장 기술적 실행 관례
8장 길고 긴 여정


2부 완전한 전환

9장 인재 채용
10장 소프트웨어 장인 면접하기
11장 잘못된 면접 방식
12장 낮은 사기의 대가
13장 배움의 문화
14장 기술적 변화의 실행
15장 실용주의 장인정신
16장 소프트웨어 장인으로서의 커리어

부록 소프트웨어 장인정신에 대한 오해와 설명


리디북스에서 자세히 보기 : http://ridibooks.com/v2/Detail?id=754016528

2016년 11월 1일 화요일

Xamarin.forms 사용 중 ViewModel에서 page navigation이 필요한 경우

Xamarin.forms를 사용 하여 MVVM pattern을 구현하다보면
View가 아닌 ViewModel에서 event 처리를 하면서 page navigation이 필요할 때가 있음.

하지만 Navigation 객체에는 View에 있으므로
View의 INavigation type 객체를 ViewModel로 넘겨서 이를 사용하기 하는 방법이 필요.

이렇게 되면 XAML에서 BindingContext로 ViewModel을 지정하는 것이 아니라
Code 상에서 BindingContext를 지정하면서 인자로 Navigation 객체를 넘겨야 한다.

자세한 것은 아래 링크 참고


http://www.johankarlsson.net/2014/09/navigation-from-viewmodel-using.html

 public class MainPageViewModel : INotifyPropertyChanged
    {
        private PersonRepository _repository;
        private INavigation _navigation; // HERE

        public MainPageViewModel (INavigation navigation) // HERE
        {
            _navigation = navigation; // AND HERE

            // This should be injected
            _repository = new PersonRepository();

            // Populate the ViewModel
            var person = _repository.GetPerson(42);
            Name = person.Name;
            Updated = person.Updated;
        }
    }