FP olmayan insanlar tarafından az miktarda fonksiyonel programlama anlaşılabilir mi? [kapalı]


43

Durum : Bir şirkette çalışıyorum, Python'da bir dizi veri işleyen bir uygulama yazıyorum. Şu anda bu programın tek geliştiricisiyim, ancak gelecekte (1-3 yıl) başka bir programcı tarafından kullanılmaya / değiştirilmeye / genişletilmeye devam edecek, şu anda benim için bilinmiyor. Muhtemelen o zaman doğrudan yardım etmek için orada olamayacağım, ancak zamanım olursa e-posta yoluyla biraz destek verebilirim.

Bu yüzden, işlevsel programlamayı (Haskell) öğrenen bir geliştirici olarak, örneğin şöyle filtrelemeyi çözme eğilimindeyim:

filtered = filter(lambda item: included(item.time, dur), measures)

Kodun geri kalan kısmı OO, sadece bu şekilde çözmek istediğim bazı küçük durumlar, çünkü bana göre çok daha basit ve daha güzel.

Soru : Bugün böyle bir kod yazmak uygun mudur?

  • FP yazmamış / öğrenmemiş bir geliştirici böyle bir koda nasıl tepki verir?
  • Okunabilir mi
  • Değiştirilebilir?
  • Çocuğa, hattın ne yaptığını açıklamak gibi belgeler yazmalı mıyım?

     # Filter out the items from measures for which included(item.time, dur) != True

Patronuma sordum ve sadece "FP kara büyü, ama işe yararsa ve en verimli çözümse, o zaman kullanmalısın" diyor.

Bu konudaki fikriniz nedir? FP olmayan bir programcı olarak, koda nasıl tepki verirsiniz? Kod "googable" yani, ne yaptığını anlayabilmeniz için mi? Bu konuda geri bildirim almak isterim.


14
Bence pek çok modern dil, bir dereceye kadar işlevsel programlama yapılmasına izin veriyor ve bunu kullanmak gittikçe yaygınlaşıyor. Şahsen bunun için gitmek derdim (en azından nispeten basit filtreleme / haritalama görevleri için).
Joachim Sauer

Etkilenmemiş bir cevap veremem çünkü FP'yi severim. Basit olsa da, bir yorum eklemek için iyi bir fikir olurdu.
Bruno Schäpper

3
Yorumunuz daha açık olabilir; süzgeç, Testin Doğru olduğu öğeleri içerir, böylece yorumunuz okuyabilir: # Select the item's from measures for which included(item.time, dur) == Trueçift ​​negatif olmaktan kaçınmak her zaman anlayışı iyileştirir.
Martijn Pieters

6
Bunun yerine liste kavramalarını kullanmayı düşündünüz mü? Genellikle harita / filtreden daha "pitonik" olarak kabul edilirler.
phant0m

2
@MatjazMuhic Eh, bu güzel ...;)
kd35a

Yanıtlar:


50

Okunabilir mi

Benim için: Evet, ama şunu anladım ki, Python topluluğu sık sık liste kavramalarını map()/ kullanmaktan daha temiz bir çözüm olarak görüyor gibi görünüyor filter().

Aslında, GvR bile bu işlevleri bir bütün olarak bırakmayı düşündü .

Bunu düşün:

filtered = [item for item in measures if included(item.time, dur)]

Dahası, bunun bir liste kavrayışının her zaman bir liste döndürmesi avantajına sahiptir. map()ve filter()diğer taraftan Python 3'te bir yineleyici döndürür.

Not: Bunun yerine bir yineleyici sahip olmak istiyorsanız, bu değiştirme gibi basit olarak var []olan ():

filtered = (item for item in measures if included(item.time, dur))

Dürüst olmak gerekirse, kullanmak map()ya filter()da Python'da çok az sebep yok .

Değiştirilebilir mi?

Evet, elbette, bunu daha kolay kılacak bir şey var: Bir işlev yap, bir lambda değil.

def is_included(item):
    return included(item.time, dur)
filtered = filter(is_included, measures)
filtered = [item for item in measures if is_included(item)]

Durumunuz daha karmaşık hale gelirse, bu çok daha kolay ölçeklenir ve ayrıca kontrolünüzü yeniden kullanmanıza izin verir. (Diğer işlevlerin içinde işlevler oluşturabileceğinizi, bunun kullanıldığı yere daha yakın tutabileceğini unutmayın.)

FP yazmamış / öğrenmemiş bir geliştirici böyle bir koda nasıl tepki verir?

Python dokümantasyonuna göz atıyor ve beş dakika sonra nasıl çalıştığını biliyor. Aksi takdirde Python'da programlama yapmamalı.

map()ve filter()vardır son derece basit. Onlardan monadları anlamalarını istemediğin gibi değil. Bu yüzden böyle bir yorum yazmanıza gerek olmadığını düşünüyorum. İyi değişken ve işlev adları kullanın, ardından kod neredeyse kendi kendini açıklayıcıdır. Bir geliştiricinin hangi dil özelliklerini bilmediğini tahmin edemezsiniz. Bildiğiniz kadarıyla, bir sonraki geliştirici sözlüğün ne olduğunu bilmiyor olabilir.

Anlamadığımız şey genellikle bizim için okunamaz. Böylece, daha önce hiç görmemiş olmanız halinde, bir liste kavrayışından daha az okunaklı olmadığını iddia edebilirsiniz. Ancak Joshua'nın yorumunda da belirtildiği gibi, diğer geliştiricilerin kullandıklarıyla tutarlı olmanın önemli olduğuna inanıyorum - en azından alternatif önemli bir avantaj sağlamazsa.


5
Bu değer aynı zamanda söz olabilir jeneratör ifadeler olarak, liste comprehensions yerine listelerin dönüş jeneratörleri gibi çalışır, mapve filterpiton 3'te yapmak
James

@James: Harika bir fikir, yazıma ekledik. Teşekkürler!
phant0m

2
Genelde reducebir karşı-örnek olarak ortaya çıkarım, her zaman bir liste anlama argümanını kullanabilirsiniz , çünkü reducebir satır içi jeneratör veya liste anlama ile değiştirmek oldukça zordur .
kojiro

4
Söz konusu dilin tercih edilen deyimini belirtmek için +1. IMHO tutarlılığı muazzam bir değere sahiptir ve bir dili "konuşmacıların" önemli bir kısmının yaptığı gibi kullanma, zaman zaman yapılan yorumlardan bile daha fazla bakım sağlayabilir.
Joshua Drake

4
+1, "Python dokümantasyonu için googles ve beş dakika sonra nasıl çalıştığını biliyor. Aksi takdirde, Python'da programlama yapmamalı."
Bjarke Freund-Hansen

25

Geliştirici topluluğu, işlevsel programlamaya ilgi duyduğundan, başlangıçta tamamen nesne yönelimli olan dillerde bazı işlevsel programlar görmek sıra dışı değildir. İyi bir örnek, adsız türlerin ve lambda ifadelerinin işlevsel programlama yoluyla daha kısa ve anlamlı olmasını sağladığı C # 'dır.

Bu, fonksiyonel programlama, yeni başlayanlar için garip. Örneğin, bir eğitim kursu sırasında, yeni başlayanlara C # 'daki fonksiyonel programlama yoluyla kodlarını nasıl geliştirebileceklerini açıkladım, bazıları ikna olmamış ve bazıları da orijinal kodun kendileri için daha kolay olduğunu söyledi. Onlara verdiğim örnek şuydu:

Yeniden düzenleme işleminden önce kod:

var categorizedProducts = new Dictionary<string, List<Product>>();

// Get only enabled products, filtering the disabled ones, and group them by categories.
foreach (var product in this.Data.Products)
{
    if (product.IsEnabled)
    {
        if (!categorizedProducts.ContainsKey(product.Category))
        {
            // The category is missing. Create one.
            categorizedProducts.Add(product.Category, new List<Product>());
        }

        categorizedProducts[product.Category].Add(product);
    }
}

// Walk through the categories.
foreach (var productsInCategory in categorizedProducts)
{
    var minimumPrice = double.MaxValue;
    var maximumPrice = double.MinValue;

    // Walk through the products in a category to search for the maximum and minimum prices.
    foreach (var product in productsInCategory.Value)
    {
        if (product.Price < minimumPrice)
        {
            minimumPrice = product.Price;
        }

        if (product.Price > maximumPrice)
        {
            maximumPrice = product.Price;
        }
    }

    yield return new PricesPerCategory(category: productsInCategory.Key, minimum: minimumPrice, maximum: maximumPrice);
}

FP kullanarak refactoring sonrası aynı kod:

return this.Data.Products
    .Where(product => product.IsEnabled)
    .GroupBy(product => product.Category)
    .Select(productsInCategory => new PricesPerCategory(
              category: productsInCategory.Key, 
              minimum:  productsInCategory.Value.Min(product => product.Price), 
              maximum:  productsInCategory.Value.Max(product => product.Price))
    );

Bu beni düşündürdü:

  • Kodunuzu koruyacak bir sonraki geliştiricinin yeterince genel deneyime ve bazı fonksiyonel programlama bilgisine sahip olacağını biliyorsanız endişelenmemelisiniz:

  • Aksi takdirde, işlevsel programlamadan kaçının veya işlevsel olmayan bir programlama olana karşı yaklaşımınızın avantajlarını ve olası uyarılarını aynı anda açıklayan, ayrıntılı bir açıklama yapın.


8
+1, kodunuzu kimseyle daha okunaklı hale getirmezse , yanlış yapıyorsunuz demektir.
György Andrasek

7
İzolasyonda, daha önce hiç FP görmeyen birinin, eski snippet'in daha sonradan daha okunaklı olduğunu nasıl düşünebileceğini görebiliyorum. Ama ya bunu 100'le çarparsak? Neredeyse İngilizce benzeri cümlelerle anlatan 100 kısa ve öz Okuma neyi sıhhi tesisat hatları binlerce vs nasıl kodu. Ne kadar tanıdık olursanız olun, kodun saf hacmi, aşinalık artık o kadar büyük bir kazanç değil. Bir noktada, herkesin ilk önce FP unsurları ile rahat etmesi ve daha sonra binlerce tanıdık kod satırının okunması ile ilgili bir avuç satır okuyun.
Esailija

7
Beni en çok rahatsız eden şey, geliştiricilerin işlevsel stili öğrenmemenin kabul edilebilir olduğuna inanmamızdan memnun olduğumuzdur. Avantajları defalarca kanıtlanmış, paradigma ana dilleri tarafından desteklenmiştir. İnsanların işlevsel teknikleri anlama kabiliyetleri yoksa, kullanmayı düşünmese bile, kendilerine öğretilmeli veya öğretilmelidir. Yanan bir tutkuyla XSLT'den nefret ediyorum ama bu beni bir profesyonel olarak öğrenmemi engellemedi.
Sprague

2
@MainMa Amacınız tamamen geçerli, daha spesifik olmalıydım. Demek istediğim, herhangi bir dilde bir geliştiriciden bu dillerin özelliklerini etkili bir şekilde kullanması beklenir. Örneğin, C # 'da functional fonksiyonel stil' kullanmak (filtre / harita kullanmak / stil programlamayı azaltmak veya geçen / geri dönmek işlevlerini kullanmak) yeni bir şey değildir ve bu yüzden, bu tür ifadeleri okuyamayan herhangi bir C # geliştiricisinin güncellemeleri gerektiğini düşünüyorum. yetenekler ... muhtemelen çok hızlı. Her geliştiricinin biraz Haskell öğrenmesi gerektiğini düşünüyorum, ancak yalnızca akademik nedenlerden ötürü. Bu farklı bir şey.
Sprague

2
@Sprague: Ben senin fikrin olsun ve buna katılıyorum. Sadece, örneğin, C # programcılarının FP'den paradigmalar kullanmaya başlamasını beklemiyoruz, çünkü bu programcıların çoğu jenerik kullanmıyor bile. Çok fazla vasıfsız programcı bulununcaya kadar, mesleğimizin çıtası düşük olacaktır, çünkü özellikle teknik altyapıya sahip olmayan kişilerin gelişimi hakkında hiçbir şey anlamadıklarından.
Arseni Mourzenko

20

FP olmayan bir programcıyım ve son zamanlarda meslektaşımın kodunu JavaScript’te değiştirecektim. İçinde bulunduğunuz ifadeye çok benzeyen bir geri çağırma ile Http isteği yapıldı. Her şeyi anlamaya çalışmamın (kodun hepsi çok büyük olmadığı) biraz zaman aldığını söylemeliyim.

Yorum yapılmamış ve sanırım herhangi bir gereklilik yoktu. Meslektaşımdan kodunu anlamama yardım etmesini bile istemedim.

Yaklaşık 1,5 yıldır çalıştığımı dikkate alarak, programcıların çoğunun bu kodu anlayacağı ve değiştirebileceğini düşünüyorum.

Ayrıca, Joachim Sauer'in yorumunda dediği gibi, C # gibi birçok dilde FP parçaları vardır (örneğin indexOf). Pek çok FP olmayan programcı bununla çok sık ilgileniyor ve eklediğiniz kod pasajı korkunç veya anlaşılmaz bir şey değil.


1
Yorumun için teşekkürler! Bana diğer perspektif hakkında daha fazla bilgi verdi. Evde kör olmak kolay, ve sonra
FP'yi

1
@ kd35a, bir şey değil. Neyse ki, burada objektif olabilir))
superM

1
Artık birçok dilin FP öğelerini içerdiğini belirtmek için +1.
Joshua Drake

LINQ, C # 'daki ana FP örneğidir
Konrad Morawski

3

Kesinlikle evet derdim!

İşlevsel programlamanın birçok yönü vardır ve örneğinizde olduğu gibi üst düzey işlevler kullanmak bunlardan yalnızca biridir.

Örneğin, herhangi bir dilde yazılan herhangi bir yazılım için saf işlevler yazmanın son derece önemli olduğunu düşünüyorum (burada "saf" derken yan etki yok).

  • ünite testi için daha kolaylar
  • yan etkileyici işlevlerden çok daha fazla güçler
  • hata ayıklamak daha kolay

Sık sık, mutasyona uğramış değerleri ve değişkenleri de önlüyorum - FP'den ödünç alınan başka bir konsept.

Bu tekniklerin her ikisi de Python'da ve işlevsel olarak sınıflandırılmayan diğer dillerde iyi çalışır. Genellikle dilin kendisi tarafından bile desteklenirler (örn final. Java'daki değişkenler). Bu nedenle, gelecekteki bakım programcıları kodu anlama konusunda çok büyük bir engelle karşılaşmazlar.


2

Aynı tartışmayı geçen sene çalıştığım bir şirkette de yaptık.

Tartışma "sihirli kod" ile ilgiliydi ve teşvik edilip edilmemesi gerekiyordu. Buna biraz daha bakarken, insanların aslında "sihirli kod" olduğu konusunda çok farklı görüşleri olduğu görülüyordu. Tartışmayı ortaya çıkaranların, çoğunlukla işlevsel tarzı kullanan ifadelerin (PHP'de) "sihirli kod" olduğu, daha doğrusu kodlarında daha fazla FP stili kullanan diğer dillerden gelen geliştiricilerin, sihirli kodun daha ziyade olduğunu düşündüğü görülüyordu. dosya isimleri ve benzeri yollarla dosyaların dinamik olarak dahil edilmesini sağlayın.

Bu konuda hiçbir zaman iyi bir sonuca varmadık, insanlar çoğunlukla yabancı görünen kodun “büyülü” veya okunması zor olduğunu düşünüyor. Peki diğer kullanıcılara yabancı görünen kodlardan kaçınmak iyi bir fikir midir? Nerede kullanıldığına bağlı olduğunu düşünüyorum. Verilerin net ve okunması kolay, sezgisel bir şekilde tünel olması gereken bir ana yöntemde (veya uygulamaların önemli merkezi bölümlerinde) fp tarzı ifadeler (dinamik dosya ekleme vb.) Kullanmaktan kaçınırdım. Öte yandan, zarfı zorlamaktan korkması gerektiğini düşünmüyorum, diğer geliştiriciler FP kodu ile karşı karşıya kalırlarsa muhtemelen FP'yi hızlı bir şekilde öğrenecekler ve belki de bu konuda danışmak için bazı iyi kaynaklara sahip olacaklardır.

TL; DR: Uygulamaların orta seviyedeki bölümlerinden kaçının (uygulamanın işlevselliğine genel bir bakış için okunması gerekir). Aksi takdirde kullanın.


İyi bir nokta daha yüksek seviye kodda kullanmaktan kaçının!
kd35a

Her zaman, farklı blok türlerinde (statik yöntemler, kamu yöntemleri, inşaatçılar, vb.) Programlama tekniklerini tanımlamakta formalizm eksikliği ve çok fazla fırsat olduğunu düşündüm. Bu düşüncelerin.
Sprague

2

C ++ topluluğu geçtiğimiz günlerde lamda'nın da yanı sıra aynı soruyu yaptıklarına inanıyorum. Cevap olsa da aynı olmayabilir. C ++ eşdeğeri:

std::copy_if(measures.begin(), measures.end(), inserter(filter),
  [dur](Item i) { return included(i, dur) } );

Şimdi std::copyyeni değil ve _ifvaryantlar da yeni değil, ama lambda. Yine de bağlamda oldukça açık bir şekilde tanımlanmıştır: duryakalanır ve bu nedenle süreklidir, Item idöngüde değişir ve tek returnifade tüm işi yapar.

Bu, birçok C ++ geliştiricisi için kabul edilebilir görünüyor. Yine de, daha yüksek seviyeli lambda hakkında fikir almamıştım ve daha az kabul görmeyi beklerdim.


İlginç olan, hangi dilin olduğuna bağlı olarak farklı cevaplar olabileceğidir. Muhtemelen @Christopher Käck ile ilgili olarak PHP kodlayıcılarının Python kodlayıcılardan daha fazla bu tür problemlerle nasıl bir sorun yaşadıklarına dair yazdıkları hakkında.
kd35a

0

Python'da akıcı olmayan bir arkadaşınıza kod pasajı gönderin ve ona anlayıp anlamadığını görmek için kodu kontrol etmek için 5 dakika geçirip geçiremeyeceğini sorun.

Eğer evet ise, muhtemelen gitmekte iyisindir. Eğer değilse, daha net hale getirmeye bakmalısınız.

Meslektaşınız kaba olabilir ve açık olması gereken bir şeyi anlamaz mı? Evet, ama her zaman KISS uyarınca programlamalısınız.

Belki de kodunuz daha sade, salakça bir yaklaşımdan daha verimli / iyi görünümlü / zarif midir? O zaman kendine sorman gerekiyor: bunu yapmam gerekiyor mu? Yine, cevap hayır ise, o zaman yapma!

Bütün bunlardan sonra, hala FP yoluna ihtiyacınız olduğunu ve yapmak istediğinizi düşünüyorsanız, o zaman elbette yapın. İçgüdülerinize güvenin, ihtiyaçlarınız için herhangi bir forumdaki çoğu insandan daha uygundur :)


Olumsuz oylamanın nedenini açıklamaktan çekinmeyin
Arnab Datta
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.