C #을 읽기 어려워지고 있습니까?


15

C #이 진행되면서 많은 언어 기능이 추가되었습니다. 그것은 읽을 수 없게되는 시점에 도달했습니다.

예를 들어 Caliburn.Micro 코드에서 다음 코드를 살펴 보십시오 .

            container = CompositionHost.Initialize(
                   new AggregateCatalog(
                      AssemblySource.Instance.
                             Select(x => new AssemblyCatalog(x))
                               .OfType<ComposablePartCatalog>()
                )
            );

자, 이것은 작은 예일뿐입니다.

여러 가지 질문이 있습니다.

  • 이것이 일반적이거나 알려진 문제입니까?
  • C # 커뮤니티가 동일하게 발견됩니까?
  • 언어에 문제가 있습니까, 아니면 개발자가 사용하는 스타일입니까?

다른 코드를 더 잘 이해하고 이러한 방식으로 코드를 작성하지 않는 간단한 솔루션이 있습니까?


6
람다 함수이며, 실제로 얻을 때까지 읽기가 어렵습니다.
Ryathal

9
나는 당신이 생각하는 것뿐만 아니라 구문을 정말로 모른다고 생각합니다. 연습을 통해 예제를 읽는 것은 간단합니다.
ChaosPandion

6
@Thomas Owens : 이런 젠장, 적어도 질문을 편집 할 수 있는 시간을 주어야합니다. 15 분? 어서
Steven Evers

4
@DannyVarod : 1. "아니오"는 용인 할 수있는 대답이 아닙니다. 2. 질문이 마감되었습니다. 3. 질문이 여기에 있어서는 안된다는 데 동의하면 질문을 닫으려면 투표 하거나 투표하십시오 .
Steven Evers 2016 년

2
@ Thorbjørn Ravn Andersen-때리고 무엇을 배울 수 있습니까? 정보가 없습니다!

답변:


12

언어를 명확하게 작성해야하는 위치에 대한 빠른 참고 사항 : C #은 범용 프로그래밍 언어입니다 . C (C ++과 같은)와 달리 높은 추상화를 위해 노력합니다. Lisp 사투리와 달리 실용적 표현을 목표로하며 Java와 달리 더욱 적극적으로 추진됩니다. Microsoft는 요구에 신속하게 대응합니다.

이것이 LINQ, 람다 및 이상한 새로운 키워드가 혼합 된 이유입니다. 새로운 문제 영역에 빠르게 적응하고 있으며 실제로 언어에 대한 미끄러운 기울기 때문에 언어를 복잡하게 사용하여 C ++과 같이 거의 사용할 수 없습니다. C # 자체에는 문제가 아니며, 이러한 야심 찬 목표를 가진 모든 언어에 문제가 있습니다.

커뮤니티는 이것을 알고 있으며, 더 중요한 것은 C #의 사람들이 이것을 잘 알고 있다는 것입니다. Microsoft 새로운 언어 (F #)에 대한 밝은 스포트라이트 인 DLR의 도입으로 타르타르가되지 않도록 플래그쉽을 떨어 뜨리려고 노력하고 있습니다.

또한 C # (MS 인증 포함)의 강의 자료에서는 문제에 따라 C #에 대해 서로 다른 (일관된) 스타일의 사용을 권장합니다. 무기를 선택하고이를 고수하십시오. 일부 문제에 대한 유창한 스타일 LINQ, 다른 문제에 대한 TPL이 포함 된 람다, 일반 -가장 오래된.


2
"실제 표현력을 목표로하는 Lisp 방언과 달리"의 의미를 설명 할 수 있습니까?
조르지오

27

아니요. C #은 더 간결하게 코드를 작성할 수있는 더 많은 옵션을 제공합니다. 이것은 사용되거나 남용 될 수 있습니다. 올바르게 사용하면 코드를보다 쉽게 ​​읽을 수 있습니다. 잘못 사용하면 코드를 읽기가 더 어려워 질 수 있습니다. 그러나 나쁜 프로그래머는 항상 읽기 어려운 코드를 작성하는 기술을 가지고있었습니다.

동일한 문제와 관련하여 StackOverflow에서 찾은 예를 기반으로 특정 속성이있는 유형을 찾는 두 가지 예를 살펴 보겠습니다.

C # 2.0 :

static IEnumerable<Type> GetTypesWithAttribute<TAttribute>(bool inherit) 
                              where TAttribute: System.Attribute
{
    foreach(Assembly assembly in AppDomain.Current.GetAssemblies())
    {
        foreach(Type type in assembly.GetTypes()) 
        {
            if (type.IsDefined(typeof(TAttribute),inherit))
                yield return type;
        }
    }
}

C # 4.0 :

IEnumerable<Type> GetTypesWith<TAttribute>(bool inherit) 
                              where TAttribute: System.Attribute
{ 
    return from assembly in AppDomain.CurrentDomain.GetAssemblies()
           from type in assembly.GetTypes()
           where type.IsDefined(typeof(TAttribute),inherit)
           select type;
}

새로운 구문 인 IMHO를 사용하면 훨씬 쉽게 읽을 수 있습니다.


새로운 구문은 실제로 읽기 쉽지만 이해하기 쉽습니다. 첫 번째 예는 이해할 만하고 두 번째 예는 더 읽기 쉽습니다.
nawfal

4
@nawfal 내 경험상 사람들은 linq 구문보다 "수율 반환"구문을 이해하는 데 훨씬 더 많은 어려움을 겪고 있습니다. 그래서 두 번째가 더 읽기 쉽고 이해하기 쉽다고 주장합니다. 두 가지 모두 프로세서가 실제로 작동하는 방식과는 거리가 먼 추상화로 매핑되므로 실제로 어떤 일이 일어나고 있는지 알 수 없습니다.
Chuu

솔직히 말해서 LINQ는 루프를 추상화하고 코더가 더 복잡한 코어가있는 하나의 루프 대신 별도의 LINQ 쿼리 (백그라운드에 별도의 루프 포함)로 데이터를 검색하도록 권장하기 때문에 LINQ를 싫어합니다.
mg30rg

8

LINQ가 추가되면 많은 Fluent 스타일 메소드 체인과 람다를 매개 변수로 전달하는 코딩 스타일이 대중화되었습니다.

이 스타일은 일단 익숙해지면 매우 강력합니다. 그러나 읽을 수없는 코드를 작성하는 것은 남용 될 수 있습니다. 들여 쓰기가 임의적이지만 (이 스타일의 코드의 일반적인 기능인 Visual Studio는 일관성있게 자동 들여 쓰기하지 않습니다) 귀하의 예제가 너무 나쁘지 않다고 생각합니다.

직장에서 우리는 올해 초에 코딩 표준을 검토 할 때이 코딩 스타일에 대해 논의했으며 개발자가 다음과 같은 코드를 분리하도록 장려하기로 결정했습니다. 특히 함수 호출 내에서 익명의 객체를 생성 및 초기화하지 않기로 결정했습니다. 따라서 코드는 다음과 같습니다.

var assemblyCatalog = AssemblySource.Instance
    .Select(x => new AssemblyCatalog(x))
    .OfType<ComposablePartCatalog>();
var aggregateCatalog = new AggregateCatalog(assemblyCatalog);
container = CompositionHost.Initialize(aggregateCatalog);

1
새로운 유형을 만든 다음 바로 그 유형을 동적으로 전환하는 것이 이상하지 않습니까?
DeadMG

아마도 의도가 무엇인지 실제로 고려하지 않고 코드 스 니펫을 잘라 냈습니다. 모든 인스턴스화를 자체 코드 행으로 분할하여 코드 모양에 어떤 영향을 미치는지 보여 주려고했습니다.
Carson63000

나는 들여 쓰기에 대한 책임이 있습니다 :(). 원본은 다음과 같습니다. devlicio.us/blogs/rob_eisenberg/archive/2010/07/08/…

1
나는 그 대답에 전적으로 동의합니다. 예제 코드의 문제점은 새로운 C # 구문이 아니며, 작성기가 "한 줄짜리"코드로 영리하려고했습니다. UNIX에서이 이전 규칙 데이트 다시이있다 : 모든에만해야 일을, 잘 해. 그것은 클래스에 적용되고, 메소드에 적용되며, 물론 가장 확실하게 코드 라인에 적용됩니다.
Laurent Bourgault-Roy

4

예제의 코드는 쉽게 읽을 수 없습니다.

  • 호출 코드는 일반적으로 하나의 레벨 만 처리해야하는 반면 여러 개념 (구성, 카탈로그, 집계, 어셈블리, 컴포저 블 파트 ...)을 여러 레벨의 중첩과 혼합합니다. 하위 하위 속성 체인 대신 중첩 된 메소드 호출 만 사용하여 Demeter of Law를 위반하는 것처럼 보입니다. 이것은 코드 라인 뒤에 의도를 둔화시킵니다.

  • 이상한 싱글 톤 사용법이 있습니다- AssemblySource.Instance.Select()인스턴스는 IEnumerable이며 약간 어색합니다.

  • 람다 식의 x 변수는 추악합니다. 일반적으로 람다 변수에 이름을 나타내는 의도를 부여하려고 시도합니다. 람다에 익숙하지 않더라도 독자가 함수에 대해 어떤 종류의 데이터를 식별하도록 도와줍니다.

  • 왜 필터링해야하는지 명확하지 않습니다 OfType<T>()방금 새로 만든 개체 모음으로 .

그러나 이러한 모든 결함은 원래 개발자가 코드를 작성하는 방식과 코드의 표현력과 관련이 있습니다. 이것은 최신 버전의 C # 및 람다 식의 모양과 관련이 없습니다.

더 일반적으로, 코드 독자가 람다의 작동 방식을 알고 있으면 도움이되지만 충분히 명확하게 이름을 지정하면 .NET 3.5 이전의 배경 지식을 가진 사람도 코드를 읽을 수 있도록 할 수 있습니다.


2

인기있는 언어의 새로운 버전이 새로운 구조를 얻을 때마다 비슷한 논쟁이 일어납니다.

또한 몇 년 전에 이러한 의심이있었습니다 (http://gsscoder.blogspot.it/2009/08/use-csharps-features-wisely.html).

제 생각에는 C #은 우아하고 일관된 방식으로 발전하고 있습니다.

샘플의 코드는 복잡하지 않으며 람다 식과 함께 사용되지 않을 수 있습니다.

문제는 C #이 객체 지향 언어 일뿐만 아니라 이제 기능적인 구문 (http://archive.msdn.microsoft.com/FunctionalCSharp/)도 지원한다는 것입니다.


1

Lambda 구문을 이해하는 데 약간의 시간이 걸렸으며 수학 및 물리학 배경을 가지고 있습니다. 수학 표현식과 약간 비슷합니다. => 대신->를 사용합니다.

수학 예제 f (x) : = x-> x + 2 "x의 함수 f는 x가 x + 2에 매핑되는 x로 정의 됨"으로 읽습니다.

C # 예 del myDelegate = x => x +2; "myDelegate는 myDelegate (x)가 x를 x + 2에 매핑하는 함수입니다.

수학과 프로그래밍의 불일치가 실제로 도움이되지는 않지만 C ++에서 이미 "속성"(urrgghh!)으로 사용되었다고 가정합니다.

http://en.wikipedia.org/wiki/List_of_mathematical_symbols


"내가 생각하기는하지만 C ++에서 이미"속성 "(urrgghh!)으로 C ++에서 사용되었다고 가정 합니다. " C ++에서는 "동적으로 할당 된 속성의 속성"을 의미합니다. 역동적이지 않은 경우 다른 모든 언어와 같이 마침표를 사용하십시오.
mg30rg
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.