C # okumak zorlaşıyor mu?


15

C # ilerledikçe, birçok dil özelliği eklenmiştir. Benim için okunamaz hale geldiği noktaya geldi.

Örnek olarak, burada Caliburn.Micro kodundan aşağıdaki kod parçacığını düşünün :

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

Şimdi, bu sadece küçük bir örnek.

Birkaç sorum var:

  • Bu yaygın veya bilinen bir sorun mu?
  • C # topluluğu aynı mı?
  • Bu dil ile ilgili bir sorun mu, yoksa geliştirici tarafından kullanılan stil mi?

Başkalarının kodunu daha iyi anlamak ve bu şekilde kod yazmaktan kaçınmak için basit çözümler var mı?


6
Onun lambda fonksiyonu, onları gerçekten elde edene kadar okumak zor.
Ryathal

9
Bence sen de düşündüğün gibi sentaksı bilmiyorsun. Alıştırma ile örnek okuma basittir.
ChaosPandion

6
@Thomas Owens: Kahretsin, en azından soruları açık tutmak için bize biraz zaman tanıyın . 15 dakika? Şimdi hadi.
Steven Evers

4
@DannyVarod: 1. "Hayır" kabul edilebilir bir cevap değil 2. Soru kapalı 3. Sorunun burada olmaması gerektiğini kabul ediyorsanız, kapatmak için işaretleyin / oylayın veya daha iyi olacak şekilde düzenleyin .
Steven Evers

2
@ Thorbjørn Ravn Andersen - Bir tokattan ne öğrenebilirim? Bu bilgi içermiyor!

Yanıtlar:


12

Dilin nerede bulunduğuna dair hızlı not: C # genel amaçlı bir programlama dilidir ; C'den (C ++ gibi) farklı olarak yüksek soyutlama için çaba gösterir; Lisp lehçelerinden farklı olarak pratik ifade etmeyi amaçlamaktadır ve Java'nın aksine, daha agresif bir şekilde yönlendirilmektedir - Microsoft talebe hızlı bir şekilde cevap vermektedir.

Bu yüzden LINQ, lambdas ve garip yeni anahtar kelimelerin karışımına dönüşüyor - yeni sorun alanlarına hızlı bir şekilde adapte oluyor ve bu gerçekten çok karmaşık bir dile doğru kaygan bir eğim (C ++ gibi). Bu C # ile ilgili bir sorun değil, bu iddialı hedefleri olan herhangi bir dilde bir sorun.

Topluluk bunun farkında ve daha da önemlisi, C #'ın arkasındaki adamlar bunun farkında. (C # 5.0'daki yeni eklemelerin arkasında ne olduğuna dair birkaç blog girişi ve podcast, bu adamların işleri ne kadar basit tutmak istediğini gösteriyor). Microsoft , amiral gemilerinden bazılarını bir tarpit haline gelmeyecek şekilde kaldırmaya çalışıyor: DLR'nin tanıtımı, yeni diller üzerinde parlak bir spot ışığı (F #).

Dahası, C # üzerindeki ders materyali (MS sertifikaları dahil), soruna bağlı olarak C # için farklı (ancak tutarlı) kullanım stilleri önerir - silahınızı seçin ve ona bağlı kalın: Bazı problemlerde akıcı tarzı LINQ, diğerlerinde TPL ile lambdas, düz -Çoğu için eski.


2
Ne demek istediğini "Lisp lehçelerinden farklı olarak pratik ifadeyi hedefliyor" ile açıklayabilir misin?
Giorgio

27

Hayır. C # bize kodu daha kısa sürede yazmak için daha fazla seçenek sunuyor. Bu kullanılabilir veya kötüye kullanılabilir. Düzgün kullanılırsa, kodun okunmasını kolaylaştırır. Yanlış kullanılırsa kodun okunması zorlaşır. Ancak kötü programcılar her zaman zor okunan kod yazma becerisine sahipti.

Her ikisi de aynı sorunla ilgili StackOverflow'da bulunan örneklere dayanarak, belirli bir özniteliğe sahip türler bularak iki örnek alalım:

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, yeni sözdizimini okumayı çok daha kolay hale getiriyor.


yeni sözdiziminin okunması gerçekten daha kolay, ama anlaşılması daha kolay, kaputun altında neler olup bittiği gibi? İlk örnek anlaşılabilir, ikincisi daha okunabilir.
nawfal

4
@nawfal Benim tecrübelerime göre, insanlar "getiri" yapılarını anlamak için linq ifadelerinden çok daha fazla sorun yaşıyorlar; bu yüzden ikincisinin daha okunabilir ve anlaşılır olduğunu iddia ediyorum. Her ikisi de size kaputun altında neler olup bittiğini söylemiyor, çünkü her iki işlemcinin de işlemcilerin gerçekte nasıl çalıştığından çok uzaktaki soyutlamaları gösteriyor.
Chuu

Dürüst olmak gerekirse, LINQ'dan hoşlanmam çünkü döngüleri soyutlar ve kodlayıcıları daha karmaşık bir çekirdeğe sahip bir döngü yerine ayrı LINQ sorgularında (arka planda ayrı döngülerle) veri almaya teşvik eder.
mg30rg

8

LINQ eklendiğinde, çok sayıda Fluent tarzı yöntem zincirleme ve lambdaların parametre olarak geçirilmesini içeren bir kodlama stili popülerleştirildi.

Bu tarz rahat edince çok güçlü. Ancak , okunamayan kodlar yapmak kötüye kullanılabilir. Girintinin bir tür rastgele olmasına rağmen örneğinizin çok kötü olduğunu düşünmüyorum (ve bu kod stilinin ortak bir özelliği, Visual Studio bunu çok tutarlı bir şekilde girintili yapmıyor).

İşyerimde, bu yılın başlarında kodlama standartlarımızı gözden geçirirken bu kodlama stilini tartıştık ve geliştiricileri bu şekilde kod kırmaya teşvik etmeye karar verdik: özellikle bir işlev çağrısı içinde anonim nesneler oluşturup başlatmamaya karar verdik. Böylece kodunuz şöyle olur:

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

1
Yeni bir tür oluşturmak garip bir şey değil mi ve hemen sonra bu türün dinamik olarak açılması?
DeadMG

Muhtemelen, kod pasajını niyetinin ne olduğuna dair gerçek bir değerlendirme yapmadan kestim. Kodun görünümü üzerinde ne gibi bir etki yaratacağını göstermek için tüm örneklemeleri kendi kod satırlarına ayırmak istedim.
Carson63000

Girintiyi suçluyorum :(). İşte orijinal: devlicio.us/blogs/rob_eisenberg/archive/2010/07/08/…

1
Bu cevaba tamamen katılıyorum. Örnek kod parçasındaki sorun yeni C # sözdizimi değil, yazar bir "tek satırlı" kod ile akıllı olmaya çalıştı. UNIX'ten kalma bu eski kural var: her şey sadece bir şey yapmalı ve iyi yapmalı. Sınıfa uygulanır, yönteme uygulanır ve tabii ki kesinlikle kod satırlarına uygulanır.
Laurent Bourgault-Roy

4

Örneğinizdeki kod kolayca okunamıyor çünkü

  • Birçok nosyonu (Kompozisyon, Kataloglar, Agregalar, Montajlar, ComposableParts ...) çeşitli iç içe yerleştirme seviyeleriyle karıştırırken, çağrı kodu genellikle sadece bir seviye ile uğraşmak zorundadır. Bir alt-alt özellik zinciri yerine sadece iç içe yöntem çağrıları ile Demeter Yasasının ihlali gibi görünüyor. Bu, kod satırının arkasındaki niyeti bir şekilde karıştırır.

  • Tuhaf bir singleton kullanımı var - AssemblySource.Instance.Select()Instance'ın IEnumerable olduğunu ima ediyor, bu biraz garip.

  • Lambda ifadesindeki x değişkeni çirkin. Genellikle lambda değişkenlerinize isimleri açıklamaya niyet etmeye çalışırsınız - lambdalara aşina olmasa bile, okuyucunun işlevin ne tür verileri hakkında olduğunu belirlemesine yardımcı olur.

  • Neden OfType<T>()yeni oluşturduğunuz bir nesne koleksiyonuyla filtrelemeniz gerektiği açık değil ...

Bununla birlikte, tüm bu kusurlar orijinal geliştiricinin kodu yazma şekli ve onu ne kadar etkileyici şekilde tasarladığı ile ilgilidir. Bu, C # 'ın en son sürümlerine ve lambda ifadelerinin görünümüne özgü bir şey değildir.

Daha genel olarak, kodunuzun okuyucusu lambdaların nasıl çalıştığını biliyorsa yardımcı olur, ancak yeterince net bir adlandırma ile neredeyse kodunuzu .NET 3.5 geçmişine sahip biri için bile okunabilir hale getirebilirsiniz.


2

Popüler dilin yeni bir sürümü her zaman yeni yapılar kazanır, benzer tartışmalar ortaya çıkar.

Bu şüphelerimi yıllar önce de yaşadım (http://gsscoder.blogspot.it/2009/08/use-csharps-features-wisely.html).

Bence C # zarif ve tutarlı bir şekilde gelişiyor.

Örneğinizdeki kod karmaşık değil, belki lamda ifadeleriyle kullanılmazsınız.

Sorun şu ki, C # sadece nesne yönelimli bir dil değil, aynı zamanda fonksiyonel yapıları da destekliyor (http://archive.msdn.microsoft.com/FunctionalCSharp/).


1

Lambda sözdizimini anlamak biraz zaman aldı ve ben bir matematik ve fizik geçmişinden geliyorum. Matematiksel ifadelere biraz benzer, kullandıkları alt> => yerine:>:

Matematik örneği f (x): = x-> x + 2, "x'in f fonksiyonu x + 2'ye x eşlemesi olarak tanımlanır

c # örnek del myDelegate = x => x +2; "myDelegate, myDelegate (x) 'in x ile x + 2 arasında eşleşeceği bir işlevdir.

Matematik ve programlama arasındaki tutarsızlık gerçekten yardımcı olmuyor, ancak sanırım -> C ++ 'da "özelliği" (urrgghh!)

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


"Her ne kadar -> Zaten C + +" (urrgghh!) "özelliği olarak alınmıştır varsayalım" sanki! C ++ 'da kötü bir şekilde "dinamik olarak ayrılmış ..." özelliği anlamına gelir. Bir şey dinamik değilse, dönemi diğer tüm diller gibi kullanırsınız.
mg30rg
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.