İç kapsam bloklarının bir işlev içinde kullanılması kötü bir stil midir?


10

Aşağıdakilerin riski olan bazı (oldukça nadir) durumlar vardır:

  • yeniden kullanılması amaçlanmayan bir değişkeni yeniden kullanmak (bakınız örnek 1),

  • veya semantik olarak başka bir değişken yerine bir değişken kullanmak (bkz. örnek 2).

Örnek 1:

var data = this.InitializeData();
if (this.IsConsistent(data, this.state))
{
    this.ETL.Process(data); // Alters original data in a way it couldn't be used any longer.
}

// ...

foreach (var flow in data.Flows)
{
    // This shouldn't happen: given that ETL possibly altered the contents of `data`, it is
    // not longer reliable to use `data.Flows`.
}

Örnek 2:

var userSettingsFile = SettingsFiles.LoadForUser();
var appSettingsFile = SettingsFiles.LoadForApp();

if (someCondition)
{
    userSettingsFile.Destroy();
}

userSettingsFile.ParseAndApply(); // There is a mistake here: `userSettingsFile` was maybe
                                  // destroyed. It's `appSettingsFile` which should have
                                  // been used instead.

Bu risk bir kapsam getirilerek hafifletilebilir:

Örnek 1:

// There is no `foreach`, `if` or anything like this before `{`.

{
    var data = this.InitializeData();
    if (this.IsConsistent(data, this.state))
    {
        this.ETL.Process(data);
    }
}

// ...

// A few lines later, we can't use `data.Flows`, because it doesn't exist in this scope.

Örnek 2:

{
    var userSettingsFile = SettingsFiles.LoadForUser();

    if (someCondition)
    {
        userSettingsFile.Destroy();
    }
}

{
    var appSettingsFile = SettingsFiles.LoadForApp();

    // `userSettingsFile` is out of scope. There is no risk to use it instead of
    // `appSettingsFile`.
}

Yanlış görünüyor mu? Böyle bir sözdiziminden kaçınır mısınız? Yeni başlayanlar tarafından anlaşılması zor mu?


7
Her bağımsız "kapsam bloğunun" kendi yöntemi veya işlevi olması gerektiğini söyleyebilir misiniz?
Dan Pichelman

"Sık sık" olabildiğince iyi uygulanmamış (ama muhtemelen bir "tasarım" sorunu) söyleyebilirim. Bazen tasarım gereği kaçınılmazdır (örneğin istisna / kaynak kapsamı belirleme).
JustinC

Yanıtlar:


35

İşleviniz artık istenmeyen yan etkileri veya değişkenlerin yasadışı olarak yeniden kullanılmasını tanıyamayacak kadar uzunsa, daha küçük işlevlere bölme zamanıdır - bu da dahili bir kapsamı anlamsız hale getirir.

Bunu bazı kişisel deneyimlerle desteklemek için: birkaç yıl önce ~ 150K kod satırına sahip bir C ++ eski projesini miras aldım ve tam olarak bu tekniği kullanarak birkaç yöntem içeriyordu. Ve tahmin edin ne - tüm bu yöntemler çok uzun. Bu kodun çoğunu yeniden düzenlediğimizde, yöntemler gittikçe küçüldü ve artık "iç kapsam" yöntemi kalmadığından eminim; bunlara ihtiyaç yoktur.


4
Ama neden kötü? Birçok adlandırılmış işleve sahip olmak da kafa karıştırıcıdır.
Kris Van Bael

1
+1 Tam olarak, bir kapsama ihtiyacınız varsa, muhtemelen bir işleve çıkarılabilen belirli bir eylem gerçekleştiriyorsunuzdur . Kris, çok ve çok sayıda fonksiyon yaratmakla ilgili değil, bu durumlar meydana geldiğinde (bir bloğun kapsamı başka bir blokla çatışabileceği yerlerde) genellikle bir fonksiyonun kullanılması gerektiğidir. Bunu her zaman başka dillerde de (yani JavaScript, düz 'eski işlevler yerine IIFE'lerle) görüyorum.
Benjamin Gruenbaum

10
@KrisVanBael: "Birçok adlandırılmış işleve sahip olmak da kafa karıştırıcı" - açıklayıcı adlar kullanırsanız, tam tersi doğrudur. Çok büyük işlevler oluşturmak, kodun bakımının zorlaşmasının ve kapsamının zorlaşmasının en üst nedenidir.
Doc Brown

2
Onları belirgin bir şekilde isimlendirmek sorun olan çok fazla işlev varsa, muhtemelen bazıları orijinal işlev gövdelerinden önemli ölçüde bağımsız olduklarından yeni bir türe ayrılabilir. Bazıları ortadan kaldırılabilecek kadar yakın ilişkili olabilir. Aniden, çok fazla işlev yok.
JustinC

3
Hala ikna olmadım. Genellikle uzun fonksiyonlar kötüdür. Ancak her kapsam gereksiniminin ayrı bir işlev gerektirdiğini söylemek benim için çok siyah-beyaz.
Kris Van Bael

3

Yeni başlayanlar (ve herhangi bir programcı) için aşağıdakileri düşünmek çok daha kolaydır:

  • alakalı olmayan bir değişken kullanmamak

düşünmektense:

  • ilgili olmayan bir değişken kullanmamasını engellemeye yönelik kod yapıları eklemek.

Dahası, bir okuyucunun bakış açısından, bu tür blokların belirgin bir rolü yoktur: onları kaldırmanın yürütme üzerinde hiçbir etkisi yoktur. Okuyucu, kodlayıcının ne yapmak istediğini tahmin etmeye çalışırken başını kaşırabilir.


2

Bir kapsam kullanmak teknik olarak doğrudur. Ancak kodunuzu daha okunabilir hale getirmek istiyorsanız, o parçayı başka bir yöntemle ayıklamanız ve buna bir tam ad vermeniz gerekir. Bu şekilde değişkenlerinizin bir kapsamını verebilir ve görevinizin bir adını verebilirsiniz.


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.