“Karma” dillerde tasarım: nesne yönelimli tasarım mı, yoksa işlevsel programlama mı?


11

Son birkaç yıldır, kullanmak istediğim diller giderek daha "işlevsel" hale geliyor. Şimdi bir çeşit "melez" olan dilleri kullanıyorum: C #, F #, Scala. Uygulamamı etki alanı nesnelerine karşılık gelen sınıfları kullanarak tasarlamayı ve bunun kodlamayı daha kolay, daha çakışık ve daha güvenli hale getirdiği işlevsel özellikleri kullanmayı seviyorum (özellikle koleksiyonlarda veya işlevleri geçerken).

Ancak iki dünya tasarım desenlerine gelirken “çatışıyor”. Son zamanlarda karşılaştığım özel örnek, Gözlemci modelidir. Bir üreticinin, bir öğe oluşturulduğunda veya değiştirildiğinde başka bir kodu ("tüketiciler / gözlemciler", bir DB depolama alanı, bir kaydedici vb.) Bilgilendirmesini istiyorum.

Başlangıçta böyle "fonksiyonel" yaptı:

producer.foo(item => { updateItemInDb(item); insertLog(item) })
// calls the function passed as argument as an item is processed

Ama şimdi daha "OO" yaklaşımını kullanmam gerekip gerekmediğini merak ediyorum:

interface IItemObserver {
  onNotify(Item)
}
class DBObserver : IItemObserver ...
class LogObserver: IItemObserver ...

producer.addObserver(new DBObserver)
producer.addObserver(new LogObserver)
producer.foo() //calls observer in a loop

İki yaklaşımın yanlısı ve olumlu yanları nelerdir? Bir zamanlar bir FP guru'nun tasarım desenlerinin sadece dilin sınırlamaları nedeniyle olduğunu söylediğini duydum ve bu yüzden fonksiyonel dillerde çok az var. Belki bu bir örnek olabilir?

EDIT: Benim özel senaryoda ihtiyacım yok, ama .. fonksiyonel şekilde "gözlemci" kaldırma ve ekleme nasıl? (Yani kalıptaki tüm işlevsellikleri nasıl uygularsınız?) Mesela yeni bir fonksiyon mu geçiyorsunuz?


Aktörler ne olacak?
kiritsuku

Sınıfları ve OOPish yararsız şeyleri unutun. Bunun yerine modüller açısından düşünseniz iyi olur (ilham almak için SML ve OCaml dillerine bakın).
SK-logic

@Antoras Aktörlere dayalı bir yaklaşımla karşılaştırma yapabilseydiniz, o zaman daha hoş olurdu :)
Lorenzo Dematté

2
@ dema80, OCaml mükemmel bir çoklu paradigmadır. Modüller hiç fonksiyonel programlama ile ilgili değildir. Örneğin tamamen zorunlu bir Ada'da gelişmiş bir modül sistemi var. Ve kazanılan tüm şöhret OOP aslında modüllere gitmelidir - OOP'taki tüm iyi, modüllerin işlevselliğini simüle etmenin çeşitli biçimleridir. Tüm bu sınıfları unutabilirsiniz ve sözdizimlerini modül ifade etmek için kullanabilirsiniz, OOP yerine modüller açısından düşünebilirsiniz. Btw., Microsoft'un mscorlib ile yaptığı şey tam olarak bu - orada çok fazla OOP değil, sadece modüller ve ad alanları.
SK-logic

1
Bence daha iyi olan soru "FP yolu ile kaybettiğiniz herhangi bir açıklık veya organizasyon var mı?"
djechlin

Yanıtlar:


0

Bu, çağıran nesne için endişe sınırı dışında bir görevi yerine getirme kavramını taşıyan iki farklı yaklaşımın iyi bir örneğidir.

Bu örnekte fonksiyonel yaklaşıma gitmeniz gerektiği açık olmakla birlikte, genel olarak, çağrılan nesnenin sergilemesi gereken davranışın ne kadar karmaşık olduğuna bağlı olacaktır. Kendinizi sık sık benzer mantığı yeniden uyguladığınızı bulacağınız ve işlev üreteçleri açıkça ifade etmek için kullanılamadığı karmaşık bir davranış meselesiyse, muhtemelen sınıf kompozisyonuna veya mirasa gitmek isteyeceksiniz. mevcut davranışı geçici olarak yeniden kullanma ve genişletme konusunda biraz daha özgür olmalısınız.

Ancak gözlemlediğim bir model, genellikle geliştiricilerin başlangıçta fonksiyonel yaklaşıma gittikleri ve ancak daha ayrıntılı davranış talebi ortaya çıktığında, sınıf temelli bir yaklaşıma gitmeye karar verdikleridir. Mesela, Django'nun faydalar ve gereksinimler belirginleştikten sonra fonksiyon tabanlı görünümlerden, şablon yükleyicilerinden ve test koşucularından sınıf tabanlı olanlara gittiğini biliyorum, ancak bundan önce değil.


Bence bu cevap biraz yanlış yönlendirilmiş. Fonksiyonel programlama fonksiyonları (sadece ile) programlamaz. Fonksiyonel programlama da soyutlamaları kullanır, bu yüzden burada bir ikilik yoktur.
Doval

"mevcut davranışı yeniden kullanma ve genişletme özgürlüğünün daha fazla olacağı kompozisyon veya kalıtım" bu şekilde konuşuyorsunuz, saf FP'nin temel faydalarından biri DEĞİLDİR. modülerlik, kompoze edilebilirlik ve tekrar kullanılabilirlik fonksiyonel olarak kodladığınızda doğal olarak gerçekleşir, bu bir "OOP olayı" değildir
sara

@ FilipDupanović Mevcut kodun tekrar kullanılması ve genişletilmesi anlamına geliyordu. saf fonksiyonlar muhtemelen tüm programlamada en iyi kompoze edilebilir şeylerdir. saf işlevsel bir ortamda karmaşıklığı yönetemiyormuş gibi yazıyorsunuz. basit parçaları daha büyük ama yine de basit ve opak parçalara ayırarak karmaşıklığı yönetmek FP'nin tüm çekirdeğidir ve birçoğu bunun OOP'tan daha iyi olduğunu savunur. İleri sürdüğünüz "hiçbir sorun ölçeklendiren VS katı OOP ölçeklemeyen fonksiyonel tek gömlekler" arasındaki ikilemi kabul etmiyorum.
sara

kod oluşturma ve yeniden kullanma söz konusu olduğunda FP'nin daha düşük olduğunu ve uygulamalar daha karmaşık hale geldiğinde, OOP'nin her zaman "daha iyi" olacağını söylediniz. Bunun sadece yanlış ve yanıltıcı olduğunu iddia ediyorum ve bu yüzden bir aşağı oy gerektirdiğini düşündüm. Bu gerçekten "saflık zealotry" mi? Ancak bu gibi uzun tartışmalar için olmadığından, burada daha fazla tartışmayacağım.
sara

5

İşlevsel versiyon çok daha kısa, bakımı daha kolay, okunması daha kolay ve genellikle akla gelebilecek her açıdan büyük ölçüde üstündür.

Her ne kadar çoğu , her şeyden çok OOP'ta Gözlemciler gibi özelliklerin eksikliğini telafi etmek içindir. Bunlar fonksiyonel olarak çok daha iyi modellenmiştir.


Aynı fikirdeyim ve aynı fikirdeyim.
Lorenzo Dematté

Kabul ediyorum ve aynı duyguya sahibim.Ama işlevsel kodumla bir tür "aldatıyorum": benim durumumda ihtiyacım olan tek şey, ama "gözlemci" eklemek ve kaldırmak gerekirse ne olacak?
Sorumu

5

"FP gurunuz" kısmen haklıdır; Birçok OO paterni fonksiyonel şeyler yapmak için hack'tir. (Az sayıda FP dilinin bunun en iyi ihtimalle şüpheli göründüğünün nedeni olduğunu iddia ediyor.) Gözlemci ve Strateji kalıpları birinci sınıf işlevleri taklit etmeye çalışıyor. Ziyaretçi Deseni, desen eşleşmesini simüle etmek için bir hack'tir. Senin IItemObserversadece kılık değiştirmiş bir işlev. Bir öğeyi alan diğer herhangi bir işlevden farklı olduğunu iddia etmek size hiçbir şey satın almaz.

Nesneler sadece bir tür veri soyutlamasıdır. Bu makale bu konuya ışık tutmaya yardımcı olacaktır. Nesneler faydalı olabilir, ancak her şeye uygun olmadıklarını bilmek önemlidir. Bir ikilik yok; sadece doğru iş için doğru aracı seçme meselesidir ve hiçbir şekilde işlevsel programlama nesnelerden vazgeçmenizi gerektirmez. Bu bir yana, fonksiyonel programlama sadece fonksiyonları kullanmaktan daha fazlasıdır. Aynı zamanda yan etkileri ve mutasyonu en aza indirmekle de ilgilidir.


+1 (IMO) için iyi bir cevap. Ayrıca, makalenin bağlantısı için teşekkürler: Bir süre önce okudum ve kaybettim. Şimdi tekrar buldum.
Giorgio

-1

Soruyu gerçekten cevaplayamıyorum çünkü fonksiyonel dillerde iyi değilim; ama bence işe yarayan şey olduğu sürece yaklaşım konusunda daha az kaygılanmalısın. Anladığım kadarıyla, gelecekte daha fazla dinleyici eklemediğiniz veya yürütme sırasında dinleyicileri değiştirmediğiniz sürece, Gözlemci modelini burada çok iyi atlayabilirsiniz.

Tasarım modellerinin OO dillerinde "sınırlamaları" oluşturduğuna katılmıyorum. OOP özelliklerini iyi kullanmak için oradalar. Çok biçimlilik ve kalıtım sınırlama değil özelliklerdir. Tasarım desenleri, esnek tasarımı desteklemek için bu özelliklerden yararlanır. Bir OO'da kesinlikle OO olmayan bir program yapabilirsiniz. Çok dikkatli bir şekilde, durumu olmayan ve FP'yi taklit eden nesneler içeren bir programın tamamını yazabilirsiniz.


1
“Çok dikkatli bir şekilde, durumu olmayan, FP'yi taklit eden nesneler içeren bir programın tamamını yazabilirsiniz.” Ve disiplin yoluyla da zorunlu dillerde aynı şeyi yapabilirsiniz. :) Genel olarak, tasarım desenlerinde sınırlamaları telafi etmek için bir şey olarak düşünmüyorum, ancak Ziyaretçi deseninin durumunu düşünüyoruz ..
Lorenzo Dematté

Ayrıca, kodla ilgilenmiyorum: Bununla birlikte, yaklaşım konusunda diğer programcılarla yüzleşmek istiyorum (benim anlayışım için, bu programcılar.se bunun için, aksi takdirde
Q'yu SO'ya gönderirdim

Yinelenen bir deseni her gördüğünüzde, diliniz ve modelleme çerçevenizde ciddi bir sınırlamanın göstergesi değildir. İdeal bir dünyada hiçbir örüntü olmayacaktır.
SK-logic

@ SK-logic: Maalesef dünya ideal değil ve gerçek dünyanın desenleri var. Bu yüzden OO dillerinin mirası vardır, tekrar tekrar kodları tekrar yazmak zorunda kalmadan uygulamak. Gerçek dünya nesnesinin bir durumu vardır, bu yüzden bir Devlet modeli vardır
DPD

1
@ SK-logic: Bazı dillerin programlanabilir olduğunun ve bazılarının da tür sisteminden efektlerin uygulanmasına izin verdiğinin farkındayım. Demek istediğim, "OOP" gibi "örüntü" ne yazık ki yanlış anlaşılmış bir terimdir. Bir örüntü, benzer ancak farklı formlarda tekrar görünmeye devam eden, muntazam bir çözümü kabul etmeyen bir şeydir . Bazen bu quasirepetition'ları ortadan kaldırabilirsiniz - multimethods Ziyaretçi / çift gönderimi gereksiz hale getirir. Bu, "tüm örüntüler bir eksiklik belirtisidir" anlamına gelmez, çünkü bu gerçek dünyanın yetersiz olduğu anlamına gelir . Desenler yazılımdan değil mimariden kaynaklanır .
Frank Shearar
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.