it-swarm.dev

OOP neden zor?

Nesneye yönelik bir dili (Java) kullanmaya başladığımda, hemen hemen "Cool" u seçip kodlamaya başladım. OOP hakkında çok fazla soru okuduktan sonra bunu hiç düşünmedim. Genel izlenim insanların bununla mücadele etmeleri. Çok zor olduğunu düşünmediğim ve dahi olduğumu söyleyemediğim için, bir şeyi kaçırmış ya da yanlış anlamış olmam gerektiğini düşünüyorum.

OOP anlamak zor? = anlamak zor?

93
gablin

Şahsen OOP mekaniğini kavramak oldukça kolay buldum. Benim için zor kısmı bunun "nedeni" idi. İlk karşılaştığımda, bir problem arayışında bir çözüm gibi görünüyordu. Çoğu insanın bunu zor bulmasının birkaç nedeni:

  1. IMHO'nun başlangıçtan OO öğretilmesi korkunç bir fikirdir. Prosedür kodlaması "kötü bir alışkanlık" değildir ve bazı işler için doğru araçtır. Bir OO programındaki münferit yöntemler, her nasılsa oldukça prosedürel görünmektedir. Ayrıca, prosedürel programlamayı sınırlamalarının görünür hale gelmesi için yeterince iyi öğrenmeden önce, OO öğrenci için çok yararlı görünmemektedir.

  2. OO'yu gerçekten kavrayabilmeniz için önce veri yapılarının temellerini ve geç bağlama/yüksek dereceli fonksiyonları bilmeniz gerekir. Eğer sadece ilkelleri kullanmak ve daha yüksek mertebeden fonksiyonları kullanmak yerine veri yapılandırma kavramlarını bile anlayamıyorsanız, polimorfizmi (temelde verilere ve veriler üzerinde çalışan bir grup fonksiyona geçirir) grok yapmak zordur. işlevlere işaretçiler.

  3. Tasarım modelleri daha gelişmiş bir şey değil OO için temel bir şey olarak öğretilmelidir. Tasarım desenleri ormanı ağaçların arasından görmenize ve OO'in gerçek sorunları basitleştirebileceği ve somut olarak nereden öğreneceğinize dair somut örnekler vermenize yardımcı olur. Dahası, gerçekten OO elde ettiğinizde, çoğu tasarım deseni arkada belirginleşir.

120
dsimcha

Henüz belirtilmemiş birkaç faktör olduğunu düşünüyorum.

Her şeyden önce, en azından "saf OOP" (örneğin, Smalltalk) 'da her şeyin bir nesne olduğu, bir sayı düşünmek için zihninizi oldukça doğal olmayan bir konfigürasyona çevirmeniz gerekir (sadece bir örnek için) sadece bir değer yerine akıllı bir nesne olarak - gerçekte, 21 (örneğin) gerçekten sadece bir değerdir. Bu, bir yandan OOP büyüklüğünün gerçekliği daha yakından modellenmesi söylendiğinde özellikle sorunlu hale gelir, ancak LSD'den ilham alan bir görünüm gibi korkunç bir şey gibi görünen şeyleri alarak işe başlarsınız. gerçekliğin en temel ve bariz kısımları bile.

İkincisi, OOP 'da kalıtım çoğu insanın zihinsel modellerini de çok yakından takip etmez. Çoğu insan için, şeyleri özel olarak sınıflandırmak değil herhangi bir yere sahiptir çalışan bir sınıf hiyerarşisi oluşturmak için gereken mutlak kurallara yakın.Özellikle başka bir class D kaynağından devralan bir class B oluşturmak, class D nesnelerinin kesinlikle, olumlu bir şekilde paylaştığı anlamına gelir all class B 'un özellikleri. class D kendi başına yeni ve farklı özellikler ekleyebilir, ancak hepsi class B karakteristikleri aynı kalmalıdır.

Aksine, insanlar bir şeyi zihinsel olarak sınıflandırdıklarında, genellikle daha gevşek bir model izlerler. Bir örnek olarak, bir kişi bir nesne sınıfını neyin oluşturduğu hakkında bazı kurallar yaparsa, diğer kurallara uyulduğu sürece neredeyse herhangi bir kuralın kırılabileceği oldukça tipiktir. Gerçekten kırılamayan birkaç kural bile neredeyse her zaman biraz "gerilebilir".

Örneğin, "araba" yı bir sınıf olarak düşünün. Çoğu insanın "araba" olarak düşündüklerinin büyük çoğunluğunun dört tekerleği olduğunu görmek oldukça kolaydır. Bununla birlikte, çoğu insan sadece üç tekerlekli bir araba gördü (en azından bir resmi). Doğru yaştaki birkaçımız 80'li yılların başlarında altı tekerleği olan bir yarış arabasını da hatırlıyoruz. Bu bize temel olarak üç seçenek sunuyor:

  1. Bir arabanın kaç tekerleği olduğu hakkında hiçbir şey iddia etmeyin - ancak bu, her zaman 4 olacağı örtük varsayımına ve başka bir sayı için kırılması muhtemel bir kodlamaya yol açar.
  2. Tüm otomobillerin dört tekerleği olduğunu iddia edin ve gerçekten olduklarını bilsek de diğerlerini "araba değil" olarak sınıflandırın.
  3. Her ne kadar iyi bir şans olsa da, bu yeteneğe asla ihtiyaç duyulmayacak, kullanılmayacak veya uygun şekilde test edilemeyecek şekilde, tekerlek sayısında değişiklik sağlayacak şekilde sınıfı tasarlayın.

OOP) hakkında öğretim genellikle büyük taksonomiler oluşturmaya odaklanır - örneğin, yeryüzünde bilinen tüm yaşamın dev bir hiyerarşisi veya bu düzende bir şey olan bitler ve parçalar. her şeyden önce, birçok insanı eldeki soru ile tamamen alakasız olan büyük miktarda bilgiye odaklanmaya yöneltiyor. Bir noktada, köpek ırklarının nasıl modelleneceği ve (örneğin) " minyatür kaniş "miraslı" tam boy kaniş "mi yoksa tam tersi mi yoksa" tam boy kaniş "ve" minyatür kaniş "her ikisi de miras ile soyut bir temel" Kaniş "sınıfı olup olmadığını miras almalı. görmezden gelmek için başvurunun köpekler için ruhsatların takibi ile uğraşması gerekiyordu ve eldeki amaç için ilişkinin modellenmesi olmadan "cins" (veya bu düzende bir şey) adında tek bir alanın olması yeterliydi. ırklar arasında.

İkincisi ve neredeyse önemlisi, eldeki görev için önemli olan özelliklere odaklanmak yerine, öğelerin özelliklerine odaklanmaya yol açar. Bir şeyleri oldukları gibi modellemeye yönelir, burada (çoğu zaman) gerçekten ihtiyaç duyulan şey, ihtiyaçlarımızı karşılayacak en basit modeli oluşturmak ve gerekli alt kısmına uyacak şekilde soyutlamayı kullanmaktır. -Yaptığımız soyutlamaya uygun sınıflar.

Son olarak, bir kez daha söyleyeceğim: yavaş yavaş veri tabanlarının yıllar içinde izlediği yolu takip ediyoruz. İlk veri tabanları hiyerarşik modeli izledi. Yalnızca verilere odaklanmak dışında, bu tek bir kalıtımdır. Kısa bir süre için, birkaç veritabanı ağ modelini izlemiştir - esasen çoklu kalıtımla özdeştir (ve bu açıdan bakıldığında, çoklu arayüzler fark etmek veya ilgilenmek için birden fazla temel sınıftan yeterince farklı değildir).

Ancak, uzun zaman önce, veritabanları ilişkisel model üzerinde büyük ölçüde birleşmişti (ve SQL olmasa da, bu soyutlama düzeyinde mevcut "NoSQL" veritabanları da ilişkiseldir). İlişkisel modelin avantajları, onları burada tekrar etmekten rahatsız olmayacağım kadar iyi bilinmektedir. Programlamadaki ilişkisel modelin en yakın analoğunun genel programlama olduğunu (ve üzgünüm, ancak Java jenerikler, bir örnek olarak) gerçekten kalifiye olmadığımı not edeceğim. , doğru yönde küçük bir adım olsalar da).

57
Jerry Coffin

OOP soyut düşünme yeteneğini gerektirir; Az sayıda insanın, hatta profesyonel programcıların bile sahip olduğu bir hediye/lanet.

26
John Kraft

Herhangi bir paradigma, çoğu insan için kavramak için belirli bir "Kenarın Üstüne Bas" gerektirir. Tanım olarak, bu yeni bir düşünce biçimidir ve bu nedenle eski kavramları bırakmanın belirli bir miktarını ve yeni kavramların neden yararlı olduğunu belirli bir miktar tam olarak kavramasını gerektirir.

Bence bir çok problem, bilgisayar programlamayı öğretmek için kullanılan yöntemlerin genel olarak oldukça zayıf olmasıdır. OOP o kadar yaygındır ki, bu kadar dikkat çekici değildir, ancak hala fonksiyonel programlamada sık sık görüyorsunuz:

  • önemli kavramlar tek isimlerin arkasında gizlidir (FP: Monad nedir? OOP: Neden onlara bazen fonksiyonlar ve diğer zamanlarda yöntemler diyorlar?)

  • garip kavramlar, gerçekte ne yaptıkları ya da neden kullandığınız ya da neden bunları kullanmayı düşündükleri yerine metaforda açıklanmaktadır (FP: Bir monad bir uzay giysisidir, bazı kodları tamamlar. nesne bir ördek gibidir, gürültü yapabilir, yürüyebilir ve Hayvandan miras alabilir)

  • iyi şeyler kişiden kişiye değişir, bu nedenle herhangi bir öğrenci için devrilme noktasının ne olacağı pek açık değildir ve çoğu zaman öğretmen hatırlayamaz bile. (FP: Oh, monadlar, tipin kendisinde bir şey gizlemenize ve her seferinde neler olduğunu açık bir şekilde yazmak zorunda kalmadan devam etmenize izin verir. OOP: Oh, nesneler bu verilerle bir tür veri için işlevleri korumanıza izin verir.)

En kötüsü, sorunun da belirttiği gibi, bazı insanlar hemen kavramın neden iyi olduğunu anlamaya başlayacak ve bazılarının olmayacak. Gerçekten devrilme noktasının ne olduğuna bağlıdır. Benim için, nesnelerin veri depolamak ve bu veriler için yöntemleri anlamak önemliydi, bundan sonra her şey doğal bir uzantı olarak uyuyordu. Sonra bir nesneden bir yöntem çağrısı ilk parametre olarak o nesne ile statik bir çağrı yapmak çok benzer olduğunu fark gibi atlar vardı.

Daha sonra küçük atlamalar, anlayışı daraltmaya yardımcı olur, ancak bir kişiyi "OOP mantıklı değil, neden insanlar bunu yapıyor?" "OOP en iyisi, neden insanlar başka bir şey yapıyor?"

21
CodexArcanum

Bence temel zorluk şu şekilde özetlenebilir:

// The way most people think.
Operation - object - parameters
// Example:
Turn the car left.

// The way OOP works conceptually
Object - operation - parameters
// Example:
Car.Turn(270);

Tabii, insanlar 270 gibi "sol" eşlemesine alışabilir ve evet, "arabayı çevir" yerine "Car.Turn" demek o kadar büyük bir sıçrama değil. ANCAK, bu nesnelerle iyi başa çıkmak ve onları oluşturmak için normal düşünme şeklinizi tersine çevirmek zorundasınız.

Bir nesneyi manipüle etmek yerine, nesneye aslında kendi başına bir şeyler yapmasını söylüyoruz. Artık zor hissetmeyebilir, ancak bir pencereye kendini açmasını söylemek tuhaf geliyor. Bu şekilde düşünmeyen insanlar, nihayetinde bir şekilde doğal olana kadar bu tuhaflıkla tekrar tekrar mücadele etmek zorundadırlar.

21
John Fisher

Çünkü temel açıklama OOP bu alanda nasıl kullanıldığı ile çok az ilgisi vardır. Öğretmek için çoğu program "gibi bir araba düşünün bir nesne ve tekerlekler nesne, kapılar ve şanzıman ... ", ancak bazı belirsiz simülasyon programlama durumlarının dışında, nesneler fiziksel olmayan kavramları temsil etmek veya dolaylı olarak tanıtmak için daha sık kullanılır. insanların bunu sezgisel olarak yanlış bir şekilde anlamalarını sağlar.

Tasarım modellerinden öğretim, programcılara bazı gerçek modelleme problemlerinin soyutta tanımlamak yerine nesnelerle nasıl etkili bir şekilde saldırıya uğratılabileceğini gösterdiği için OOP'u tanımlamanın çok daha iyi bir yoludur.

15
Dan Monego

Çoğunlukla dsimcha'nın cevabına katılmıyorum:

  1. Başlangıçtan OO öğretmek de kendi içinde kötü bir fikir değil, aynı zamanda prosedürel dil öğretmek de değildir. Önemli olan, OO veya prosedürden bağımsız olarak insanlara açık, özlü, tutarlı kod yazmayı öğretmemizdir.

  2. İyi OO programlardaki bireysel yöntemler hiç yordamsal olmaya eğilimlidir. Bu, OO dillerinin evrimi ile giderek daha doğru hale geliyor (C # okuyun çünkü C++ dışında bildiğim tek diğer OO dil) ve gün geçtikçe daha karmaşık hale gelen sözdizimleri (lambdas, nesnelere LINQ, vb.). Prosedürel dillerde OO yöntem ve prosedürler arasındaki tek benzerlik, yakın zamanda değişeceğinden şüphelendiğim her birinin doğrusal doğasıdır.

  3. Veri yapılarını anlamadan da prosedürel bir dilde uzmanlaşamazsınız. İşaretçi kavramı yordamsal diller için OO diller kadar önemlidir. Örneğin prosedür dillerinde oldukça yaygın olan parametreleri referans olarak iletmek, herhangi bir OO dilini öğrenmek için gereken işaretçileri anlamanızı gerektirir.

  4. Tasarım desenlerinin OO programlamada hiç öğretilmemesi gerektiğini düşünmüyorum, çünkü OO programlama için hiç de temel değiller. Tasarım desenleri hakkında hiçbir şey bilmeden kesinlikle iyi bir OO programcı olabilir. Aslında bir kişi, uygun isimlerle belgelendiğini ve kitapların onlar hakkında yazıldığını bile bilmeden iyi bilinen tasarım desenlerini bile kullanıyor olabilir. Temel olarak öğretilmesi gereken, Tek Sorumluluk, Açık Kapalı ve Arayüz Ayrımı gibi tasarım ilkeleridir. Ne yazık ki, bugünlerde kendilerini OO programcı olarak gören birçok insan ya bu temel kavrama aşina değil ya da görmezden gelmeyi tercih ediyor ve bu yüzden orada çok fazla çöp OO kodu var. Sadece bu ve diğer ilkelerin tam olarak anlaşılmasından sonra tasarım kalıpları tanıtılmalıdır.

Orijinal posterin sorusunu cevaplamak için, evet, OO prosedürel programlamaya göre anlaşılması daha zor bir kavramdır. Çünkü gerçek hayattaki nesnelerin özellikleri ve yöntemleri açısından düşünmüyoruz. Örneğin, insan beyni "TurnOn" u bir TV yöntemi olarak kolayca düşünmez, ancak onu TV'yi açmanın bir işlevi olarak görür. Benzer şekilde, polimorfizm insan beyninin her bir gerçek yaşam nesnesini yalnızca bir "yüz" ile gören yabancı bir kavramdır. Kalıtım yine beynimiz için doğal değildir. Bir geliştirici olduğum için oğlumun bir tane olacağı anlamına gelmez. Genel olarak, insan beyninin OO öğrenmek için eğitilmesi gerekirken, prosedürel diller daha doğaldır.

13

Bence birçok programcı ön tasarım ve planlama konusunda zorluk çekiyor. Birisi sizin için tüm tasarımı yapsa bile, OOP ilkelerinden kurtulmak mümkün. Anlamayan biri OOP hala Java ile programlayabilir.

6
JeffO

Nesneleri Hiç okumamalısınız? Eh, Neredeyse Hiç. (ACM üyeliği gerekir) Mordechai Ben-Ari tarafından OOP çok zor, çünkü aslında doğal bir paradigma değil) (Makale hakkında çekincelerim olmasına rağmen, bir programın yordamsal bir paradigmanın aksine OOP paradigması üzerine yazıldığını söylemek için yerine getirmesi gerektiğini düşündüğü açık değildir. bir OO dil.)

5
Ken Bloom

Nesneye Dayalı Programlama kendi başına zor değildir.

Zor kısmı iyi yapıyor. Kodları arasında kesmeyi nereye koyabilirsiniz, böylece işleri ortak temel nesneye kolayca taşıyabilir ve daha sonra genişletebilirsiniz? Kodunuzu başkaları tarafından nasıl kullanılabilir hale getirebilirsiniz (sınıfları genişletin, proxy'lere sarın, yöntemi geçersiz kılın), bunu yapmak için çembere atlamaksızın.

Bu zor kısmıdır ve doğru yapılırsa çok zarif olabilir ve kötü yapılırsa çok beceriksiz olabilir. Kişisel deneyimim, yeterince iyi yapabilmek için farklı bir şekilde yapmak istediğiniz her durumda olmanız için çok fazla uygulama gerektirdiğidir this time.

5
user1249

OW ile tanışmadan önce GW-Basic ve Turbo Pascal programlama yaptım, bu yüzden başlangıçta kafamı yaptı.

Başkalarına ne olduğu hakkında bir fikrim yok, ama benim için böyle oldu: programlama hakkındaki düşünce sürecim tamamen prosedüreldi. Gibi: "böyle ve böyle olur, sonra böyle ve sonra olur", vb. Ben asla değişkenleri ve verileri program akışında geçici aktörler daha başka bir şey olarak düşünmüyordu. Programlama "eylemlerin akışı" idi.

Sanırım kavraması kolay olmayan şey (şimdi bana göründüğü kadar aptalca), veri/değişkenlerin aslında gerçekten önemli, sadece geçici aktörlerden daha derin bir anlamda olduğu fikriydi. "akış" programında. Ya da başka bir deyişle: onu kavramanın gerçek anahtarı olan is ile değil, olur ile anlamaya çalıştım.

4
Bobby Tables

Richard Feynman'ın sadece insanların düşünürken akıllarında nasıl tamamen farklı metodolojilere sahip olabileceğini tartışan bir video izliyordum - yani tamamen farklı.

Üst düzey tasarım yaptığımda nesneleri görselleştiriyorum, onları görebiliyorum, arayüzlerini görebiliyorum ve bilginin hangi yollardan geçmesi gerektiğini görüyorum.

Ayrıca ayrıntıları hatırlamakta sorun yaşıyorum ve OO harika bir organizasyon yardımı olduğunu buldum - işlevselliği bulmak, gevşek organize edilmiş bir alt program listesini taramaktan çok daha kolay.

Benim için OO büyük bir yarardı, ancak aynı şekilde görselleştirmezseniz veya üst düzey mimari yapmazsanız, muhtemelen anlamsız ve sinir bozucu.

4
Bill K

Anlamanın zor olduğunu düşünmüyorum ama sorgulayan programcıların çoğu, yordamsal dillerden gelen kavram için yeni olabilir.

Gördüğüm/okuduğum birçok insandan (en azından forumlarda) OOP'tan bir 'sonuç' arayın. Geri dönüp kodunu değiştirmeyen bir prosedürel programcıysanız, faydalarını anlamak muhtemelen zor olabilir.

Ayrıca, bir sürü kötü OOP orada, eğer insanlar okuyor/görüyorsa, neden zor bulabileceklerini görmek kolaydır.

IMO 'tıklama' ya da gerçek bilgiye sahip biri tarafından öğretilene kadar beklemeniz gerekir, acele edebileceğinizi sanmıyorum.

3
DBlackborough

Bence neden OOP birçokları için zor çünkü araçlar gerçekten kolaylaştırmıyor.

Günümüzde bilgisayar dilleri bilgisayarda olup bitenlerin bir soyutlamasıdır.

OOP soyutlamaları temsil etmek için soyutlanmış bir yoldur.

Bu yüzden soyutlama ile soyutlama yapmak için bir soyutlama kullanıyoruz. Buna soyutladığımız şeyin genellikle çok karmaşık fiziksel/sosyal etkileşimler olduğunu ve hiç de şaşırtıcı olmadığını ekleyin.

3
ElGringoGrande

Aslında "Nesne Odaklı Programlamada Mücadele" adlı bir blogum var. Anlamak benim için özellikle zor oldu çünkü prosedürel programlama kullanarak çok zaman geçirdim ve bir nesnenin bir dizi özellik ve davranışlarla temsil edilebileceği fikrini almak için zorlandım. basitçe değişkenler ve yöntemler koleksiyonu).

Ayrıca, bir dil nesnesini yönlendiren çok sayıda kavram vardır - kalıtım, arayüzler, polimorfizm, kompozisyon, vb. Gerçekten etkili ve nesne yönelimli bir kod yazmadan önce teorisi hakkında öğrenilecek çok şey var. yöntemsel programlama ile, değişkenler için bellek ayırma ve diğer yöntemlere giriş noktası çağrıları gibi şeyleri anlamak meselesidir.

2
Tim Claason

Motivasyon. Nedenini görmediğinizde ve yaptığınız şeye bakıp doğru yapıp yapmadığınızı anlayamadığınızda bir şey öğrenmek daha zordur.

Gerekli olan şey, yararlı şeyler yapmak için OO kullanan küçük projelerdir. Tasarım desenleri hakkında bir kitaptan bakmayı ve açıkça faydalı olan ve OO ile iyi çalışan bir proje bulmanızı öneririm. Stratejiyi bir kez denediğimde kullandım. Flyweight veya Singleton gibi bir şey kötü seçimler olurdu, çünkü bunlar genel olarak nesneleri kullanma yollarıdır, bir şeyi başarmak için nesneleri kullanmazlar.)

2
David Thornley