출처: http://qiita.com/ryotanatsume/items/018cae5c5be8faba367a



KISS

Keep It Simple, Stupid

간단하게 해 어리석은 놈아


코드를 쓸 때 "단순성"이나 "간결성"을 최대 중요 항목으로 한다.


코드는 자연에 맡겨 수정해 가면 무 질서하게 되고 복잡해진다. 

그 결과, 읽기 어렵고 수정하기 어려워진다.

코드를 간단하게 유지하는 것으로 수정하기 쉬워 진다.


구체적으로는 프로그래밍할 때 "동작하기 위해서 가장 단순한 것은 무엇인가"라고 자주 물어보는 것이 필요하다.



DRY

Don't Repeat Yourself.

되풀이하지 마라.


같은 코드를 중복해서 쓰지 말라는 것.


왜냐하면, 코드의 개선이 어려워지기 때문이다.

우선 같은 코드가 여럿 있는 것으로 양적으로 "더 많은" 질적으로 "보다 복잡한 "이 되기 때문에 코드를 읽는 작업이 어려워진다.

또 수정할 때도 하나 고칠 때도 중복해서 쓴 코드에 대해서도 빠짐없이 고쳐야 하니 큰일이다.


구체적으로는 처리의 모음은 "함수화" "모듈화"를 하고 데이터는 이름 있는 정수를 정의하는 것이 중요하다.



YAGNI

You Aren't Going to Need it.

그것은 꼭 필요하게 되지 않는다


코드를 필요 최저한으로 한다.


미리 여러가지 사태에 대비하여 코드를 써도 결국은 이용되지 않는 것이 많다.

그리고 그것에 의해서 코드에 "쓸데없는" 복잡성을 담아 버리게 되는, KISS에 사상에도 역행한다.

즉, 예상이 빗나간 경우 시간이 헛되게 사용하는 것에 더해 방해도 되는 것이다.

그리고 단순 코드가, 범용성이 높다.

구체적으로는 보편성보다는 단순성을 생각하는 것이 중요. 

코드는 "지금" 필요한 것만 하기.



PIE

Program Intently and Expressively

의도를 표현하는 프로그래밍을 해라


코드는 의도를 분명히 표현하게 써야 한다는 것이다.


코드가 "사람"이 읽기 위한 것이며 코드만이 소프트웨어의 동작을 "정확히" "완전히" 알기 위한 단서이다.

따라서 소프트웨어의 동작을 파악하는 데는 쉬운 코드를 쓰고 코드에서 의도를 전하는 수밖에 없다.


구체적으로는 코드를 쓸 때는 "쓰기 쉬움" 보다 "읽기 쉬움"을 중시하는 것.

코드는 "쓰는 것" 보다 "읽는 것"이 더 많은 것이기 때문이다.



SLAP

Single Level of Abstraction Principle

추상화 수준의 통일


코드를 쓸 때 높은 수준의 추상화 개념과 낮은 수준의 추상화 개념을 분리하도록 할 것.


왜냐하면, 코드가 수준에 어울리는 함수로 분할됨으로써 "요약성" "열람성"을 동시에 충족시킬 수 있다.

같은 곳에는 같은 추상도의 처리와 같이 코드가 통일됨으로써 코드는 거침 없이 흐르고 이해하기 쉽다.


구체적으로는 함수를 구조화하는 것이 중요하다.

하나의 함수에서 어느 부분에서는 데이터베이스 접속은 저 수준의 처리를 하고 다른 부분에서는 비즈니스 로직의 실행이라는 높은 수준 처리를 하도록 하지 않는 것이 중요하다.



저작자 표시
신고
by 흥배 2016.11.07 08:00

잘못된 SqlConnection

// 코드 1

using (var connection = new SqlConnection("접속문자열"))

{

    connection.Open();

    Parallel.For(1, 1000, x =>

    {

        var _ = connection.Query<DateTime>("select current_timestamp").First(); // Dapper

    });

}


<코드 1>을 실행하면 크래쉬가 발생

이유는 간단 SqlConnection가 스레드 세이프 하지 않기 때문.


위의 코드를 올바르게 수정하려면 아래와 같이 변경.

// 코드 2

Parallel.For(1, 1000, x =>

{

    using (var connection = new SqlConnection("접속문자열"))

    {

        connection.Open();

        var _ = connection.Query<DateTime>("select current_timestamp").First(); // Dapper

    }

});



<코드 2>는 안전하지만 아마 위 방식은 원하는 방식이 아닐 것이다.



ThreadLocal

위의 문제를 ThreadLocal을 사용하여 해결해 보자


// 코드 3

using (var connection = new ThreadLocal<SqlConnection>(() => { var conn = new SqlConnection("접속문자열"); conn.Open(); return conn; }))

{

    Parallel.For(1, 1000, x =>

    {

        var _ = connection.Value.Query<DateTime>("select current_timestamp").First(); // Dapper

    });

}



성능 테스트를 해보면 싱글 스레드를 사용하면 16초, <코드 2>는 5초, <코드 3>은 2초



<코드 3>은 안전한가?

<코드 3>은 위험한 코드.

이유는 연결한 후 Dispose 하지 않기 때문.

ThreadLocal의 Dispose는 어디까지는 ThreadLocal의 Dispose이기 때문에 그 안의 객체를 Dispose 해주지 않는다.


이 문제는 trackAllValues 라는 옵션을 사용하여 간단하게 해결 가능!



// 코드 4

using (var connection = new ThreadLocal<SqlConnection>(() => { var conn = new SqlConnection("접속문자열"); conn.Open(); return conn; }

    , trackAllValues: true)) // ThreadLocalの.Values 프로퍼티의 참조를 유효화 한다

{

    Parallel.For(1, 1000, x =>

    {

        var _ = connection.Value.Query<DateTime>("select current_timestamp").First(); // Dapper

    });


    // 생성된 모든 Connection을 일괄적으로 Dispose

    foreach (var item in connection.Values.OfType<IDisposable>()) item.Dispose();

}



단 trackAllValues는 닷넷프레임워크 4.5 부터 사용 가능




trackAllValues 랩퍼 클래스 사용


public static class DisposableThreadLocal

{

    public static DisposableThreadLocal<T> Create<T>(Func<T> valueFactory)

        where T : IDisposable

    {

        return new DisposableThreadLocal<T>(valueFactory);

    }

}


public class DisposableThreadLocal<T> : ThreadLocal<T>

    where T : IDisposable

{

    public DisposableThreadLocal(Func<T> valueFactory)

        : base(valueFactory, trackAllValues: true)

    {

    }


    protected override void Dispose(bool disposing)

    {

        var exceptions = new List<Exception>();


        foreach (var item in this.Values.OfType<IDisposable>())

        {

            try

            {

                item.Dispose();

            }

            catch (Exception e)

            {

                exceptions.Add(e);

            }

        }


        base.Dispose(disposing);


        if (exceptions.Any()) throw new AggregateException(exceptions);

    }

}



// 사용

using (var connection = DisposableThreadLocal.Create(() => { var conn = new SqlConnection("접속문자열"); conn.Open(); return conn; }))

{

    Parallel.For(1, 1000, x =>

    {

        var _ = connection.Value.Query<DateTime>("select current_timestamp").First(); // Dapper

    });

}





출처: http://neue.cc/2013/03/09_400.html 

저작자 표시
신고
by 흥배 2016.11.04 08:00

'게임 서버 제작자' 모임에서 10월 25일에 했던 강연 중의 하나 


'CTO가 하는 일 '

https://www.youtube.com/watch?v=hkzgPFd_IFU&feature=youtu.be




저작자 표시
신고
by 흥배 2016.11.02 08:00
| 1 2 |