Yazılım karmaşıklığını yönetmek için gerçekten OO dillerine ihtiyacımız var mı?


209

Bu teknik olmayan, yumuşak bir soru olacak ve bunun doğru platform olup olmadığından emin değilim. Ama ben yeni bir CS öğrencisiyim, umarım buna katlanabilirsiniz.

İlk dönemde kapsülleme, veri gizleme, modülerlik, kalıtım vb. OOP kavramlarını Java ve UML üzerinden tanıttık. (Java benim ilk programlama dilimdir)

Anladığım kadarıyla OOP, yazılım karmaşıklığını yönetmenin bir yoludur. Ancak prensipleri yeni ya da benzersiz değil, bir anlamda tüm mühendislik alanlarına evrensel.

Örneğin, bir araba, karmaşıklığı iyi tanımlanmış davranışlara ve arayüzlere sahip modüler ve kapsüllenmiş bileşenlerin hiyerarşisi tarafından yönetilen çok karmaşık bir yapıdır.

Ancak yeni bir programlama paradigması getirmenin nedenini anlamıyorum. Karmaşıklığın yönetiminde kullanılan tüm ilkelerin prosedürel programlama dilleri ile gerçekleştirilebileceğini düşünüyorum. Örneğin, modülerlik için programı, kodu ayrı dosyalarda bulunan iyi tanımlanmış görevleri gerçekleştiren birçok küçük programa ayırabiliriz. Bu programlar birbirleriyle iyi tanımlanmış girdi ve çıktıları ile etkileşime girer. Kapsülleme sağlamak için dosyalar korunabilir (şifrelenmiş mi?). Kodu tekrar kullanmak için, yeni programlarda gerektiğinde bu dosyaları çağırabiliriz. Bu, OOP'nin ne olduğunu yakalamıyor mu yoksa çok açık bir şeyi mi özlüyorum?

OOP'un karmaşıklığı yönettiğine dair bir kanıt istemiyorum. Bence kesinlikle öyle. Ancak modülerlik, kapsülleme, veri gizleme ve benzeri karmaşıklığı yönetmek için kullanılan tüm ilkelerin prosedürel diller tarafından kolayca uygulanabileceğini düşünüyorum. Öyleyse, karmaşıklığı onsuz yönetebiliyorsak neden gerçekten OOP?


41
Arayüz ve uygulamanın ayrılığını kaçırıyorsunuz. Çalışma zamanında bir uygulamayı diğerine takas edebilmek çok önemli bir özelliktir. Temel olarak, bu, OO dillerinin kalıtımsal olarak dinamik yöntemlerle gönderilmesiyle elde edilir. Usul dilleri de bunu yapabilir (okuma: boşluk işaretçiler), ancak tür güvenliği olmadan.
Marstato

81
Nesne yönelimli diller ve tasarım fikri, büyük ölçüde, bu evrensel, sezgisel kavramları kod içinde temsil etmek ve yeniden oluşturmak için mümkün olduğunca kolay hale getirmek içindir . Bütün bu şeyleri doğası gereği Nesne Yönelimli bir dil olmadan nasıl elde edeceğinize dair bir planınız veya bir kılavuzunuz varsa, o zaman işlerin nasıl yapılacağına dair önerileriniz etkili bir şekilde kullanılan Nesne Yönelimli metodoloji olacaktır. Gerçek OO dilleri sadece onu biçimlendirmenin ve basitleştirmenin bir yoludur.
Stand-

14
@RobbieDee aslında sorumu okudun mu? Yazılım karmaşıklığının OO olmadan yönetilebildiği hava durumunu sorgulayarak OO'yu daha temel bir düzeyde anlamaya çalışmakla ilgilidir. OO'yu baltalamaya çalışmıyorum, yeni bir şey icat etmeye çalışmıyorum, sadece daha iyi anlamaya çalışıyorum ve eğer soru o kadar açıksa, neden Jorg'dan mükemmel cevap aldı?
steakexchange

12
Bir dosyayı şifrelemek, kapsülleme değildir. Kodun içeriğini başka bir geliştiriciden görmeyi gizlemiş olabilirsiniz, ancak kodun iç işleyişini başka kodlardan korumanız gerekmez. Orijinal yazar bunu nasıl hatırlayabiliyorsa, şifrelemeden önce veya sonra yapabilir.
JeffO

8
Sen yok gerek makine diline ötesinde bir şey - programcısı opcodes ezberlemek ve birler ve sıfırlar kendisi yazalım. Ancak bir çeşit "sembolik" dilin olması, hataları azaltmak ve verimliliği arttırmak için çok faydalıdır ve Dijkstra'nın gözlemlediği gibi, bazı "yapı" ya da en azından "yapıyı korumayı kolaylaştıran" bir dil önemli ölçüde yardımcı olur. OO dilleri, mevcut dil karmaşıklığı seviyesi göz önüne alındığında ideal teknoloji olmayabilir, ancak birçok uygulama için oldukça iyidirler. Fikir, karmaşıklığı engellemeden yönetmektir.
Daniel R Hicks

Yanıtlar:


177

Gerçekten düşük bir teori cevabı ile deneyeyim :)

Gerçekten sormak istedikleriniz: OO kodunu tasarlamak ve yazmak için prosedürel diller kullanıldığında neden Nesne Yönlendirme (OO) dilini doğrudan o dilde destekliyorsunuz?

Ve cevap: OO'nun kaynak kodunda nasıl ifade edildiğine dair bir standarda sahip olmak, böylece aynı soyutlama için 22 farklı uygulamaya son vermemelisiniz.

Örneğin, bir kullanıcı arayüzü sisteminde kullanılabilecek bir MagicButtonve bir tane MagicSlideroluşturduğumu varsayalım. MagicButton ile kullanılabilecek yöntemleri, yalnızca MagicSlider ile kullanılabilecek yöntemleri ve her ikisi tarafından da kullanılabilecek yöntemleri gruplandırmam için bir yol gerekli. Bu nesneler bazı yöntemleri paylaşır, çünkü ikisi de Magic gui nesnesidir.

İşlevleri özel bir şekilde MagicSlider_DoSomething ...adlandırarak, özel bir şekilde adlandırılmış belirli dosyalara yöntemleri dahil ederek gruplamayı yapabilirim MagicSliderMethods.XXXveya aynı şeyi yapmak için başka bir özel yol bulabilirim. Dilde standart bir yol yoksa, onu sizden ve başkalarından farklı yapacağım. Bu, kod paylaşmayı çok daha zorlaştırır.

Evet, geç gönderme - OO dillerinde sanal yöntemler - prosedürel dillerde uygulanabilir, ancak bunu uygulamanın çok farklı yolları vardır. Kodu kimin yazdığına bağlı olarak, aynı programın içinde farklı OO uygulamaları olacaktır.

Kötü bakım geliştirici hakkında düşünün. Bu kişi, orijinal kodu kimin yazdığına bağlı olarak, farklı nesne soyutlamaları ve sanal yöntemleri çağırmanın farklı yollarını yönetmelidir.

Ayrıca: Dilde soyutlamalara sahip olmak, Eclipse gibi gelişmiş kod editörlerinin kod üzerinde çok fazla statik analiz yapmalarını sağlar. Örneğin Eclipse, boş "TODO yöntemlerinin" otomatik olarak uygulanmasının yanı sıra bir nesnede kullanılabilecek tüm yöntemlerin bir listesini sunabilir. Eclispe, hangi sınıfları genişlettiğinizi ve hangi arayüzleri uyguladığınızı temel alarak sınıfınızın hangi yöntemleri uygulaması gerektiğini bilir. OO yapmak için bir dil standardı olmasaydı bu neredeyse imkansız olurdu.


40
Klasik örnek: Lua. Doğal olarak OO değil, yapılabilir, ancak bu tamamen birlikte çalışamayan yaklaşık 5 farklı eşit derecede iyi bilinen OO kütüphanesi olduğu anlamına gelir.
Kroltan

55
@steakexchange Çok fazla mutlaklığa odaklanıyorsunuz. Çok azının tek bir amacı var. Dillerin hepsi farklı kalite derecelerinde birçok farklı şey yapar. Bir dil seçmek, ihtiyaç duyduğunuz amaç için en uygun hale getiren takas gruplarını seçmektir.
Tim B

42
@nocomprende Soyutlamaları standartlaştırmak, programlama dilleri için kullanılan anlamlıdır. Assembly dili bile bir on buçuk yıl boyunca on donanım nesli gibi bir şey arasındaki farklılıkları soyutlar.
David Moles,

56
@DavidMoles Standartlaştırılmış soyutlama olan anlamıyla programlama dilleri nelerdir. Kelimenin tam anlamıyla kelimenin tam anlamıyla kullanmak için mükemmel bir fırsat kaybetmeyin!
Clement Cherlin

12
Bunu standart hale getirmek mümkündür. 90'lı yılların ortalarında üniversitedeyken, X-Windows'ta oldukça fazla miktarda iş yaptım (çoğunlukla Motif'e dayanıyordu, böyle şeyleri hatırlayanlar için). X-Windows, nesne yöneliminin tüm özelliklerini normal C'de uygulamanıza izin verdi . Bunu yapmak için zihinsel jimnastik oldukça önemliydi ve ağır bir şekilde kutunun içine bakmayan insanlara güveniyordu (bu noktada Schroedinger'in Widget Kodu genellikle sona erdi). OO dilleri bunu kodlayıcılardan gizler, aynı şekilde düzenli bir derleyicinin montajcı için yaptığı gibi ve hayat da kolaydır.
Graham

211

İlk dönemde kapsülleme, veri gizleme, modülerlik, kalıtım vb. OOP kavramlarını Java ve UML üzerinden tanıttık. (Java benim ilk programlama dilimdir)

Bunların hiçbiri OOP kavramı değil. Hepsi OO dışında, OO'dan bağımsız olarak var ve birçoğu OO'dan önce icat edildi.

OO'nun bununla ilgili olduğunu düşünüyorsanız, sonucunuz doğrudur: Bunların hepsini işlemsel dillerde yapabilirsiniz çünkü onların OO ile ilgisi yoktur .

Örneğin, Modülerlik ile ilgili seminal makalelerden biri, Modüllere Ayrıştırma Sistemlerinde Kullanılacak Kriterler Üzerinedir . Orada OO'dan bahsetmiyoruz. (1972'de yazılmıştır, o zamana kadar OO, on yıldan daha eski olmasına rağmen hala belirsiz bir yerdi.)

Veri Soyutlama , OO'da önemli olmakla birlikte , OO'nun (Messaging) birincil özelliğinin, tanımlayıcı bir özellik olmaktan çok bir sonucudur . Ayrıca, farklı türde veri soyutlamalarının olduğunu hatırlamak çok önemlidir . Günümüzde kullanılan en yaygın iki veri soyutlama türü (muhtemelen hala birleştirilen diğer ikisinden daha fazla kullanılan "hiçbir şekilde soyutlama" görmezden gelirsek), Özet Veri Türleri ve Nesneleridir . Yani, sadece "Bilgi Gizleme", "Kapsülleme" ve "Veri Soyutlama" diyerek, OO hakkında hiçbir şey söylemediniz, çünkü OO sadece bir Veri Soyutlama biçimidir ve ikisi aslında temelde farklıdır:

  • Soyut Veri Tipleriyle, soyutlama mekanizması tip sistemidir ; Uygulamayı gizleyen tip sistemidir. (Tip sisteminin mutlaka statik olması gerekmez.) Nesnelerle, uygulama, tür gerektirmeyen bir prosedürel ara yüzün arkasına gizlenir . (Örneğin, ECMAScript'te olduğu gibi kapaklarla uygulanabilir.)
  • Özet Veri Türleriyle, farklı ADT örnekleri birbirinden kapsüllenir, ancak aynı ADT örnekleri birbirlerinin temsilini ve özel uygulamalarını inceleyebilir ve bunlara erişebilir. Nesneler her zaman her şeyden kapsüllenir . Sadece nesnenin kendisi kendi temsilini denetleyebilir ve kendi özel uygulamasına erişebilir. Başka hiçbir nesne , aynı tipteki diğer nesneler, aynı sınıfın diğer örnekleri, aynı prototip içeren diğer nesneler, nesnenin klonları veya ne yapabilirse yapılmadı. Yok .

Bunun anlamı, bu arada, Java'da sınıfların nesne yönelimli olmamasıdır. Aynı sınıfın iki örneği olabilir birbirlerinin temsilini ve özel uygulama erişin. Bu nedenle, sınıf örnekleri nesne değildir, aslında ADT örnekleridir. Java interfaces, ancak, do nesne yönelimli veri soyutlama sağlamak. Yani başka bir deyişle: sadece arayüzlerin örnekleri Java'daki nesnelerdir, sınıfların örnekleri değildir.

Temel olarak, tipler için sadece arayüzleri kullanabilirsiniz. Bunun anlamı, parametre türlerinin ve yapıcıların, geri dönüş yöntem türlerinin, örnek alan türlerinin, statik alanların ve yerel alanların, bir instanceofişlecin ya da bir işlecin argümanının ve genel bir tür kurucu için tür argümanlarının her zaman arayüz olması gerektiği anlamına gelir. Bir sınıf sadece newoperatörden hemen sonra, başka hiçbir yerde kullanılabilir.

Örneğin, modülerlik için programı, kodu ayrı dosyalarda bulunan iyi tanımlanmış görevleri gerçekleştiren birçok küçük programa ayırabiliriz. Bu programlar birbirleriyle iyi tanımlanmış girdi ve çıktıları ile etkileşime girer. Kapsülleme sağlamak için dosyalar korunabilir (şifrelenmiş mi?). Kodu tekrar kullanmak için, yeni programlarda gerektiğinde bu dosyaları çağırabiliriz. Bu, OOP'nin ne olduğunu yakalamıyor mu yoksa çok açık bir şeyi mi özlüyorum?

Tanımladığınız şey OO.

Bu gerçekten OO hakkında düşünmek için iyi bir yoldur. Aslında, OO'nun özgün mucitlerinin aklında olan şey tam olarak buydu. (Alan Kay bir adım daha ileri gitti: birbirlerine ağ üzerinden mesajlar gönderen çok sayıda küçük bilgisayar öngördü.) "Program" dediğiniz şeye genellikle "nesne" denir ve "çağrı" yerine "genellikle" ".

Nesne Oryantasyonu tamamen Mesajlaşma (aka dinamik gönderme ) ile ilgilidir. "Nesne Yönelimli" terimi, Smalltalk'ın ana tasarımcısı Dr. Alan Kay tarafından yazılmıştır ve şöyle tanımlamaktadır :

Bana göre OOP sadece mesajlaşma, yerel alıkoyma ve devlet sürecinin korunması ve saklanması ve her şeyin aşırı geç bağlanması demektir.

Şunu parçalayalım:

  • mesajlaşma ("sanal yöntem gönderme", Smalltalk'ı bilmiyorsanız)
  • devlet süreci olmalı
    • yerel olarak tutulan
    • korumalı
    • gizli
  • her şeyin aşırı geç bağlanması

Uygulama-bilgili, mesajlaşma bir geç sınırlanmış prosedür çağrısıdır ve prosedür çağrıları geç sınırlanmışsa, o zaman tasarım zamanında ne arayacağınızı bilemezsiniz , böylece devletin somut temsili hakkında herhangi bir varsayımda bulunamazsınız. Yani, bu gerçekten mesajlaşma ile ilgili, geç-bağlama mesajlaşma bir uygulama ve kapsülleme bunun bir sonucudur.

Daha sonra " Büyük fikir" mesajlaşma " olduğunu açıkladı ve" mesaj yönelimli "yerine" nesne yönelimli "olarak adlandırdığı için pişmanlık duydu, çünkü" nesne yönelimli "terimi önemsiz şeye odaklanıyor (nesneler) ) ve gerçekte önemli olanın dikkatini dağıtır (mesajlaşma):

Sadece küçük bir hatırlatmak için son OOPSLA'da bazı sıkıntıları çektiğimi hatırlatan bir hatırlatma, Smalltalk'un sadece sözdizimi ya da sınıf kütüphanesi değil, sınıflarla ilgili olmadığını da hatırlatmak için. Uzun zaman önce bu konu için "nesneler" terimini kullandığım için üzgünüm çünkü birçok insanın daha az fikre odaklanması gerekiyor.

Büyük fikir "mesajlaşma" dır - Smalltalk / Squeak'in çekirdeği tamamen budur (ve Xerox PARC fazımızda asla tamamlanmayan bir şeydir). Japonların küçük bir kelimesi var - "- bunlar arasında olan" - belki de en yakın İngilizce karşılığı "interstitial". Mükemmel ve büyütülebilir sistemler yapmanın anahtarı, modüllerinin iç özelliklerinin ve davranışlarının ne olması gerektiğinden ziyade nasıl iletişim kurduğunu tasarlamaktır. İnterneti düşünün - yaşamak, (a) tek bir standardın ötesinde birçok farklı türde düşünce ve gerçekleştirmeye izin vermek ve (b) bu ​​fikirler arasında farklı derecelerde güvenli birlikte çalışabilirlik sağlamak için izin vermek zorundadır.

(Tabii ki, bugün, çoğu insan nesnelere odaklanmıyor, hatta daha da yanlış olan sınıflara odaklanıyor.)

Mesajlaşma , hem metafor hem de mekanizma olarak OO için esastır .

Birine mesaj gönderirseniz, onunla ne yaptıklarını bilemezsiniz. Sadece sen gözlemleyebilirsiniz şey, onların yanıttır. Mesajı kendileri işleme alıp almadıklarını (yani nesnenin bir yöntemi olup olmadığını), mesajı başka birine iletip iletmediklerini (temsilci / vekil), bilmiyorlarsa bile bilmiyorsunuz. Kapsüllemenin konusu budur, OO'nun konusu budur. Bir vekili, beklediğiniz gibi yanıt verdiği sürece, gerçek olandan ayırt edemezsiniz.

"Mesajlaşma" için daha "modern" bir terim "dinamik yöntem gönderme" veya "sanal yöntem çağrısı" dır, ancak metaforu kaybeder ve mekanizmaya odaklanır.

Dolayısıyla, Alan Kay'ın tanımına bakmanın iki yolu vardır: eğer kendi başına ayakta durursanız, mesajlaşmanın temelde bir gecikme prosedürü çağrısı olduğunu ve geç bağlamanın kapsülleme anlamına geldiğini gözlemleyebilirsiniz; ve # 2 aslında gereksizdir ve OO tamamen geç bağlanma ile ilgilidir.

Ancak, daha sonra önemli olan şeyin mesajlaşma olduğunu ve böylece farklı bir açıdan bakabileceğimizi açıkladı: mesajlaşma geç kalmış. Şimdi, eğer mesajlaşma mümkün olan tek şey olsaydı, o zaman # 3 önemsiz bir şekilde doğru olurdu: eğer sadece bir şey varsa ve o şey geç bağlıysa, o zaman her şey geç kalmış olur. Ve bir kez daha, kapsülleme mesajlaşmadan sonra gelir.

Benzer noktaları da yapılır Revisited Veri Soyutlama, Anlama On tarafından William R. Cook da onun "Odaklı Nesne" "Nesne" ve basitleştirilmiş Modern Tanımlar önerisi :

İşlemlerin dinamik gönderilmesi nesnelerin temel özelliğidir. Çağrılacak olan işlem nesnenin kendisinin dinamik bir özelliği olduğu anlamına gelir. İşlemler statik olarak tanımlanamaz ve genel olarak, verilen bir talebe cevap olarak hangi işlemin gerçekleştirileceğini, çalıştırmanın dışında tam olarak bilmenin bir yolu yoktur. Bu, her zaman dinamik olarak gönderilen birinci sınıf işlevlerle aynıdır.

Smalltalk-72'de herhangi bir nesne bile yoktu! Yalnızca ayrıştırılan, yeniden yazılmış ve yönlendirilen ileti akışları vardı . İlk olarak yöntemler (mesaj akışlarını ayrıştırma ve yeniden yönlendirmenin standart yolları), daha sonra nesneler (bazı özel durumları paylaşan yöntemlerin grupları) geldi. Miras çok daha sonra geldi ve sınıflar sadece mirası desteklemenin bir yolu olarak tanıtıldı. Kay'ın araştırma grubu prototipler hakkında zaten bilgi sahibi olsaydı, muhtemelen ilk etapta asla ders vermezlerdi.

Türler ve Programlama Dillerinde Benjamin Pierce , Nesne Yöneliminin belirleyici özelliğinin Açık Özyineleme olduğunu savunuyor .

Yani: Alan Kay'a göre, OO tamamen mesajlaşma ile ilgili. William Cook'a göre, OO tamamen dinamik yöntem gönderimi ile ilgilidir (bu gerçekten aynı şeydir). Benjamin Pierce'e göre, OO tamamen Açık Recursion ile ilgilidir, bu temel olarak öz referansların dinamik olarak çözüldüğü (veya en azından düşünmenin bir yolu) veya başka bir deyişle mesajlaşma anlamına gelir.

Gördüğünüz gibi, "OO" terimini kullanan kişi nesneler üzerinde oldukça metafizik bir görünüme sahip, Cook oldukça pratik bir görünüme sahip ve Pierce çok sıkı bir matematiksel görünüme sahip. Ancak önemli olan şudur: filozof, pragmatist ve teorisyen hepsi aynı fikirde! Mesajlaşma, OO'nun bir ayağıdır. Dönemi.

Burada miras söz konusu değil! Kalıtım, OO için zorunlu değildir. Genel olarak, çoğu OO dili yeniden kullanımın bir yolunu kullanmaktadır, ancak bunun mutlaka miras olması gerekmemektedir. Örneğin, bir tür delegasyon da olabilir. Aslında, Orlando Antlaşması tartışır heyeti nesne oiented dillerin tasarım alanı içinde farklı tasarım noktalarına heyeti ve miras kurşun formları veraset ve ne kadar farklı alternatif olarak. (Aslında Java gibi kalıtımı destekleyen dillerde bile, insanlara aslında OO için gerekli olmadığını belirten, bundan kaçınmaları gerektiğini öğretilmektedir.)


16
+100 - Biz yanlış şeyler kullandıkları için doğal suçlamalar yaptık.
JeffO

55
Üzgünüz, ama bu inanılmaz derecede yanlış. Alan Kay terimi ile gelmiş olabilir, ancak ilkeler Smalltalk önce etrafında idi. Nesneye yönelik programlama Simula'dan türemiştir ve OO stilinin "mesajlar" ile hiçbir ilgisi yoktur. Başarılı olan her OO dili, Simula'da ortaya konan temel ilkeleri (Java'da gördüğümüzle aynı) ve Smalltalk tarzı OO, her yeniden tanıtıldığında "fikir piyasasında" bir başarısızlık oldu. çünkü hiç iyi çalışmıyor. Adı, Kay'ın katkıda bulunduğu tek gerçek anlamlı şeydi.
Mason Wheeler

23
@steakexchange No. "OO'nun özü", onu gerçekten ayırt edici kılan şey, sanal yöntemlere sahip nesnelerdir. Hiç kimsenin Smalltalk kullanmamasının bir nedeni var: Mesajlaşma sistemi bireysel bilgisayar ölçeklerinde çok zayıf çalışıyor. Bazı iyi niyetli ama naif bir dil tasarımcısı, Smalltalk ilkelerini yeniden uygulamaya çalıştığında, başarısızlıkla sonuçlanır. (En son örnek, Steve Jobs onu iOS topluluğunun boğazına sokmasaydı, hiç kimsenin kullanmayacağı Objective-C olurdu. Apple ekosisteminin dışında hiçbir çekiş bulamadı ve bunun bir nedeni yoktu.). )
Mason Wheeler

28
@MasonWheeler Jorg'un söylediklerinin tam tersi bir bakış açısına sahip olduğunuzdan, yorumunuzu bir cevapta açıklayabilir misiniz?
steakexchange

20
Nesneye yönelik diller kavramının çok geliştiğini not etmek de önemlidir. Bu atalara ait kavramlar, bugünlerde eski modelleri çukurlayan ve çoklu paradigmaları benimseyen birçok dilde geçerli olmayabilir. Örneğin, C # 'a bakın - bu dilin neredeyse güneşin altındaki her şeyi bir kerede karıştırması ve çoğunlukla OO dili olarak adlandırılması, aslında farklı paradigmaların bir karışımıdır. Bu, tüm geliştiriciler için gerçekten etkileyici bir araç olmasını sağlar. Ayrıca, Sınıf Tabanlı OO, OO programlamanın eşit derecede geçerli tatlarından biridir.
T. Sar

66

Ancak modülerlik, kapsülleme, veri gizleme ve benzeri karmaşıklığı yönetmek için kullanılan tüm ilkelerin prosedürel diller tarafından kolayca uygulanabileceğini düşünüyorum.

"Çok kolay" derken çok cesur bir ifade veriyorsun. Okuduğum yol şu: "Zorluğu göremiyorum, bu yüzden çok büyük olmamalıdır." Bu şekilde ifade edildiğinde, “neden OO'ya ihtiyacımız var” diye sormadığınızı, “neden OO'nun icat edilmesine yol açan diğer programlama paradigmalarının karşılaştığı zorluklar olmadığını” soruyorsunuz. "

Bu sorunun cevabı, üzerinde çalıştığınız program türlerinde bu zorlukların çoğunun mevcut olmadığıdır. 40 yıllık spagetti kodunu güncellemeniz istenmiyor. İşletim sistemi için yeni bir ekran yöneticisi yazmayı denemiyorsunuz. Çok iş parçacıklı dağıtılmış uygulamalarda hata ayıklamıyorsunuz.

CS öğrencilerine yazma konusunda görevlendirdiğimiz birçok oyuncak programı türü için, onları BASIC ya da mecliste Java ya da Python olarak da yazabiliriz. Bunun nedeni, görevlerin içsel karmaşıklığının çok düşük olması, yalnızca bir geliştirici olması, eski bir birlikte çalışabilirlik sorunu olmaması, performansın önemli olmaması ve kodun yalnızca bir makinede yalnızca birkaç kez çalıştırılmasıdır.

Öğrenci şoföre bindiğini ve yoğun saatlerde yoğun bir caddede, senkromeçsiz manuel bir şanzıman üzerinde dik bir tepeye çıkmalarını istediklerini hayal edin. Afet. Neden? Görevin gerektirdiği tüm kuralları aynı anda takip etmek için gereken karmaşıklık seviyesini yönetemezler.

Şimdi aynı öğrenciyi, aynı aracı, boş bir otoparkta yürüme hızında sürdüğünüzü hayal edin. Tamamlar, çünkü yetenek seviyeleri görev için yeterli. Baskı yok, çok az risk var ve her seferinde bir başkasının, kavrama, vites değiştirme, hızlanma, yönlendirme alt görevlerini alabilirler.

Bu öğrenci, yetenekli bir sürücü bütün bunları aynı anda yapabiliyorsa neden otomatik şanzımanımız olduğunu sorabilir? Cevap, yeteri kadar yetenekli bir sürücünün, optimal koşullarda otomatik bir sisteme ihtiyaç duymamasıdır. Ancak, en iyi durumda olan tüm profesyonel sürücüler değiliz ve genellikle otomobil tasarımcılarının bizim için tüm bu karmaşıklığı gözetmesini sağlamanın rahatlığını istiyoruz.

Yetenekli, yeterince disipline sahip bir programcı gerçekten de C veya mecliste işleyen bir yüksek karmaşıklık sistemi yaratabilir. Ama hepimiz Linus Torvalds değiliz. Ne de faydalı bir yazılım oluşturmak için olmamız gerekmemeli.

Elimizdeki sorunu çözmeden önce modern bir dilin tüm özelliklerini yeniden icat etmekle şahsen ilgilenmiyorum. Çözülmüş sorunlara çözüm içeren bir dilden faydalanabilirsem neden olmasın?

Öyleyse sorunuzu tersine çevireceğim ve dillerin kapsülleme ve polimorfizm gibi uygun özellikler sağlayıp sağlamadığını soracağım, neden bunları kullanmamalıyız?


13
Dolayısıyla, temelde OO'yu bir prosedür diliyle yapmak mümkündür, ancak standartlaştırılmış bir OO dili kullanırken işleri manuel olarak yapan, otomatikleştiren ve basitleştiren bir işlemdir.
steakexchange

6
@steakexchange Neredeyse tam olarak bu.
Tim B,

3
@steakexchange bunun güzel bir tarihsel örneği, günümüzde X Windows için nesne modeliydi. C ile yazılmış ancak nesne yönelimli bir sisteme dayanıyordu. Bu yüzden, onunla etkileşimde bulunmak için belirli sözleşmeleri takip etmek zorunda kaldın, böylece sınıflarınız herkesinkilerle iyi oynayacaktı.
Ukko

7
@nocomprende Kesinlikle. Ama bir olabilir yazıyor ham diski yapıyor yerine dosya sistemi güvenerek unbootable kişinin bilgisayarı işlemek ve orada olacak bir acemi tarafından yaptırılan bir ad-hoc nesne sisteminde hatalarını ayıklamak için gerçekten zor. Enkapsülasyon, doğru yapıldığında, bizi kasıtlı olarak veya istemeyerek karıştırmamamız gereken şeylere karışmaktan alıkoyuyor.
Clement Cherlin

3
OO'dan fayda sağlayacak uygulamalara verdiğiniz örneklerin genellikle OO dillerinde yazılmaması ilginçtir. 40 yaşındaki spagetti muhtemelen C, COBOL, FORTRAN veya REXX dilinde yazılmıştır. Ekran yöneticisi büyük olasılıkla C (OO-ish sözleşmelerine rağmen) da yazılmıştır ve birçok başarılı dağıtılmış okuyuculu sistemler Erlang, Go veya C olarak yazılmıştır
James_pic

22

Tarif ettiğiniz şey OOP değil, soyutlama. Soyutlama, tüm modern tasarım modellerinde, OOP olmayan modellerde mevcuttur. Ve OOP çok özel bir soyutlama türüdür.

Öncelikle, tek bir OOP tanımı olmadığını belirtmekte fayda var, bu yüzden OOP olarak nitelendirdiğim şeye katılmıyor olabilir.

İkincisi, OOP'un geleneksel tasarım modellerinden ilham aldığını hatırlamak önemlidir, bu nedenle araba tasarımına benzerlikler tesadüf değildir.

Ancak, işte OOP söylediklerinizden daha farklı olmasının bazı yolları:

  • Kapsülleme: Bu sadece bir modül için ayarlanmış bir arayüze sahip olmakla ilgili değildir (soyutlama), bu arayüzün ötesine erişimi yasaklamakla ilgilidir. Java'da, özel bir değişkene erişmek bir derleme hatasıdır, oysa araç tasarımınızda (bazı durumlarda) şeyleri istenen arayüzden farklı bir şekilde kullanabilirsiniz.

  • Kalıtım: Bu gerçekten OOP'u benzersiz yapan şeydir. Bir arabirim tanımladıktan sonra, bu arabirimi uygulayan birden çok şey yapabilir ve bunları önceki tüm parçaları devralarak , uygulamalarının belirli bölümlerini değiştirerek , önceki tüm parçaları devralarak kod çoğaltmasını büyük ölçüde azaltarak yapabilirsiniz.

    Bir arabanın kapsüllenmiş bileşenleri açısından düşünürseniz, bunun gerçekten bir karşılığı yoktur. Farklı bir dişli alarak ve uygulamasının belirli bir parçasını değiştirerek dişli yapmamın bir yolu yok. (En azından öyle düşünmüyorum, arabalar hakkında fazla bir şey bilmiyorum).

  • Polimorfizm : Bir arayüzü tanımladıktan sonra, bu arayüzü kullanan herhangi bir şey, hangi işlemlerin kullanılabilir olduğuna göre ayırt edilemez olmalı ve bir arayüzü kullanmak için hangi uygulamanın kullanıldığını bilmeniz gerekmez. Bu, subtyping ve Liskov Değiştirme Prensibi'nin önem kazandığı yerdir .

  • Eşleştirme : OOP'nin temel bir yönü, şeyleri aynı işlemlerle yakından ilişkilendirmemiz ve sahip olabilecekleri farklı biçimleri yaymamızdır. Veriler, bu verilerdeki işlemlerle birlikte gelir. Bu, yeni bir veri biçimi (yeni bir uygulama) eklemenin çok kolay olduğu, ancak bir arabirime yeni bir işlem eklemenin çok zor olduğu (arabirimi uygulayan her sınıfı güncellemeniz gerekeceği) anlamına gelir. Bu, yeni bir işlem eklemenin çok kolay olduğu (sadece tüm durumlarla ilgilenen bir işlev yazdığınız) işlevsel dillerdeki Cebirsel Veri Türlerinin aksine, ancak yeni bir değişken eklemek zor (yeni bir tane eklemeniz gerektiğinden tüm işlevlerinize göre).


1
İyi cevap! Kabul etmediğim bir kısım: kapsülleme hakkında çizdiğiniz ayrım geçerli değil. Kapsülleme her zaman "bu arabirimin ötesinde erişimi yasaklamak" anlamına gelir - bu, hem OOP hem de OOP olmayan ayarlar için geçerlidir. Yani bu kısım gerçekten OOP'a özgü bir şey değil.
DW

@DW, OOP'a özgü olmadığını, kapsülleme ve soyutlama arasındaki fark olduğunu söyleyerek bunu açıklamaya çalıştım. Geri dönüşünüz için teşekkür ederiz!
jmite

2
TAMAM. Ama yine de bu konuda ne yazdığı hakkında farklı görüşlerim var. "İşte, OOP'nin söylediklerinizden daha farklı olduğu yollarını" yazdınız, ancak kapsülleme, OOP'un soruda yazıldığından daha farklı bir yol olmadığını gösteriyor. Kapsülleme, herhangi bir paradigmada olduğu gibidir. Ve "Açıkladığınız şey OOP değil, soyutlamadır" yazdığını yazdığınız yerde, asıl sorunun kapsüllemeyi (sadece soyutlamayı değil) tanımlamaya çalıştığını düşündüm. Sanırım bu yorumu farklı bir bakış açısı olarak bırakacağım. Cevabın çok faydalı olduğunu düşünüyorum!
DW

Kalıtım ortak bir özelliktir, ancak birkaç önemli OO dili bu konuda eksiktir.
Bradd Szonye

İyi cevap, ama IMO araba örneğini aştınız. Belirli bir model için bir motor iyi tanımlanmış bir arayüze (kam mili, montaj braketi "yuvalar", vb.) Sahiptir. Sen, bir yakıt enjeksiyonlu biriyle düz eski karbüratör yerine bir turbo şarj vs. ekleyebilir olmadan iletimini etkileyen. (Her ne kadar bir dizel motorun IIRC'de modifiye edilmiş bir yakıt deposuna ihtiyacı olsa da.) Bunun tersine, manuel şanzımanı motoru hiç etkilemeyen otomatik ve AFAIK ile değiştirebilirsiniz.
David

11

Yazılım karmaşıklığını yönetmek için gerçekten OO dillerine ihtiyacımız var mı?

Bu, "ihtiyaç" kelimesinin anlamına bağlıdır.

"İhtiyaç" gerektiren anlamına gelirse, hayır bunu istemeyiz.

"İhtiyaç", "güçlü faydalar sağlar" anlamına gelirse, "Evet" derim, arzuluyoruz.

Büyük fotoğraf

OO dilleri işlevselliği verilere bağlar.

Bu bağlamayı önleyebilir ve veri değerlerinin etrafından geçen fonksiyonları yazabilirsiniz.

Ama sonra muhtemelen bir araya gelen veri takımyıldızları ile başlayacaksınız ve veri dosyalarının, kayıtların veya sözlüklerin etrafından dolaşmaya başlayacaksınız.

Ve aslında, tüm yöntem çağrıları şöyle: sınırlı veri kümelerinde kısmi fonksiyonlar.

Özelliğe göre özellik

OOP Özellikleri:

  • Kalıtım , kodun (karışımların) ve konseptin (Soyut Temel Sınıflar / arayüzler) yeniden kullanılmasına izin verir - ancak bunu, işlevleri ve değişkenleri bir alt kapsamda yeniden dekore ederek elde edebilirsiniz.
  • Kapsülleme bilgi gizlemeye izin verir, böylece daha yüksek soyutlama seviyelerinde çalışabiliriz - ancak bunu başlık dosyaları, işlevler ve modüller ile yapabilirsiniz.
  • Polimorfizm , bu argümanlar aynı arayüzleri desteklediği sürece farklı türlerdeki argümanları kullanmamızı sağlar - ancak bunu fonksiyonlarla da yapabiliriz.

Ancak, bu özelliklerin hiçbiri, birinci sınıf desteği bu özellikleri desteklemeyen nesne yönelimli bir dilde olduğu kadar kolay olmuyor.

Referanslar

Çok fazla OOP eleştirmeni var .

Bununla birlikte, çalışmalar OOP aracılığıyla kodun yeniden kullanılmasından daha fazla programcı üretkenliği aldığımızı gösteriyor gibi görünüyor. Bu tartışmalı bir bulgu ve bazı araştırmacılar bu kısıtlamaları göz önünde bulundurarak bu verimlilik artışlarını üretemediklerini söylüyor. (kaynak)

Sonuç

OOP'a "ihtiyacımız" yok. Ancak bazı durumlarda kullanıcı OOP'yi ister .

Anladığım kadarıyla olgun programcılar nesne yönelimli tarzda oldukça üretken olabilirler. Paketler kolay anlaşılan basit arayüzlere sahip çekirdek nesnelere sahip olduğunda, yeni programcılar bile hızlı bir şekilde oldukça verimli olabilirler.


10

Kısa olmaya çalışacağım.

OO'nun temel ilkesi, tek bir organizasyonel birimdeki (bir nesne) veri ve davranış kombinasyonudur.

Bu, karmaşıklığı kontrol etmemize izin veren şeydi ve ortaya çıktığında oldukça yenilikçi bir kavramdı. Bunu bir eldeki dosyalarla (saf veri), diğer yandan bu dosyaları okuyan ve işleyen programlar (saf mantık) ve çıktı (tekrar saf veri) ile karşılaştırın.

Ancak bu gerçek veri paketini ve mantığı bir araya getirdikten sonra, bazı gerçek dünya varlıklarını modelleyerek mesaj alışverişine başlayabilir, çocuk sınıfları oluşturabilir, kamuya açık verilerden ve davranışlardan özel olarak ayırabilir, polimorfik davranışlar uygulayabilir, tüm bu OO'ya özgü sihri yapabilirsiniz.

Yani, evet, OO önemli bir şey. Ve hayır, süslü bir ismi olan sadece bir sürü eski şey değil.

Hepsini parçalara ayırmak, öğelere bakmak ve sonra "ah, daha önce burada hiç görmediğim bir şey yok" diyerek yeniliği barındıran montajı tanımıyor. Sonuç, parçalarının toplamından daha fazlasıdır.


8

Nesne yönelimli programlamanın “resmi” bir tanımı yoktur ve makul kişiler OO'nun kalitesini tanımlayan şey konusunda hemfikir değildir. Bazıları mesajlaşma, bazıları ise alt yazma, bazıları ise kalıtım, bazıları veri ve davranış demeti diyor. Bu, terimin anlamsız olduğu anlamına gelmez, sadece gerçek OO'nun ne olduğu konusunda kafa yormayacaksınız .

Kapsülleme ve modülerlik tasarımın daha temel ilkeleridir ve tüm programlama paradigmalarında uygulanmalıdır. OO'nun savunucuları, bu özelliklerin yalnızca OO ile elde edilebileceğini iddia etmiyor - sadece OO'nun bunu başarmak için özellikle uygun olduğunu. Elbette, işlevsel programlama diyelim ki diğer paradigmaların savunucuları paradigmaları için aynı iddiada bulunurlar. Uygulamada birçok başarılı dil çoklu paradigmadır ve OO, işlevsel vb. "Gerçek yol" yerine araç olarak görülmelidir.

Karmaşıklığın yönetiminde kullanılan tüm ilkelerin prosedürel programlama dilleri ile gerçekleştirilebileceğini düşünüyorum.

Doğru, çünkü sonunda herhangi bir programlama dilinde her şeyi yapabilirsiniz. Bazı dillerde diğerlerinden daha kolay olabilir, çünkü tüm dillerin farklı güçlü ve zayıf yönleri vardır.


7

Diğer cevapların bahsetmediği bir şey: devlet.

Karmaşıklığı yönetmek için bir araç olarak OO hakkında konuşuyorsunuz . Karmaşıklık nedir? Bu bulanık bir terim. Hepimiz ne anlama geldiğine dair bu gestalt anlayışına sahibiz, ancak onu tespit etmek daha zor. Döngüsel karmaşıklığı, yani kod boyunca çalışma zamanı yollarının sayısını ölçebiliriz, ancak karmaşıklığı yönetmek için OO kullandığımız zaman bunun hakkında konuştuğumuzu bilmiyorum.

Ne düşünüyorum bahsettiğimizi devlet ile ilgili karmaşıklığı.

Kapsüllemenin arkasında iki ana fikir var . Bunlardan biri, uygulama detaylarını gizleme , diğer cevaplarda oldukça iyi ele alınmıştır. Ama bir diğeri çalışma zamanı durumunu saklıyor . Nesnelerin iç verileriyle uğraşmıyoruz; mesajları iletiriz (ya da Jörg Mittag'ın işaret ettiği gibi uygulama detaylarını kavram üzerinden tercih ederseniz). Neden?

İnsanlar zaten, çünkü erişim kodunu değiştirmeden verilerinizin iç yapısını değiştiremezsiniz ve bunu 300 yer yerine tek bir yerde (erişim yöntemi) yapmak istiyorsunuz.

Ancak bunun nedeni, kodu nedenini zorlaştırmasıdır : prosedürel kod (doğada prosedürel olan veya basit bir şekilde yazılmış bir dilde olsun), devletin mutasyonuna kısıtlama getirilmesinde çok az yardım sunar. Her şey, her an, her yerden değişebilir. İşlevleri / yöntemleri çağırmak, uzaktan uzaktan ürkütücü bir harekete sahip olabilir. Otomatikleştirilmiş testler daha zordur, çünkü testlerin başarısı, geniş ölçüde erişilen / erişilebilir olan yerel olmayan değişkenlerin değeri ile belirlenir.

Diğer iki büyük programlama paradigması (OO ve fonksiyonel) devletle ilgili karmaşıklık sorununa ilginç, ancak neredeyse tamamen zıt çözümler sunmaktadır. İşlevsel programlamada kişi bundan tamamen kaçınmaya çalışır: işlevler genellikle saftır, veri yapılarındaki işlemler orijinali yerinde güncellemekten ziyade kopyaları döndürür, vb.

Diğer yandan OO, durumu yönetme ile başa çıkmak için araçlar sunar (bundan kaçınmak için araçlar yerine). Erişim değiştiricileri (korunan / halka açık / özel), alıcılar ve ayarlayıcılar, vb. Gibi dil seviyesindeki araçlara ek olarak, başka nesneler verilerini almak için nesnelere ulaşmaya karşı tavsiyelerde bulunan Demeter Yasası gibi bir dizi ilgili sözleşme de vardır. .

Bunlardan herhangi birini yapmak için nesnelere ihtiyacınız olmadığına dikkat edin : erişilemeyen verilere sahip olan ve bunları işlemek için işlevlerin veri yapısını döndüren bir kapatmaya sahip olabilirsiniz. Ama bu bir nesne değil mi? Bu, sezgisel olarak bir nesnenin ne olduğu hakkındaki anlayışımıza uymuyor mu? Ve eğer bu kavrayışa sahipsek, (diğer cevapların söylediği gibi) yerine geçici uygulamaların birleştirici bir patlamasına dayanmak yerine, dili yeniden ifşa etmek daha iyi olmaz mı?


5

Yazılım karmaşıklığını yönetmek için gerçekten OO dillerine ihtiyacımız var mı?

Hayır. Fakat birçok durumda yardımcı olabilirler.

On yıllardır öncelikle tek bir OO dili kullandım, ancak kodumun çoğu aslında kesinlikle OO tarzı bir prosedürdü. Bununla birlikte, bir GUI içeren herhangi bir şey için, dilin engin OO yerleşik yöntemler ve nesneler kitaplığını kullanıyorum, çünkü kodumu muazzam derecede kolaylaştırıyor.

Örneğin, bir formu, düğmeyi ve düzenleme alanını görüntülemek için orijinal düşük düzey Windows API kullanan bir Windows uygulaması çok fazla kod gerektirir, bunun yerine Visual Basic veya C # veya Delphi ile gelen nesnelerin kütüphanelerini kullanmak aynı şeyi yapar program minik ve önemsiz. Bu nedenle, OO kodum genellikle nispeten küçük ve GUI için, bu nesnelerin çağırdığı kodum genellikle çok daha büyük ve genellikle OO olmakla ilgilenmiyor (çözmeye çalıştığım soruna bağlı olarak değişebilse de).

Aşırı derecede karmaşık olan, nesnelerin nasıl uygulandığına dair karmaşık ezoterik kurallara dayanan ve OO kavramları olmadan yazıldığında daha basit olabilecek OO programlarını gördüm. Bunun tersini de gördüm: nesneler kullanılarak yeniden yerleştirilmek ve sadeleştirilmek üzere ağlayan karmaşık sistemler.

Deneyim kazandıkça, farklı araçlar ve çözümler gerektiren farklı durumlar bulacaksınız ve bir boyut hepsine uymuyor.


3

Tamamen C ile yazılmış çok büyük bir projede yer alan biri olarak, cevabın açık bir "hayır" olduğunu kesinlikle söyleyebilirim.

Modülerlik önemlidir. Ancak modülerlik pratik olarak herhangi bir dilde uygulanabilir. Örneğin, C modüler derlemeyi, başlık dosyalarını ve yapı tiplerini destekler. Bu, vakaların% 99'u için yeterli. İhtiyacınız olan her yeni veri türü için bir modül tanımlayın ve veri türünde çalışmak için işlevleri tanımlayın. Bazen performans istersiniz ve bu işlevler satır içi işlevler olarak başlık dosyasındadır, diğer zamanlarda standart işlevleri kullanacaksınız. Hangi yolun seçildiği kullanıcı tarafından görülmez.

Yapılar kompozisyonu destekler. Örneğin, bir muteks kilidi ve normal bir karma tablodan oluşan kilitli bir karma tabloya sahip olabilirsiniz. Bu nesne yönelimli programlama değildir; alt sınıflama yapılmaz. Kompozisyon, nesne yönelimli programlama fikrinden çok daha eski bir araçtır.

Derleme seviyesi modülerliğinin yeterli olmadığı ve çalışma zamanı modülerliğine ihtiyaç duyduğunuz durumlarda% 1 için işlev işaretçisi adı verilen bir şey vardır. İyi tanımlanmış bir arayüzün bireysel uygulamalarına izin verir. Bunun nesne yönelimli olmayan bir dilde nesne yönelimli programlama olmadığını unutmayın. Bu, bir arayüz tanımlamak ve sonra onu uygulamaktır. Örneğin, alt sınıflama burada kullanılmaz.

Belki de en karmaşık açık kaynaklı projeyi düşünün. Yani, Linux çekirdeği. Tamamen C dilinde yazılmıştır. Esas olarak, kompozisyon dahil standart derleme seviyesi modülerlik araçları kullanılarak yapılır ve daha sonra zaman zaman çalışma zamanı modülerliğine ihtiyaç duyulduğunda, bir arayüz tanımlamak ve uygulamak için işlev işaretçileri kullanılır.

Eğer Linux çekirdeğinde nesne yönelimli bir programlama örneği bulmaya çalışırsanız, nesne aramalı programlamayı "bir arayüz tanımlamak ve daha sonra uygulamak" gibi standart görevleri dahil etmek için genişletmediğiniz sürece, bu tür bir örnek bulmak çok zor olduğundan eminim.

C programlama dilinin bile gerçekten ihtiyaç duyduğunuzda nesne yönelimli programlamayı desteklediğini unutmayın. Örneğin, GTK grafik kullanıcı arayüzü araç setini düşünün. Nesne yönelimli olmayan bir dilde yazılmış olsa da aslında nesne yönelimlidir. Bu, “nesne yönelimli bir dile” ihtiyaç duyduğunuz fikrinin derinde hatalı olduğunu göstermektedir. Nesne yönelimli bir dilin yapabileceği başka bir dilin yapamayacağı hiçbir şey yoktur. Ayrıca, uzman bir programcıysanız, nesneye yönelik kodları herhangi bir dilde çok kolay bir şekilde yazmayı biliyorsunuz. Örneğin, C kullanmak bir yük değildir.

Bu nedenle, sonuçlar, nesneye yönelik dillerin muhtemelen yalnızca kavramın gerçekte nasıl uygulandığını anlamada başarısız olan acemi programcılar için yararlı olduğu yönündedir. Ancak, programcıların bu kadar acemi programcılar olduğu herhangi bir projenin yakınında olmak istemem.


1
“[...] varılan sonuçlara göre, nesneye yönelik diller muhtemelen yalnızca kavramın gerçekte nasıl uygulandığını anlayamayan acemi programcılar için yararlıdır.” İlginç. Aklında hangi dilleri var? Bu dillerde, başarısız olan veya başarısız olan açık kaynaklı projelerden örnekler var mı?
Vincent Savard

3
Bazı iyi puanlar alıyorsunuz, ancak ana fikriniz hatalı. Evet, kapsülleme, sanal gönderme, devralma ve hatta çöp toplama gibi OO kavramlarını C gibi bir dilde uygulamak mümkündür. Programlamayı kolaylaştırmaz. Programlama ve özellikle C gibi bir dilde tasarım kesinlikle bir OO diline göre daha zor. C'de kavramları uygulamalarıyla eşleştirmeniz gerekir, bir OO dilinde bu adımı yapmanız gerekmez (en azından OO kavramları için).
balık,

1
"[işlev işaretçileri], iyi tanımlanmış bir arabirimin bireysel uygulamalarına izin verir. Bunun nesne yönelimli olmayan bir dilde nesne yönelimli programlama olmadığını unutmayın. Bu, bir arabirim tanımlamak ve daha sonra uygulamaktır." Üzgünüz, ama bu tamamen yanlıştır, çünkü bu tam olarak OOP'dir. "Örneğin, alt sınıflama burada kullanılmaz" Alt sınıflama, OOP'nin gerekli bir özelliği değildir. Örneğin, JavaScript'in alt sınıflandırma içermeyen bir nesne yönelimli dil olduğunu unutmayın (veya bu konuda, tüm sınıflar ... Yalnızca işlev referansları içeren nesneler).
Jules

1
Son yorumumu açıklığa kavuşturmak için, benim görüşüme göre, OOP (zorunlu olarak herhangi bir OO dili değil) ile diğer yöntemler arasındaki ana ayırt edici faktör, OOP'da, o verilerin biçimini bilmeye gerek kalmadan, veri üzerinde soyut olarak çalışan arayüzleri tanımlamamızdır. arayüzlerin uygulanmasını verinin kendisine bağlamak. OOP budur. Uygulama yöntemi, Java stili bir sınıf, bir JavaScript nesnesi (etkili bir şekilde bir veri veya kod olabilecek bir ad haritası) veya veriler için işlev işaretleyicileri ve bir boşluk * içeren bir yapı olup olmadığıyla ilgili değildir.
Jules

1
“Öyleyse, sonuç, nesneye yönelik dillerin muhtemelen sadece kavramın gerçekte nasıl uygulandığını anlayamayan acemi programcılar için yararlı olduğu yönündedir.” .... Ve bu açıkçası hakarettir. Bu kavramların nasıl uygulandığını yeterince iyi biliyorum. O zaman bile yetkin olmak için kullanarak yeterince iş yaptım. Geçmişte OO dilleri için hem tercüman hem de derleyici uyguladım. Ancak birinci sınıf nesnelere sahip daha yüksek seviyeli dillerde çalışmayı tercih ettiğim için çalışmayı tercih etmeyen acemi bir programcı olmalıyım ?!
Jules

2

Nesne yönelimli yöntemler de dahil olmak üzere programlama paradigmalarını getirmenin nedeni, daha karmaşık ve güçlü programlar yapmayı kolaylaştırmaktır. Byte Dergisi'nin Ağustos 1981 sayısında, Smalltalk'ın kilit yaratıcılarından biri olan Daniel Ingalls , aşağıdakileri içeren “nesne yönelimli” yi tanımladı:

  • otomatik depolama yönetimi
  • mesaj alışverişi yapabilme
  • dilin tüm işlemlerine uygulanan tek biçimli bir metafor
  • hiçbir bileşen başka bir bileşenin iç kısmına bağlı değildir (modülerlik)
  • program sadece nesnelerin davranışını tanımlar, temsil edilmelerini (polimorfizm) değil
  • her bileşen sadece bir yerde görünmelidir (faktoring)
  • donanımdan bağımsız bir sanal makinenin kullanımı
  • Her kullanıcı tarafından erişilebilir bileşen, gözlem ve kontrol için mevcut olmalıdır (reaktif prensip)
  • genel kontrolör olmamalıdır (işletim sistemi yok)

Bunlar, Xerox Parc Research tarafından geliştirilen SmallTalk-80 için sürüş tasarımı konusundaki düşünceler olarak tanımlanan Ingalls prensipleriydi. Yukarıda belirtilen dergi makalesinde, bu ilkelerin her birinin ayrıntılı bir açıklamasını ve Ingalls'a göre nesne yönelimli paradigmaya nasıl katkıda bulunduklarını okuyabilirsiniz.

Bu ilkelerin tümü, herhangi bir Turing tam dili kullanılarak, ister işlemsel, isterse montaj dili veya ne olursa olsun uygulanabilir. Bunlar bir dil özelliği değil, tasarım ilkeleridir. Nesne yönelimli bir dil, yazılım oluştururken bu ilkeleri kullanmayı kolaylaştırmayı amaçlamaktadır.

Örneğin, Ingall'in ilkelerini ilk almak için (otomatik depolama yönetimi), herkes kendi otomatik depolama yönetim sistemini prosedürel bir dilde yazabilir, ancak bunu yapmak için çok çalışmak gerekir. Yerleşik otomatik depolama yönetimine sahip SmallTalk veya Java gibi bir dil kullanırken, programcının belleği yöneten kadar iş yapması gerekmez. Değişim, programcının hafızanın kullanım şekli üzerinde daha az kontrol sahibi olması. Yani, bir fayda ve dezavantaj var. Nesne yönelimli programlama gibi bir tasarım paradigması fikri, paradigmanın faydalarının en azından bazı programcılar için dezavantajlardan ağır basmasıdır.


Etki Alanı Özel Dilleri için de aynı kuralların geçerli olacağını düşünüyorum. Aynı avantajlar ve dezavantajlar ... Tek fark, DSL’lerin son kullanıcıların çalışabilmesi için yeterince basitleştirilebilmesi, çünkü 'dil' sorunlu alan hakkındaki anlayışına tekabül ediyor ve başka bir şey bulunmuyor.

0

Yazılım karmaşıklığını yönetmenin bir yolu, çerçeveyi tamamen bir Etki Alanına Özel Dil kullanarak istenen eylemlerden ayırmaktır . Bu, programlama kodunun seviyesinin, istenen sonuçların yapılandırıldığı seviyeden farklı olduğu anlamına gelir - tamamen farklı bir dil veya sistem. Bu doğru yapıldığında, geleneksel kod esasen bir kütüphane haline gelir ve istenen sonuçları yaratan kullanıcı veya diğer kişi, bir komut dosyası dili veya bir rapor oluşturucu gibi görsel tasarım aracıyla birlikte bir şeyler tarar.

Çalışmak için, bu, hangi işlemlerin mümkün olacağı ve bunların nasıl bir araya getirileceği (komut dosyası dili veya görsel tasarım, bir form oluşturma aracı gibi) etrafında kesin bir sınır çizilmesini gerektirir. Meta veri, çalışma zamanı konfigürasyonunu kodlama detaylarından çıkarmanın önemli bir yoludur ve bir sistemin çok çeşitli istenen sonuçları desteklemesini mümkün kılar. Sınırlar belirlenir ve tutulursa (ortaya çıkan her bir uzatma talebini kabul etmiyorsanız), istediklerini elde etmek için programcı olmalarına gerek kalmadan, insanlar için çalışan uzun ömürlü ve sağlam bir sisteme sahip olabilirsiniz.

Martin Fowler bu konuda bir kitap yazdı ve bu teknik neredeyse programlama kadar eski. Neredeyse tüm programlama dillerinin Etki Alanı Özel Dilleri olduğunu söyleyebilirsiniz ve bu nedenle fikir endemiktir, çünkü çok açıktır. Ancak hayatınızı kolaylaştırmak için yine de kendi senaryolarınızı veya görsel tasarım araçlarınızı oluşturabilirsiniz. Bazen bir sorunu genelleştirmek çözmeyi çok kolaylaştırır!


0

Bu çok iyi bir soru ve burada verilen cevapların adalet yapmadığını hissediyorum, bu yüzden devam edip düşüncelerimi ekleyeceğim.

Amaç - Yazılım Karmaşıklığını Yönetme . Amaç "OO dilini kullanmak" değildir.

Yeni bir paradigma getirmenin ardındaki 'sebep' değildir. Kodlama daha olgunlaştıkça doğal olarak gerçekleşen bir şeydir. Bağlantılı listenin sonuna yeni bir düğüm eklemek yerine, trenin sonuna koçu koyduğumuz bir kod yazmamız daha mantıklıdır (bağlanmış bir liste kullanılarak modellenmiştir).


Gerçek dünya varlıklarına açısından Kodlama basitçe ne zaman kodlamak için açık ve doğru bir yoldur edilir gerçek dünya varlıklar hakkında kodlama.


Bir bilgisayar bağlantılı listenin sonuna bir düğüm ekleyerek çalışabilir ve trenin sonuna fazladan bir koç ekleyerek çalışabilir. Ancak insanlar için, trenle ve koçla çalışmak, bağlantılı bir listeye ve düğümlere göre daha kolaydır, düz bir seviyeye gidersek, trenin bağlantılı bir liste ile modellendiğini görürüz.

Dosyaları korumak veya şifrelemek, kapsülleme sağlayamaz. Şifrelemenin tam tersi şifre çözmedir. Kapsülleme tersidir dekapsülasyonu anlamına gelen daha iyi performans elde etmek programlama dillerinde yapılar ve sınıflar ayrışımı. Bellek trafiğini azaltma ve OOP kurallarını denetlemekten kaçınmanın kazandığı performans.

Böylece hem şifreli hem de iyi kapsüllenmiş kod yazabilirsiniz çünkü bu ikisi farklı kavramlardır.

Kapsülleme, gerçeğe yakın olması nedeniyle karmaşıklığı yönetmeye yardımcı olur.

Bu nedenle, nesneleri programlayın çünkü kodlamanız daha kolay ve siz ve diğer herkesin anlaması için daha hızlı.


0

Hatırlanması gereken bir şey şudur:
OOP, dil özellikleri ile ilgili değildir; kodunuzu yapılandırma şeklinizle ilgilidir .

OOP bir düşünme ve kodunuzun mimarisini tasarlamanın bir yoludur ve hemen hemen her dilde yapılabilir. Bu, özellikle assembler ve C olarak adlandırılan düşük seviyeli, OO olmayan dilleri içerir. Assembly'de mükemmel nesne yönelimli programlama yapabilirsiniz ve C ile yazılmış Linux çekirdeği birçok yönden nesne yönelimlidir. .

Bununla birlikte, bir dilde OO özellikleri, istenen sonuçları elde etmek için yazmanız gereken kazan plakası kodunu büyük ölçüde azaltır . Açıkça bir sanal fonksiyon tablosu tanımlamanız ve onu C'deki uygun fonksiyon göstergeleriyle doldurmanız gerektiğinde , Java'da hiçbir şey yapmazsınız ve bitirdiniz. OO dilleri basitçe kaynak kodundan kabadayılık sağlayan tüm dilleri kaldırır, onu güzel, dil düzeyinde soyutlamalar (sınıflar, yöntemler, üyeler, temel sınıflar, örtülü yapıcı / yıkıcı çağrıları vb.) Arkasına saklar.

Yani, hayır, OOP yapmak için OO dillerine ihtiyacımız yok. Sadece OOP'un iyi bir OO dili ile yapması çok daha kolay .


-1

Nesneye yönelik programlama sadece modüllerin + kapsüllemeden daha fazlasıdır. Dediğiniz gibi, modüllerin + kapsüllemeyi nesne yönelimli olmayan (prosedürel) bir dilde kullanmak mümkündür. OOP sadece bundan daha fazlasını içerir: nesneler ve yöntemler içerir. Yani, hayır, bu OOP'yi yakalamaz. Bkz. Örneğin, https://en.wikipedia.org/wiki/Object-oriented_programming veya iyi bir ders kitabının OOP'ye girişini görün.


Cevap için teşekkür ederim. Bir tane tavsiye eder misin?
steakexchange

-2

Bunun en büyük nedeni, bir program daha karmaşık hale geldikçe, onun bazı bölümlerini diğer bölümlerden görünmez hale getirmeniz veya uygulamanın karmaşıklığı ve işlev sayısının beyninizi kulaklarınızdan sallanmasına neden olmasıdır.

Her biri üzerinde gerçekleştirilebilecek yaklaşık 20 işlemden oluşan 100 sınıf bir sistem düşünelim; bu 2,000 fonksiyondur. Bununla birlikte, bunlardan sadece 500 tanesi 'Save' ve 'Delete' gibi komple işlemlerdir, 1500 ise biraz bakım veya dahili bir rol oynar. Düşünmek;

// intentionally in a non-specific language!

setName(person, name) {
    nameParts = splitPersonName(name);
    person.firstName = nameParts[0];
    person.lastName = nameParts[1];
    person.modified = true;
}

splitPersonName(name) {
    var result = [];
    result.add(name.substring(0, name.indexOf(" ")));
    result.add(name.substring(name.indexOf(" ") + 1));
    return result;
}

Yani SetNameinsanlar yapması gereken bir işlevdir için bir kişinin, ancak SplitPersonNamekullanılan bir yardımcı fonksiyonudur tarafından kişi.

Düz prosedürel programlama, bu iki işlem arasında bir ayrım yapmaz. Bu, 2.000 işlevselinizin dikkatinizi çekeceği anlamına gelir. Bununla birlikte, eğer bu işlevleri 'kişi kaydına sahip olan herkese açık' ve 'yalnızca kişi kaydında yardımcı bir fonksiyon olarak kullanılan' olarak işaretleyebilirsek, dikkatimiz şu anda 500 'herkesin kullanımına açıktır' ve 15 'fayda' düzenlediğiniz sınıf için işlevler

İşte bu publicve privatene;

public class Person {
    public void setName(...) {...}
    private string[] splitPersonName(...) { ...}
}

1
Sorumu doğru anladığınızdan emin değilim. Zaten kapsülleme ve karmaşıklığı yönetmenin bir yolu olarak saklanan verilerin farkındayım. Bunun, usule ilişkin dillerde de kolayca yapılabileceğini düşünüyorum; ayrıca programı, iç işleri ayrı korunan kaynaklarda belirlenmiş, iyi tanımlanmış basit görevleri yerine getiren modüllere bölerek. Öyleyse neden işlemsel dillerde bu şeyleri yapabildiğimizde OOP? Bu benim sorum.
steakexchange

2
Sanırım cevabım, eğer böyle bir şey yapmak istiyorsanız, bunu yapmak için özel bir takım ve dil yapıları yazmak zorunda kalacaksınız (örneğin, özel bir 'include' çağrısı yapamayan bir dosyaya çağrı yapma başka bir yere dahil edilmek). Bu yoldan başladığınızda, aslında nesne yönelimli bir dili kendi yönteminizle uygulamaya başladınız. Örneğin, C ++ başlangıçta düz C üreten bir ön
işlemciydi

3
@steakexchange OOP'nin birçok prosedürel dilin böyle modüllere sahip olmadığı bir zamanda geliştirildiğini unutmayın . Bazıları bile bu dilleri usule uygun şekilde çağırmazdı. Aslında, bir prosedürel dilin OO veya tam tersi olmaması gerektiğini söyleyen hiçbir şey yoktur. Etiketlere dikkat edin - sizi kolayca yanlış yönlendirebilirler. Prosedürel diliniz genel ve özel alanlara ve prosedürlere sahip modülleri destekliyorsa, sizin için iyi :) :) "geleneksel prosedürel" ve "OOP" arasındaki temel fark, arama gönderiminin OOP'ta daha esnek olmasıdır - gerçekten de, katı OOP'ta, hangi kodu aradığını asla bilemezsin.
Luaan

2
@steakexchange ML ailesi dillerinde, modüller harika çalışır ve lambdas ile birlikte, size herhangi bir OO dilinin tüm gücünü verir (sonuçta, bir işlev tek bir yöntemle bir arayüzdür - bu neredeyse "iyi kod" adamları 0 mı?: P). Çeşitli nedenlerden ötürü, C ++ veya Java gibi daha ustaca kullanılan dillerden daha az kullanılıyorlar, ancak çekiciliği var ve birçok kişi insanları (ya da daha az başarılı) hayatlarını nasıl basitleştirebilecekleri konusunda eğitmeye çalışıyor.
Luaan

C etkili bir şekilde bu şeylere sahiptir. Arabirimleri (.h dosyaları) olan modüllere (.c dosyaları) sahiptir ve genel (harici) ve genel olmayan (harici) yöntemlere (işlevlere) sahip olabilir. Fonksiyon işaretçilerinin dizileri ile fakir bir adamın polimorfizmine bile sahip olabilirsiniz, OO'nun C'de (veya belki de aklı başında) kolay olmadığını ancak kapsüllemenin oldukça kolay olduğunu söylemiyorum,
Nick Keighley
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.