# Bölgeleri bir antipattern veya kod kokusu mu?


264

C #, #region/ #endregionanahtar kelimelerinin kod alanlarını düzenleyicide daraltılabilir hale getirmesini sağlar. Her ne zaman bunu yapsam da, muhtemelen başka sınıflara veya yöntemlere yeniden yerleştirilebilecek büyük kod parçalarını gizlemek için yapıyorum. Örneğin, yönetilebilir hale getirmek için 3 veya 4 bölgeli 500 satır kod içeren yöntemler gördüm.

Öyleyse bölgelerin makul kullanımı bir sorun belirtisi midir? Bana öyle geliyor.


9
Bilginize: CodeMap bölgelere olan ihtiyacı büyük ölçüde ortadan kaldırır. visualstudiogallery.msdn.microsoft.com/… - Tıklayın ve sizi / niteliği / ne olursa olsun yöntemine götürün. Her gün kullanıyorum ve üretkenlik ve bilişsel terimlerle ne kadar kazandığınız şaşırtıcı. Sınıfın daha net bir 'kuş bakışı görünümü' elde edersiniz.

7
Bunu bir wiki yapan var mı? Bu sorunun doğru ya da yanlış bir cevabı yoktur (haklı olarak), neredeyse tamamen özneldir.
Ed S.,

6
Buna değer, Jeff Atwood onlardan nefret ediyor . Kötü kod sakladıklarını savunuyor.
Brian

3
Kod kokusu, duş almayan ve deodorant kullanmayan bir geliştiricidir!
marko

5
Dikkatli bir şekilde işlenmiş bölgeler Kokmuş kodda, Febreeze'nin sıkışık bir koltukta birkaç sıkıntısının yaptığı şey. Yerine koymak için (zaman) parayı bulana kadar katlanılabilir hale getirir.
Newtopian

Yanıtlar:


284

Kod kokusu, tasarımda böcek sayısını potansiyel olarak artıracak bir sorun olduğunu belirten bir belirtidir: bölgeler için durum böyle değildir, ancak bölgeler uzun yöntemler gibi kod kokusu oluşturmaya katkıda bulunabilir.

Dan beri:

Anti-patern (veya antipattern), sosyal veya iş operasyonlarında veya yazılım mühendisliğinde kullanılan, yaygın olarak kullanılabilen ancak pratikte etkisiz ve / veya verimsiz olan bir paterndir.

bölgeler olan , anti-desenler. Kodun kalitesini veya okunabilirliğini artırmayacak, hata sayısını azaltmayacak ve kodu yalnızca refactor için daha karmaşık hale getirebilecek daha fazla çalışmaya ihtiyaç duyarlar.

Yöntemlerin içindeki bölgeleri kullanmayın; refactor yerine

Yöntemler kısa olmalı . Bir yöntemde sadece on satır varsa, muhtemelen diğer beşte çalışırken beşini gizlemek için bölgeleri kullanmazsınız.

Ayrıca, her yöntemin bir ve bir tek şey yapması gerekir . Diğer taraftan bölgeler farklı şeyleri ayırmak için tasarlanmıştır . Metodunuz A, B ise, iki bölge oluşturmak mantıklıdır, ancak bu yanlış bir yaklaşımdır; bunun yerine, yöntemi iki ayrı yönteme yeniden uygulamalısınız.

Bu durumda bölgelerin kullanılması yeniden yapılanmayı daha da zorlaştırabilir. Bir hayaliniz olduğunu düşünün:

private void DoSomething()
{
    var data = LoadData();
    #region Work with database
    var verification = VerifySomething();
    if (!verification)
    {
        throw new DataCorruptedException();
    }

    Do(data);
    DoSomethingElse(data);
    #endregion

    #region Audit
    var auditEngine = InitializeAuditEngine();
    auditEngine.Submit(data);
    #endregion
}

Birinci bölgeye ikinciye konsantre olacak şekilde çökertmek sadece riskli değildir: akışı durdurma istisnasını kolayca unutabiliriz ( returnbunun yerine bir bekçi maddesi olabilir , bunun yerine tespit edilmesi daha da zor olabilir), fakat aynı zamanda bir sorunu olurdu Kodun bu şekilde yeniden yapılandırılması gerekiyorsa:

private void DoSomething()
{
    var data = LoadData();
    #region Work with database
    var verification = VerifySomething();
    var info = DoSomethingElse(data);

    if (verification)
    {
        Do(data);
    }

    #endregion

    #region Audit
    var auditEngine = InitializeAuditEngine(info);
    auditEngine.Submit(
        verification ? new AcceptedDataAudit(data) : new CorruptedDataAudit(data));
    #endregion
}

Artık bölgeler bir anlam ifade etmiyor ve ilk bölgedeki kodu görmeden ikinci bölgedeki kodu okuyamıyor ve anlayamıyorsunuz.

Bazen gördüğüm başka bir dava şudur:

public void DoSomething(string a, int b)
{
    #region Validation of arguments
    if (a == null)
    {
        throw new ArgumentNullException("a");
    }

    if (b <= 0)
    {
        throw new ArgumentOutOfScopeException("b", ...);
    }
    #endregion

    #region Do real work
    ...
    #endregion
}

Bağımsız değişkenler doğrulaması onlarca LOC'ye yayılmaya başladığında bölgeleri kullanmak cazip gelir, ancak bu sorunu çözmenin daha iyi bir yolu vardır: .NET Framework kaynak kodu tarafından kullanılan:

public void DoSomething(string a, int b)
{
    if (a == null)
    {
        throw new ArgumentNullException("a");
    }

    if (b <= 0)
    {
        throw new ArgumentOutOfScopeException("b", ...);
    }

    InternalDoSomething(a, b);
}

private void InternalDoSomething(string a, int b)
{
    ...
}

Gruplandırmak için yöntemler dışındaki bölgeleri kullanmayın

  • Bazı insanlar alanları, özellikleri vb. Birlikte gruplamak için kullanırlar . Bu yaklaşım yanlıştır: kodunuz StyleCop uyumluysa, alanlar, özellikler, özel yöntemler, yapıcılar vb. Zaten bir araya getirilmiş ve bulmak kolaydır. Değilse, kod tabanınızda aynılığı sağlayacak kurallar uygulamayı düşünmeye başlamanın zamanı gelmiştir.

  • Diğer insanlar birçok benzer varlığı gizlemek için bölgeleri kullanır . Örneğin, yüz alanı olan (sınıfları ve boşlukları sayarsanız en az 500 satırlık kod yapan) bir sınıfınız olduğunda, bu alanları bir bölgeye koymak, daraltmak ve onları unutmak isteyebilirsiniz. Yine, bunu yanlış yapıyorsunuz: bir sınıftaki o kadar çok alanda, devralmayı kullanmayı veya nesneyi birkaç nesneye dilimlemeyi daha iyi düşünmelisiniz.

  • Son olarak, bazı insanlar bölgeleri ilgili şeyleri birlikte gruplamak için kullanmaya özen gösterirler: delegesiyle bir olay veya IO ile ilgili diğer yöntemlerle IO ile ilgili bir yöntem vb. İlk durumda, bakımı zor bir karmaşa olur. , oku ve anla. İkinci durumda, daha iyi tasarım muhtemelen birkaç sınıf oluşturmak olacaktır.

Bölgeler için iyi bir kullanım var mı?

Hayır. Eski bir kullanım vardı: oluşturulan kod. Yine de, kod oluşturma araçları bunun yerine kısmi sınıfları kullanmak zorunda. C # bölgeleri destekliyorsa, bunun nedeni çoğunlukla bu eski kullanımdır ve şimdi kodlarının çoğunda bölgeleri kullandığı için, varolan kod tabanlarını kırmadan bunları kaldırmak imkansız olacaktır.

Bunun hakkında düşün goto. Dil veya IDE'nin bir özelliği desteklemesi, günlük kullanılması gerektiği anlamına gelmez. StyleCop SA1124 kuralı açık: bölgeleri kullanmamalısınız. Asla.

Örnekler

Şu anda iş arkadaşımın kodunu kod incelemesi yapıyorum. Kod temeli birçok bölge içerir ve aslında hem bölgelerin nasıl kullanılmayacağına hem de bölgelerin neden kötü kodlara yol açtığına mükemmel bir örnektir. İşte bazı örnekler:

4 000 LOC canavarı:

Son zamanlarda bir yerde Programmers.SE'yi okudum. Bir dosya çok fazla usings içerdiğinde ("Kullanılmayan Kullanımları Kaldır" komutunu yürüttükten sonra), bu dosyanın içindeki sınıfın çok fazla çalıştığını gösteren bir işarettir. Aynısı dosyanın kendisi için de geçerlidir.

Kodu incelerken 4.000 LOC dosyası ile karşılaştım. Bu kodun yazarı, değişkenlerin adlarını ve çağrılan yöntemi hafifçe değiştirerek, aynı 15 satır yöntemini yüzlerce kez kopyalayıp yapıştırdığı ortaya çıktı. Basit bir regex sadece birkaç jenerik ekleyerek dosyayı 4.000 LOC'dan 500 LOC'ye kesmeye izin verdi; Daha akıllı bir yeniden düzenlemeyle, bu sınıfın birkaç düzine satıra indirgenebileceğinden eminim.

Yazar, bölgeleri kullanarak, kodun sürdürülmesinin ve kötü bir şekilde yazılmasının imkansız olduğu gerçeğini görmezden gelmeye ve yeniden yazmak yerine kodu ağır şekilde çoğaltmaya teşvik etti.

Bölge “Do A”, Bölge “Do B”:

Başka bir mükemmel örnek, basitçe görev 1, sonra görev 2, sonra görev 3, vb. Yapan bir canavar başlatma yöntemidir. Her biri bir konteyner sınıfında bir şeyi başlatan, tamamen bağımsız olan beş ya da altı görev vardı. Tüm bu görevler tek bir yöntemde gruplandı ve bölgelere göre gruplandı.

Bunun bir avantajı vardı:

  • Metot bölge adlarına bakarak anlaşılması oldukça açıktı. Bu söylenirse, refactored bir kez aynı yöntem, orijinal kadar net olacaktır.

Öte yandan, meseleler çoktur:

  • Bölgeler arasında bağımlılıklar olup olmadığı belli değildi. Umarım, değişkenlerin yeniden kullanımı yoktu; Aksi takdirde, bakım daha da kabus olabilirdi.

  • Yöntem test etmek neredeyse imkansızdı. Aynı anda yirmi şeyi yapan yöntemin bunları doğru yapıp yapmadığını kolayca nasıl bilebilirsin?

Alanlar bölgesi, özellikler bölgesi, yapıcı bölge:

Gözden geçirilmiş kod aynı zamanda bütün alanları bir araya getiren tüm bölgeleri, bütün özellikleri birlikte vb. İçeren bir çok bölgeyi içeriyordu.

Bir dosyayı açtığınızda ve çok büyük bir alan listesi gördüğünüzde, önce sınıfı yeniden ele geçirmeye daha meyillidir, sonra kodla çalışırsınız. Bölgelerle, işleri çökmekten ve unutmayı alışkanlık haline getiriyorsunuz.

Başka bir sorun ise, her yerde yaparsanız, kendinizi mantıklı olmayan tek bloklu bölgeler yaratırken bulacaksınız. Bu aslında incelediğim kodda, #region Constructorbir kurucu içeren çok fazla olan durumdu.

Son olarak, alanlar, özellikleri, vb kurucular zaten sırada olmalıdır . Eğer bunlar ve sözleşmelere uyuyorlarsa (büyük harfle başlayan sabitler vb.), Öğelerin tipinin nerede durduğu ve diğerlerinin başladığı açıktır, bu nedenle açıkça bunun için bölgeler oluşturmanız gerekmez.


13
Bence, en azından bir kaç savunulabilir-kullanım alanı vardır - örneğin, korunma maddelerinin çökmesi (girdi parametrelerinin kontrol edilmesi), eğer çözülmezse bırakılırsa, metodun özünü veya "etini" çıkarır. Diğer bir örnek API sınırlarında istisna kullanımıdır; istisnayı sarmak için başka yöntemleri çağırarak yığın izlemesini etkilemek istemezsiniz, bu nedenle sarmak ve yeniden okumak için birkaç satır kodunuz olur. Bu aynı zamanda genellikle alakalı olmayan koddur ve güvenle daraltılabilir.
Daniel B,

9
Gerçeklik kontrolü. Yöntemler arasında yardımcı olan # bölge hakkında çok şey gördüm. İçlerinde yer alan kontrol mantığına sahip birkaç yüz hat yöntemine sahip olduğunuzda, bunlardan bazılarında yüzlerce hat bulunur - salaklar en azından bölgelere yerleştirilmiş olanlara şükürler olsun.
radarbob

37
@radarbob: Kısacası bölgeler, ilk etapta olmamalıdır berbat kodunda yardımcı olur.
Arseni Mourzenko

41
-1 (itibarım varsa). Yazılı üyeleriniz iyi organize edilmiş ve ayrılmış olsalar bile, çoğu olabilir. Bölgeler, üzerinde çalışmak istediğiniz bir yönteme ulaşmak için 10 veya 12 özellikten sonra bunlarla ilişkili alıcı ve ayarlayıcıları kaydırmanızdan tasarruf etmenizi sağlar. Tek alternatif, tüm mülkünüzü ayrı ayrı çökertmek, hayranı olduğum bir şey değil. Sağlanan büyük ölçekli show / hide işlevsellik bölgeleri son derece kullanışlıdır. Yine de yöntem içi bölgeler konusunda hemfikirim.
Asad Saeeduddin

14
Kesinlikle bu cevaba katılmıyorum: Kod kıyameti ve bölgenin birbirleriyle hiçbir ilgisi yok. Kodunuz kokarsa, bölgeler olsun ya da olmasınlar, o pis kokuyor. Bölgeleri kullanmamın yolu, sınıflarımı bölgelere ayırmak. Genelde olsa aynı kalıba yapıyorum: Genel Özellikler, Genel Yöntemler, Özel Alanlar, Özel Yöntemler. Bölgelere sahip olacağım tek kullanım bu. Başka bir şey varsa, muhtemelen kodunuzda SRP müdürünü çiğniyorsunuz.
Alexus

113

Kaç kişinin bölgeleri bu kadar tutkuyla nefret ettiği benim için inanılmaz !

İtirazlarının çoğuyla tamamen aynı fikirdeyim: Kodu #regiongörünümden gizlemek için içine sokmak kötü bir şey. Bir sınıfı #regionsayrı sınıflara yeniden ayrılması gerektiğinde ayırmak açıkça bir hatadır. #regionGereksiz anlamsal bilgileri katıştırmak için a kullanmak , aslında gereksizdir.

Ancak bu şeylerin hiçbiri kodunuzdaki bölgeleri kullanırken doğal olarak yanlış bir şey olduğu anlamına gelmez ! Çoğu insanın itirazlarının, başkalarının bunun gibi IDE özelliklerini kullanma eğiliminde olan ekiplerde çalışmış olmasından kaynaklandığını varsayabilirim. Birincil olarak çalışma lüksüne sahibim ve bölgelerin iş akışımı düzenlememe yardım ettiklerini takdir ediyorum. Belki benim saplantılı zorlayıcı bozukluğumdur, ancak ne kadar zarif ve zarif bir şekilde yazılmış olursa olsun, ekranımda bir sürü kod görmekten hoşlanmıyorum. Mantıksal bölgeye şeyler ayırmak bana kod daraltmak için izin verir yok ben kod üzerinde çalışmak için umurumda yapmakönemsemek. Kötü yazılmış kodları görmezden gelmiyorum, onu yeniden olduğundan daha fazla yeniden etkilemenin anlamı yok ve ek "meta" organizasyonu da anlamsız değil açıklayıcı.

Artık C ++ 'da çalışarak daha fazla zaman harcadığımdan, doğrudan Windows API'sine programlama yaparak kendimi bölgelere yönelik desteğin C # için olduğu kadar iyi olmasını dileyerek buluyorum. Alternatif bir GUI kütüphanesi kullanmanın kodumu daha basit veya daha net hale getireceğini, böylece ekrandan alakasız kod parazitini alma ihtiyacını ortadan kaldıracağını iddia edebilirsiniz, ancak bunu yapmak istememenin başka nedenleri de var. Klavyem ve IDE'mde, bölgelere bölünmüş kodu genişletme / daraltma işleminin bir saniyeden daha kısa sürmesiyle yeteri kadar yetkinim. Beyin gücünden tasarruf ettiğim zaman, bilinçli odağımı sadece üzerinde çalışmakta olduğum kodla sınırlandırmaya çalışıyorum, buna değmez. Hepsi tek bir sınıfa / dosyaya ait, ancak hepsi aynı anda ekranıma ait değil.

Mesele şu ki #regions, kodunuzu ayırmak ve mantıksal olarak bölmek için kullanmanın her ne pahasına olursa olsun kaçınılması gereken kötü bir şey olmadığıdır. Ed'in işaret ettiği gibi "kod kokusu" değil. Kodunuz kokuyorsa, bölgelerden gelmediğinden, bunun yerine o bölgelere gömmeye çalıştığınız koddan emin olabilirsiniz. Bir özellik daha organize olmanıza veya daha iyi kod yazmanıza yardımcı oluyorsa, onu kullanın derim . Bir zararı olur, ya da kendinizi yanlış kullanmaya bulursanız, o zaman durmak kullanmaktan. En kötüsü en kötüye gelirse ve onu kullanan kişilerle bir ekip üzerinde çalışmaya zorlanırsanız, kod özetini kapatmak için klavye kısayolunu ezberleyin: Ctrl+ M, Ctrl+P. Ve şikayet etmeyi bırak. Bazen, bunun “gerçek”, “hardcore” programcılar olarak görülmek isteyenlerin kendilerini kanıtlamaya çalışmaktan hoşlandıklarının başka bir yolu olduğunu hissediyorum. Bölgelerden uzak durmakta, sözdizimi renklendirmesinden kaçındığınızdan daha iyi olamazsınız. Seni daha fazla maço geliştiricisi yapmaz.

Bunların hepsi söyleniyor, bir yöntem içindeki bölgeler tamamen saçma. Kendinizi bu şekilde yapmak istediğinizde bulduğunuzda, ayrı bir yöntemle yeniden düzenlemelisiniz. Bahane yok.


9
İyi dedi. Bölge için kuruluşların kullanımı, IDE'nin “boşlukları görüntüle” seçeneğini değiştirmekten daha zararlı değildir. Bu kişisel bir tercih.
Josh,

24
WPF üzerinde, sadece modelime özellik katan 10 veya 20 özelliğe sahip ViewModels ile çalışmak, bölgeleri seviyorum - Bu özellikleri bir bölgeden uzak tutabilirim (asla dokunulmaları gerekmez) ve gözlerimi ilgili kodda tutabilirim .
Kirk Broadhurst

4
Tamamen katılıyorum. .NET 2.0'da, özellikler yaklaşık 8-10 satır uzunluğundadır. Bir sınıfta 20'den fazla mülkünüz varsa, çok fazla yer kaplarlar. Bölgeler onları çökertmek için mükemmeldir.
Kristof Claes

6
@Kristof: .NET 4.0’da basit giriş doğrulaması yapan özellikler gibi. Otomatik özellikler sadece benim amaçlarım için o kadar büyülü olmadı.
Cody Gray

8
Sol topuma bahse girmeye istekliyim ki, bölgelerden nefret eden insanlar hiçbir zaman bir WPF uygulaması geliştirmediler ya da WPF'nin veri bağlama ve komut bağlama gibi işlevsellik tanımlamaları yapmadılar. Bu işi yapmak için kodunuzu ayarlamak çok fazla yer kaplar ve genellikle tekrar bakmak zorunda kalmazsınız.
l46kok

70

Öncelikle, artık "kod kokusu" terimine dayanamıyorum. Çok sık kullanılır ve ısrarsa iyi kodu tanıyamayan insanlar tarafından atılan zamanın çoğudur. Neyse...

Şahsen pek çok bölge kullanmaktan hoşlanmıyorum. Koda girmeyi zorlaştırıyor ve kod ilgilendiğim şey. Ben çok sık bir şekilde dokunulması gerekmeyen büyük bir kod yığınına sahip olduğum bölgeleri seviyorum. Bunun dışında sadece yoluma giriyorlar ve "Özel Metotlar", "Genel Metotlar" gibi bölgeler beni deli ediyor. Çeşitliliğin yorumlarına benziyorlar i++ //increment i.

Ayrıca bölgelerin kullanımının gerçekten bir "kalıp karşıtı" olamayacağını da eklerdim, çünkü bu terim bir metin editörünün düzenini değil, program mantığını / tasarım kalıplarını tanımlamak için kullanılır. Bu özneldir; sizin için neyin işe yaradığını kullanın. Bölgeleri aşırı kullandığınızdan dolayı, bu durum anti-paternlerin ne olduğu ile ilgili olarak, sürdürülemez bir programla asla bitmeyeceksiniz. :)


2
Normalde kod kokusu yorumu için size oy vermem iyi olur ama bu durumda kesinlikle doğru. Kod dışı kod kokusu olamaz. 2!

7
Haha, "kod kokusu" teriminin tam olarak kullanılamayacağını söylemek istemem. Olabilir, ama bugünlerde o kadar çok atıldığını görüyorum ki, hemen tepkim, sadece sinir bozucu bir durumdur, özellikle de duyduklarını gerçekten eleştirmeden ya da eleştirel düşünmeden tekrar eden, sadece can sıkıcıdır. "Bir fonksiyondaki 5'ten fazla yerel değişken bir kod kokusudur" gibi ifadeler, o kişinin gerçekte ne kadar az deneyime sahip olduğunu gösterir.
Ed S.

13
Kod kokuları hakkındaki yorumunuzu anladığımdan emin değilim. Kod kokuları bir sorun olduğunu göstermez, sadece bir sorun olabilir.
Craig

7
Kod kokusu terimine dik dururken +1. Özel yöntemlerin kod kokusu olduğunu iddia eden bir yazı görünce bıktım. Ama genel olarak bölgeler için isteksizliğinize katılmıyorum. Kolayca dikkatim dağılıyor. Aslında eğer VS, bir seferde sadece tek bir yöntem gösterebileceğiniz bir VB4 moduna sahipse çok isterim.
Josh

7
Sadece içeri girmek ve mükemmel derecede iyi bir metaforun kötüye kullanılması metaforu değersizleştirmemelidir. "Kod kokusu", anında anlaşılan, kolayca hatırlanabilen ve kolay kullanılan harika bir metafordur. "Kod kokusu" metaforunu uygulamak, bir noktaya değinmenin en iyi yolu olduğu hala birçok yer var.
Eric King

23

Evet bölgeler kod kokusudur!

Derleyiciden tamamen kaldırılmış bölgeleri görmekten mutlu olurum. Her geliştirici, asla başka bir programcı için asla değerli olmayacak kendi anlamsız tımar şemasıyla gelir. Bebeği dekore etmek ve güzelleştirmek isteyen programcılarla yapacak her şeyim var, gerçek değeri olan hiçbir şey.

"Tanrım, keşke meslektaşım burada bazı bölgeleri kullansaydı!"

IDE'mi tüm bölgeleri otomatik olarak genişletecek şekilde ayarlayabilsem de hala göze hitap ediyorlar ve gerçek kodu okuyorlar.

Tüm kamu yöntemlerimin bir araya getirilip getirilmemesi daha az önemserdim. Tebrikler, değişken bildirimi ve ilklendirme arasındaki farkı biliyorsunuz, kodda göstermenize gerek yok!

Değerli tımar!

Ek olarak, eğer dosyalarınız gerekiyorsa ve bölgeleri kullanarak 'bilgi mimarisi' varsa, ana problemle mücadele etmek isteyebilirsiniz: Sınıfınız çok büyük! Küçük parçalara bölmek çok daha faydalıdır ve doğru yapıldığında gerçek anlamsallık / okunabilirlik ekler.


# Bölgeleri derleyicinin bir parçası mı? Onların IDE’nin göz ardı edilebilecekleri bir yönerge olduğunu düşündüm.
Steve Rukuts,

2
C # kodunuzu ayrıştırırken derleyicinin bunları yoksayması gerekir. Onları görmezden gelmezse, onları atar. Öyle demek istiyorum.
Joppe

1
“Nerede olduğunuzu bir örnek düşünebilir misiniz?” Tanrım, keşke meslektaşım burada bazı bölgeleri kullansaydı! ”?” Evet, çok öyle. Özel yöntemlere ve genel yöntemlere sahip bir sınıfım olduğunda, bölgelere göre ayırırım çünkü genel yöntemlere yeniden bakarken, mutlaka özel koda ve tam tersine dokunmanız gerekmez.
Anshul

Açıkça hiçbir zaman dış kaynaklı kod görmedin. Sooo birçok kez bölgeler dış kaynaklı kodda görmek harika olurdu. Kod berbat olsa da, en azından mantıklı bir şekilde grup halinde olup olmadığını anlamak daha kolay olurdu. Kodları mantıksal bir ihtimal olmasa da bölgeler de olmazdı, muhtemelen daha da kötüleşecekti. Bölgeler düzgün kullanıldığında mükemmeldir.
Nickmccomb

15

Bölgeleri kişisel olarak çeşitli yöntem türlerini veya kod bölümlerini birlikte gruplamak için kullanıyorum.

Yani bir kod dosyası açıldığında şöyle görünebilir:

  • Genel Mülkler
  • Kurucular
  • Yöntemleri Kaydet
  • Yöntemleri Düzenle
  • Özel Yardımcı Yöntemler

Metotların içine bölgeler koymuyorum. IMHO bu bir kod kokusu işaretidir. Bir zamanlar 1200'den fazla çizgiden oluşan bir yöntemle karşılaştım ve içinde 5 farklı bölge vardı. Korkutucu bir manzaraydı!

Kodunuzu, diğer aygıtlar için işleri daha hızlı bulmayacak şekilde düzenlemenin bir yolu olarak kullanıyorsanız, bunun bir sorun belirtisi olduğunu sanmıyorum. Bir yöntemin içindeki kod satırlarını gizlemek için kullanıyorsanız, bu yöntemi yeniden düşünmenin zamanı geldiğini söyleyebilirim.


14
Ugh. Bunun öznel bir konu olduğunu biliyorum, ama dostum, bu şemaya dayanamıyorum. Tecrübelerime göre, eklenen 'organizasyon' hiç yardımcı olmuyor ve sadece koda göz atmayı boynundan acı çekiyor. Ayrıca sadece erişim değiştiriciyle değil aynı zamanda mantıksal sorumlulukla da gruplama yöntemlerini tercih ediyorum. Genel arayüz için, tipik olarak, her bir metodu / özelliği birlikte gruplandırmakla birlikte, çoğu zaman korunan bir metodun özel bir yardımcı fonksiyon çağrısı yapabileceği ve bu durumda, yardımcı fonksiyonun (sadece orada kullanılabilecek), cihazın üstünde veya altında olmasını tercih ederim. çağıran yöntem.
Ed S.,

3
@ Ed S. - bu yüzden "benzeyebilir" dedim. Bu çok özneldir. Her dosyanın böyle görünmesi gerektiğini söylemiyorum. Olsalardı şaşırırdım. Karmaşık bir konu üzerine sadece bir örnek. :)
Tyanna

Oh, dediğim gibi; özneldir. Sizin için / ekibiniz için ne işe yararsa. Sadece bu şema için hazırladım çünkü işe yaramadı (benim için), fakat tam da bunu yapan bir proje sürdürmek zorunda kaldım. Bu beni deli etti.
Ed S. 23

3
@EdS. Öyleyse, vs seçeneklerinize gidin ve bölgeleri kapatın. Sorun çözüldü.
Andy

Nesnelerin neden kaydetme yöntemleri var? :(
TheCatWhisperer 17:17

10

#regionÇok büyük bir sınıfı okunaklı kılmak için bloklar kullanmak tipik olarak Tek Sorumluluk İlkesini ihlal etmenin bir işaretidir. Davranışı gruplandırmak için kullanılıyorlarsa, o zaman sınıfın da çok fazla işi yapması muhtemeldir (bir kez daha SRP'yi ihlal ediyor).

"Kod kokusu" düşünce çizgisine sadık kalarak, #regionbloklar kod kodlarının kendileri için değil, daha çok kokuları gizlemeye çalıştıkları "kod için Febreze" olurlar. Bunları geçmişte bir ton kullandım, yeniden toparlanmaya başladığınızda daha az görmeye başlarsınız çünkü sonunda çok fazla saklanmayacaklar.


5

Buradaki anahtar kelime "mantıklı" dır. Bir bölgeyi bir yönteme koymanın mantıklı olduğu bir durumu hayal etmek zor; Hepsi kod gizleme ve tembellik olma ihtimalinin çok yüksek. Bununla birlikte, burada ve orada bir kişinin kodunda birkaç bölgeye sahip olmak için iyi nedenler olabilir.

Çok fazla bölge varsa, bunun bir kod kokusu olduğunu düşünüyorum. Bölgeler çoğu zaman gelecekteki refactoring için olası bir yerde ipucudur. Birçok bölge, birisinin aslında hiç ipucu almadığı anlamına gelir.

Akıllıca kullanıldıklarında, birçok yöntemle tek bir sınıfın yapısı ile her birinde yalnızca birkaç yöntemle birçok sınıfın yapısı arasında iyi bir orta yol oluştururlar. Bir sınıf birden fazla sınıfa yeniden yerleştirilmesi gereken noktaya yaklaşmaya başladığında çok faydalıdır, ancak henüz tam olarak orada değildir. İlgili yöntemleri birlikte gruplayarak, sayıları artmaya devam ederse, bir dizi ilgili yöntemi kendi sınıflarına çıkarmayı daha kolay hale getiririm. Örneğin, 500 satırlık kod satırına yaklaşan bir sınıfım varsa, bir bölgede bir araya toplanan toplam 200 satırlık kod kullanan bir dizi yöntem muhtemelen bir şekilde refaktör için iyi bir parçadır - ve bu bölgedeki 100 satırlık kodlu diğer bölge yöntemler de iyi bir hedef olabilir.

Bölgeleri kullanmaktan hoşlandığım bir diğer yol da, büyük bir yöntemin yeniden yapılandırılmasının olumsuz etkilerinden birini azaltmaktır: Bir okuyucunun çoğunlukla ilgisiz başka bir yönteme ulaşmak için kaydırması gereken çok sayıda küçük, kısa, kolayca kullanılan yöntem. Bir bölge, bir yöntemi ve okuyucular için yardımcılarını meta-kapsüllemek için iyi bir yol olabilir, bu nedenle sınıfın farklı bir yönüyle çalışan bir kişi bunları daraltabilir ve kodun bu bölümünü hızlı bir şekilde kaldırabilir. Tabii ki, bu yalnızca bölgeleriniz gerçekten iyi organize edilmişse ve temel olarak kodunuzu belgelemek için başka bir yol olarak kullanılıyorsa işe yarar.

Genel olarak, bölgeleri kendimi organize tutmama, kodumu "belgelememe" yardım et ve bölgeleri kullanmadığımdan çok daha kısa sürede yeniden ateşlenecek yerleri yakalamama yardım ettim.


4

Genellikle çeşitli işlem türlerini düzenlemek için CRUD sunucusu sınıfları için bölgeler kullanıyorum. O zaman bile memnuniyetle onlarsız gidebiliyordum.

Yaygın olarak kullanılırsa, bir kırmızı bayrak yükseltir. Çok fazla sorumluluğu olan dersleri aramak isterim.

Tecrübelerime göre yüzlerce satırdan oluşan bir kod bir koddur.


4

Temel kuralm şudur: Bir dosyada 5'den fazla bölgeniz varsa, bu bir kod kokusu

Başka bir deyişle, alanı, yöntemleri, özellikleri ve yapıcıları tanımlamak iyi olabilir, ancak diğer tüm yöntemleri kendi bölgelerinde sarmaya başlıyorsanız, bir şeylerin ciddi şekilde yanlıştır.

..ve evet, çoğu zaman kötü kodlama standartları, kod üretimi veya her ikisi için de olsa, durumun olduğu birçok projede bulundum. Kodun iyi bir genel bakışını elde etmek için görsel stüdyosunda tüm ana hatları açıp kapamaya gerek kalmaz.


4

BÖLGELER KULLANIMI VARDIR

Bunları kişisel olarak "el kodlaması" arayüz olayları için Windows uygulamaları oluşturmadan önce kullandım.

Ancak işimde SQL'i işlemek için bir kod üreteci kullanıyoruz ve otomatik olarak seçim, güncelleme, silme, vb. Yöntem türlerini sıralamak için bölgeleri kullanıyor.

Bu yüzden onları sık kullanmasam da, büyük kod parçalarını silmek için gayet iyi.


1
Benzer kod üreteçleri kullandım ve üretilen kodu çıkarmak için kısmi sınıfları kullanmayı tercih ediyorum.
Craig

Yaparız, bölgeler okumayı veya hata ayıklamayı kolaylaştırmak için (gerekirse) oluşturulan kodun içindedir.
Ken

4

Eğer bölgeler varsa İÇİNDE kod kesinlikle bir sorun (üretilen kod davayı engelleme.) Temelde söylediği kodunda bölgeleri koyarak var "bu planı ayrı."

Ancak, başka durumlar da var. Bir süre önce yaptığımı aklıma gelen bir tane: İçinde birkaç bin önceden hesaplanmış eşya bulunan bir masa. Bu bir geometri tanımlamasıdır, tablodaki bir hatanın kısa olması, asla ona bakmak için bir fırsat olamaz. Elbette, verileri bir kaynaktan veya benzeri bir şeyden elde etmiş olabilirdim ancak bu, derleyicinin okunmasını kolaylaştırmak için kullanılmasını engelleyecekti.


1
Bu, ayrı bir dosyada saklanan kısmi bir sınıf veya HardcodedDataSource uygulamasıyla birlikte enjekte edilmiş bir IMyDataSource için daha iyi bir kullanım durumudur.
Bryan Boettcher

3

Yeni bir projede, içine gömülmüş çeşitli bölgelere sahip 1700 hat yöntemi vardı. İlginç olan, bölgelerin bu yöntemde yapılan farklı eylemleri engellemesidir. Kodun işlevselliğini etkilemeden bölgelerin her birinde bir refactor -> özü yöntemi yapabildim.

Genel olarak, kazan plaka kodunu gizlemek için kullanılan bölgeler kullanışlıdır. Özellikleri, alanları ve benzerlerini gizlemek için bölgeleri kullanmamalarını öneririm çünkü sınıf içinde çalışırken bakmaya çok hevessizlerse, muhtemelen sınıfın daha da bozulması gerektiğinin bir işareti. Ancak zor bir kural olarak, bir yöntemi bir bölgeye koyuyorsanız, bir bloğu bir bölgeye sarmaktan başka bir yöntemi çıkarmaktan büyük olasılıkla daha iyi olursunuz.


3

İyi kalitede olan kodlarda bölgeler kullanılabilir mi? Muhtemelen. Eminim onlar, çoğu durumda. Ancak, kişisel deneyimim beni çok şüpheli kılıyor - bölgeleri neredeyse tamamen kötüye kullandıklarını gördüm. Yorulduğumu söyleyebilirim ama yine de iyimserim.

Bugüne kadar gördüğüm bölge kodunu kabaca üç kategoriye ayırabilirim:

  • Zayıf faktörlü kod: Gördüğüm kodların çoğu bölgeleri fakir bir erkek faktoring aracı olarak kullanıyor. Örneğin, farklı amaçlar için uzmanlaşmanın anlamlı olduğu noktaya ulaşan bir sınıf, bunun yerine her bir amaç için ayrı ayrı bölgelere ayrılabilir.

  • Sorunlu alan için yanlış kitaplıklar ve bazen de yanlış dil kullanılarak yazılmış kod Genellikle, bir programcı sorunlu alan için doğru kitaplık kümesini kullanmadığında, kodun inanılmaz derecede ayrıntılı olduğunu göreceksiniz - çok sayıda küçük yardımcı işlev ki bunlar gerçekten ait değil (muhtemelen kendi kütüphanelerine aitler).

  • Öğrenciler veya yeni mezunlar tarafından yazılmış kod. Bazı programlar ve kurslar, öğrencileri her türlü tuhaf amaç için bölgelerin kullanılmasına teşvik etmeye çalışıyor. Bölge kodunu bölge etiketlerinin kod satırlarına oranının 1: 5 ya da daha kötü olduğu noktaya kadar sürükleyen bölgeleri göreceksiniz.


3

Bunun bir "kod kokusu" olduğunu söyleyebilirim.

Anti-paternler genellikle bir yazılımdaki temel yapısal problemlerdir, oysa bölgeler kendi başlarına bir editörde iğrenç bir davranışa neden olurlar. Bölgeleri kullanmak aslında doğası gereği kötü değildir, ancak onları çok kullanmak, özellikle de kod parçalarını gizlemek için başka yerlerde olan başka, bağımsız ve daha büyük sorunların olduğunu gösterebilir.


@Andrew Grimm: evet
whatsisname

3

Bölgeleri yalnızca bir şey için kullanıyorum (en azından onları kullandığım diğer yerleri düşünemiyorum): bir yöntem için birim testlerini gruplamak için.

Genelde sınıf başına bir test sınıfım var ve daha sonra metodun adını taşıyan bölgeleri kullanarak her bir metot için birim testlerini gruplandırıyorum. Bunun bir kod kokusu ya da başka bir şey olup olmadığından emin değilim, ancak temel fikir, koddaki bir şey değiştiği için kırılmadıkça ünite testlerinin değişmesi gerekmediğinden, belirli bir yöntem için tüm testleri bulmamı kolaylaştırıyor. oldukça hızlı.

Geçmişte kod düzenlemek için bölgeler kullanmış olabilirim, ancak son yaptığım zamanı hatırlayamıyorum. Bölgelerime birim test derslerinde bağlı kaldım.


1
Hiç birden fazla yöntemi test eden testleriniz oldu mu?
Marcie

Soruyu ya da neyi hedeflediğinizi gerçekten anlamıyorum. Cevap: Hayır, bir birim testi daima bir yöntem veya bir yöntemin belli bir yönünü hedef alır.
Anne Schuessler

2

Bunun bir anti model olduğuna ve açıkça ortadan kaldırılmaları gerektiğine inanıyorum. Ancak, standart olmayan bir yerde çalışmanın talihsiz durumundaysanız, Visual Studio, nefret ettiğim bir bölgeyi her gördüğünüzde kusmak istediğiniz miktarı en aza indirmek için harika bir araç sunar.

Bu eklenti, bölgelerin yazı tipi boyutunu gerçekten küçük tutacaktır. Ayrıca genişletilecektir, böylece tüm bölgeleri açmak için ctr + m + l tuşlarına basmanız gerekmez. Bu kod kanseri türünü düzeltir, ancak katlanılabilir hale getirir.


0

Her görünürlük ve üye türü kombinasyonunu içerecek bölgeleri kullanıyorum. Böylece tüm özel fonksiyonlar bir bölgeye girer.

Bunu yapmamın nedeni kodu katlayabilmem değil. Editörümün kodlanmış olması ve proxy referansı ekleyebilmemin nedeni:

#region "private_static_members"
 /// <summary>
 /// cache for LauncherProxy
 /// </summary>
private static LauncherProxy _launcherProxy;
#endregion

#region "protected_const_properties"
protected LauncherProxy LauncherProxy{
  get{
    if(_launcherProxy==null) {
      if (!God.Iam.HasProxy(LauncherProxy.NAME)) {
        God.Iam.RegisterProxy(new LauncherProxy());
      }
      _launcherProxy=God.Iam.Proxy(LauncherProxy.NAME) as LauncherProxy;
    }
    return _launcherProxy;
  }
}
#endregion

Kodun içine girin ve her parçanın düzgün bir şekilde uygun bölgeye yerleştirilmesini sağlayın.

Bu durumda makro projemi analiz eder, bana bir proxy listesi kutusu verir ve istediğim kodun kodunu enjekte eder. İmlecim hareket etmiyor bile.

Öğrenmenin başlangıcında, C # ortaklığın bir arada tutulması için bölgelerin kullanıldığını düşünmüştüm, ancak bu her zaman bire bir ilişki olmadığından isabetli ve ısrarlı bir teklif. İki bölge tarafından kullanılan bir üyeye üzülmek, hatta bu şartlardan ayrılmaya başlamak isteyen.

Diğer tek ayırım türü yöntemlerdir - Yöntemleri Komutlar, İşlevler ve İşleyicilere ayıracağım, bu yüzden halka açık, özel vb Komutlar vb. İçin bir bölgem olacaktı.

Bu bana tanecikliği veriyor, ancak güvendiğim tutarlı, kesin taneciklik.


-1 oy kullanmaya başladığımda 125 puan alır almaz. Gereksiz kod satırları ekliyorsunuz. NEDEN NEDEN Niçin bir mülkün etrafına bir bölge koyacaksınız ... eğer (God.Iam.AbusingRegions () == true) myName = "Mark"
DeadlyChambers

1
@DeadlyChambers Sebep ikinci paragrafta belirtildi - Dosyaya ortak kod desenlerini enjekte etmek için editör makrolarını kullanıyorum, bölgeler yapılandırılmış dosyayı benzer şekilde gruplandırmaya yardımcı olur. Tekil bir mülkün etrafına bir bölge koymuyorum, ancak tüm mülkler "tanımlı_const_properties" özelliklerine bağlı olarak belirlenmiş bir bölgeye giriyor. Yazıyı okudun mu ??
Mark

1
Muhtemelen bu içine yeniden düzenleyebilirsin: korumalı LauncherProxy LauncherProxy => God.Iam.GetOrAddProxy <LauncherProxy> (ref _launcherProxy); ve böylece artık bölgeye ihtiyacınız yok. Ayrıca _launcherProxy, _launcherProxyCache olarak yeniden adlandırılabilir, böylece bölgeye veya yorum yapmaya gerek kalmaz.
aeroson

0

Bölgeler önişlemci ifadeleridir - başka bir deyişle yorum gibi değerlendirilir ve temel olarak derleyici tarafından yoksayılır. Tamamen Visual Studio'da kullanılan görsel bir araçtır. Bu nedenle # bölge gerçekten bir kod kokusu değil, çünkü sadece kod değil. Kod kokusu, daha çok içerisine gömülmüş birçok farklı sorumluluğa sahip olan 800 çizgi yöntemidir. Dolayısıyla, bir yöntemde 10 bölge görürseniz - muhtemelen bir kod kokusunu gizlemek için kullanılır. Onları çok daha iyi yazılmış ve yapılandırılmış bir sınıfta göze daha hoş ve gezilebilir hale getirecek bir sınıfı yapmak için çok etkili kullandıklarını gördüm.


0

Bölgeler çok şık bir organizasyon fikriydi, ancak her gün aşırı sınıflandırma yapmak isteyen bazı geliştirici eğilimleri dikkate almadılar, ve çoğu günümüz OOP uygulamalarına göre genellikle gereksizdiler ... Sınıfınızın / yönteminizin çok büyük olması ve yeniden katlanması gerektiği, çünkü SOLID ilkelerinin “S” sini ihlal etmeniz muhtemeldir ... ancak herhangi bir koku gibi, mutlaka bir şeyin kötüye gittiği anlamına gelmez.

Bölgeler, nesne yönelimli kod yerine işlevsel kodda daha fazla amaca hizmet eder, IMO, sıralı verilerin uzun işlevlerinin olduğu, ayrılmasının anlamlı olduğu, ancak bunları kişisel olarak c # 'da kullandığım zamanlar oldu ve neredeyse her zaman Kodlamak için odaklanmanıza gerek yok / bakmak istemezsiniz. Benim için bunlar genellikle NPoco veya değişkenleri için kullanılan kod tabanında ham SQL string sabitleriydi. Verilerin POCO nesnesini ORM'nizden doldurma konusunda gerçekten nasıl bir anlam verdiğinize dikkat etmiyorsanız, bunlar bakmak için tamamen anlamsızdı ... ve umursuyorsanız, hey, sadece bölgeyi ve BAM'ı genişletin ! İzleme zevkiniz için 150'den fazla satır karışık SQL sorgusu.

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.