Tamamen estetik nedenlerle iç içe işlevler mi oluşturuyorsunuz?


16

Her zaman başka programcıların saf estetik işlevler yaratma fikri hakkında ne düşündüklerini merak ettim.

Ben Veri yığınının işleyen bir işlevi olduğunu varsayalım: Function ProcessBigData. O veriler için geçerlidir, birkaç işlem adımlarını gerektiğini düşünün: Step1, Step2, Step3.

Kaynak kodda en çok gördüğüm normal yaklaşım, şöyle yorum yazmaktır:

Function ProcessBigData:
    # Does Step1
    Step1..
    Step1..

    #Does Step2
    Step2..
    Step2..

Genellikle yaptığım, ancak akranları tarafından böyle bir kodlama stilinin olmaması nedeniyle her zaman yanlış hissettim:

Function ProcessBigData:
    Function Step1:
        Step1..
        Step1..

    Function Step2:
        Step2..
        Step2..

    Step1() -> Step2()

Ben esas olarak Javascript ve Python bu tarz için herhangi bir dezavantaj varsa endişe duyuyorum

Görmediğim alternatifler var mı?


3
Python hakkında hiçbir şey söyleyemem, ancak Javascript için iç içe işlevler için bir performans maliyeti var: çoğu JavaScript motoru değişken kapsamı saymak için bağlantılı liste benzeri bir yapı kullanır. Ek bir fonksiyon katmanı eklemek, motoru değişkenleri çözerken muhtemelen daha uzun / daha büyük bir veri yapısını aramaya zorlar. Öte yandan, tüm kötülüğün kökü, elbette, erken optimizasyon. :)
Marco

Yanıtlar:


4

Düşündüğünüz kadar garip değil. Örneğin, Standart ML'de yardımcı işlevlerin kapsamını sınırlamak gelenekseldir. Verilen SML'nin bunu kolaylaştırmak için sözdizimi vardır:

local
    fun recursion_helper (iteration_variable, accumulator) =
        ... (* implementation goes here *)
in
    fun recursive_function (arg) = recursion_helper(arg, 0);
end

1) küçük fonksiyonların program hakkında akıl yürütmeyi kolaylaştırdığı ve 2) okuyucuya bu fonksiyonların bu kapsamın dışında kullanılmadığını bildirdiği göz önüne alındığında, bu iyi tarzı düşünürüm.

Dış fonksiyon çağrıldığında iç fonksiyonları oluşturmanın bazı ek yükleri olduğunu düşünüyorum (JS veya Python'un bunu optimize edip etmediğini bilmiyorum) ama erken optimizasyon hakkında ne söylediklerini biliyorsunuz.


11

Bunu mümkün olduğunda yapmak genellikle iyi bir şeydir, ancak bu tür işleri "adımlar" olarak değil, alt görevler olarak düşünmeyi seviyorum .

Belirli bir sorumluluğu vardır ve tanımlanmış girişi (ler) ve çıkış (lar) (düşünmek: Bir alt görev yapılabilir işin belli bir birimdir "S" in KATI ). Bir alt görevin yeniden kullanılabilir olmasına gerek yoktur: bazı insanlar "Bunu asla başka bir şeyden çağırmam gerekmeyecek, neden bir işlev olarak yazmalıyım?" ama bu bir yanılgıdır.

Ben de faydaları ve aynı zamanda sınıfta sadece başka bir işlev vs iç içe işlevler (kapaklar) için geçerli anlatmaya çalışacağız. Genel olarak konuşursak, özellikle bir ihtiyacınız olmadığı sürece kapanışları kullanmamanızı tavsiye ederim (birçok kullanım vardır, ancak kodu mantıksal parçalara ayırmak bunlardan biri değildir).

Okunabilirlik.

200'den fazla işlem kodu (bir fonksiyonun gövdesi) okunması zordur. 2-20 hat fonksiyonunun okunması kolaydır. Kod insanlar içindir.

Yuvalanmış olsun ya da olmasın, ana kapsamdan çok sayıda değişken kullanmadığınız sürece çoğunlukla okunabilirlik avantajından faydalanırsınız, bu durumda okunması da zor olabilir.

Değişken kapsamını sınırla

Başka bir işleve sahip olmak, sizi değişken kapsamı sınırlandırmaya ve özellikle ihtiyacınız olanı geçirmeye zorlar.

Bu genellikle kodun daha iyi yapılandırılmasını sağlar, çünkü daha önceki bir "adımdan" bir çeşit durum değişkenine ihtiyacınız varsa, aslında bu değeri elde etmek için önce yazılması ve çalıştırılması gereken başka bir alt görev olduğunu görebilirsiniz. Ya da başka bir deyişle, çok eşleşmiş kod parçaları yazmayı zorlaştırır.

İç içe işlevlere sahip olmak, iç içe işlevin (kapatma) içinden üst kapsamdaki değişkenlere erişmenizi sağlar. Bu çok yararlı olabilir, ancak işlevin yürütülmesi yazılı olarak gerçekleşmeyebileceğinden ince, bulunması zor hatalara da yol açabilir. Üst kapsamdaki değişkenleri değiştiriyorsanız, bu daha da fazladır (genellikle çok kötü bir fikir).

Birim testleri

Bir fonksiyonun (hatta bir sınıfın) uygulandığı her alt görev, bağımsız ve test edilebilir bir kod parçasıdır. Birim testi ve TDD'nin faydaları başka yerlerde iyi belgelenmiştir.

İç içe işlevlerin / kapakların kullanılması birim sınamasına izin vermez. Bana göre, bu bir anlaşma kırıcı ve özel bir kapatma gerekmediği sürece, sadece başka bir işlev yapmalısınız.

Takım üzerinde çalışma / Yukarıdan aşağıya tasarım

Alt görevler gerektiğinde bağımsız olarak farklı kişiler tarafından yazılabilir.

Kendiniz bile bile, ana işlevselliği oluştururken henüz var olmayan bazı alt görevleri çağırmak için kod yazarken yararlı olabilir ve alt görevi yalnızca bir anlamlı bir yol. Buna Yukarıdan Aşağıya tasarım / programlama da denir.

Kodun yeniden kullanımı

Tamam, daha önce söylediklerime rağmen, bazen daha sonra başka bir şey için bir alt görevi yeniden kullanmak için bir neden olur. Ben "mimarlık astronot" -izm hiç savunmuyorum ama sadece gevşek bir şekilde kod yazarak, daha sonra yeniden kullanım yararlanabilir.

Çoğunlukla bu yeniden kullanım, mükemmel bir şekilde beklenen bazı yeniden düzenleme anlamına gelir, ancak giriş parametrelerini küçük bir bağımsız işleve yeniden düzenlemek, yazıldıktan aylar sonra 200'den fazla satır işlevinden ayıklamaktan çok daha kolaydır;

Yuvalanmış bir işlev kullanırsanız, yeniden kullanmak genellikle ayrı bir işleve yeniden düzenleme meselesidir, yine, bu yüzden iç içe geçmenin yol olmadığını iddia ediyorum.


2
Bunlar genel olarak işlevleri kullanmak için gerçekten geçerli bazı noktalar, ancak NESTED işlevlerinin iyi bir fikir olduğunu düşünüyorsanız, cevabınızdan alamadım. Yoksa işlevleri yukarı akış kapsamına mı sokuyorsunuz?
Slytael

Üzgünüm iyi bir nokta, bu kısmı ele almayı unuttuğum diğer faydaları yakaladım. :) Düzenlendi.
gregmac
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.