Sızdıran Soyutlamanın Anlamı?


90

"Sızdıran Soyutlama" terimi ne anlama geliyor? (Lütfen örneklerle açıklayın. Sadece bir teoriyi incelerken sık sık zorlanırım.)



14
Joel Spolsky'nin , bildiğim kadarıyla terimin kökeni olan Sızdıran Soyutlamalar Yasası adlı orijinal makalesini okumak isteyebilirsiniz .
Daniel Pryden

2
Önerilen dupe yanıtlarının çoğu akıcı arayüzler hakkındadır.
David Thornley

@David: En yüksek oyu alan ikinci gönderi, sızdıran soyutlamanın ne anlama geldiğini ve harika bir örnekle yanıtlıyor.
missingfaktor

4
Bu soruya 4 yıl sonra google'da yolunuzu aradığınızda, hangi gönderinin en yüksek oyu alan 2. yayının olduğunu tahmin etmek zor.
John Reynolds

Yanıtlar:


108

İşte bir et alanı örneği:

Otomobillerin sürücüler için soyutlamaları vardır. En saf haliyle, bir direksiyon simidi, gaz pedalı ve fren var. Bu soyutlama, kaputun altında ne olduğu hakkında birçok ayrıntıyı gizler: motor, kamlar, triger kayışı, bujiler, radyatör vb.

Bu soyutlamanın güzel yanı, kullanıcıyı yeniden eğitmeden uygulamanın parçalarını iyileştirilmiş parçalarla değiştirebilmemizdir. Diyelim ki distribütör kapağını elektronik ateşleme ile değiştiriyoruz ve sabit kamı değişken kam ile değiştiriyoruz. Bu değişiklikler performansı iyileştirir, ancak kullanıcı yine de direksiyonla çalışır ve başlatmak ve durdurmak için pedalları kullanır.

Aslında oldukça dikkat çekici ... 16 yaşında ya da 80 yaşında biri bu karmaşık makineyi, içinde nasıl çalıştığını gerçekten bilmeden çalıştırabilir!

Ancak sızıntılar var. İletim küçük bir sızıntı. Otomatik şanzımanda, vites değiştirirken otomobilin bir an için güç kaybettiğini hissedebilirsiniz, oysa CVT'de tamamen yumuşak tork hissedersiniz.

Daha büyük sızıntılar da var. Motoru çok hızlı devirirseniz, ona zarar verebilirsiniz. Motor bloğu çok soğuksa, araç çalışmayabilir veya performansı düşük olabilir. Radyoyu, farları ve AC'yi aynı anda çalıştırırsanız, gaz kilometrenizin azaldığını göreceksiniz.


8
Örnek için teşekkürler. Başka hiç kimse basit bir açıklama sunabilecek gibi görünmüyordu.
Sebastian Patten

8
Bu harika bir cevap, özellikle de kullanıcı bakış açısını gösterdiği için, yazılım sürümünün konusu bu.
chad

1
Et alanı ne anlama geliyor? Uzman olmayan kişi açıklaması?
brumScouse

1
@brumScouse "et alanı" fiziksel, çevrimdışı dünya anlamına gelir. Çevrimiçi, siber dünyayla karşılaştırmak için kullanılır. Tanıma bir bağlantı eklemek için cevabımı düzenleyeceğim.
Mark E. Haase

1
Bu yazının "hala sızıntılar olduğunu" belirtmesi hoşuma gidiyor. Her şey onları küçültmekle ilgili.
alaboudi

52

Basitçe, soyutlamanızın bazı uygulama ayrıntılarını ortaya koyduğu veya soyutlamayı kullanırken uygulama ayrıntılarının farkında olmanız gerektiği anlamına gelir. Bu terim 2002 dolaylarında Joel Spolsky'ye atfedilmiştir . Daha fazla bilgi için wikipedia makalesine bakın .

Klasik bir örnek, uzak dosyaları yerel olarak değerlendirmenize izin veren ağ kitaplıklarıdır. Bu soyutlamayı kullanan geliştirici, ağ sorunlarının bunun yerel dosyaların yapmadığı şekillerde başarısız olmasına neden olabileceğinin farkında olmalıdır. Daha sonra, ağ kitaplığının sağladığı soyutlamanın dışındaki belirli hataları işlemek için kod geliştirmeniz gerekir.


7
@mehaase Soyutlamanızın tasarım veya ihmal nedeniyle sızdırması ne kadar önemli olduğunu anlamıyorum. Yanıtı, kendi başına durabilmesi için bir örnek ve referans alınan makaleden daha fazla bilgi ile genişlettim. Dahası, "sızdıran soyutlamanın" mutlaka aşağılayıcı olması gerektiğini düşünmüyorum. Bana göre, bir geliştirici olarak soyutlama ile çalışırken daha dikkatli olmanız gereken bir durumu anlatıyor. Tasarım, "sızıntıdan" bağımsız olarak iyi, kötü veya ilgisiz olabilir.
tvanfosson

13

Vikipedi bir sahiptir oldukça iyi tanımını bunun için

Sızdıran bir soyutlama, karmaşıklığı azaltmayı (veya gizlemeyi) amaçlayan, temeldeki ayrıntıların tamamen gizlenmediği, uygulanan herhangi bir soyutlamayı ifade eder.

Veya başka bir deyişle, yazılım için, programdaki sınırlamalar veya yan etkiler yoluyla bir özelliğin uygulama ayrıntılarını gözlemleyebileceğiniz zamandır.

Hızlı bir örnek, C # / VB.Net kapanışları ve ref / out parametrelerini yakalayamamalarıdır. Yakalanamamalarının nedeni, kaldırma işleminin nasıl gerçekleştiğine dair bir uygulama detayından kaynaklanmaktadır. Bu, bunu yapmanın daha iyi bir yolu olduğu anlamına gelmez.


13

İşte .NET geliştiricilerine tanıdık bir örnek: ASP.NET'in Pagesınıfı, HTTP işlemlerinin ayrıntılarını, özellikle de form verilerinin yönetimini gizlemeye çalışır, böylece geliştiricilerin gönderilen değerlerle uğraşmasına gerek kalmaz (çünkü form değerlerini sunucuya otomatik olarak eşler) kontroller).

Ancak en temel kullanım senaryolarının ötesine geçerseniz, Pagesoyutlama sızmaya başlar ve sınıfın uygulama ayrıntılarını anlamadığınız sürece sayfalarla çalışmak zorlaşır.

Yaygın bir örnek, bir sayfaya dinamik olarak kontroller eklemektir - dinamik olarak eklenen kontrollerin değeri, bunları tam olarak doğru zamanda eklemediğiniz sürece sizin için eşlenmeyecektir: alttaki motor, gelen form değerlerini uygun kontrollerle eşlemeden önce. Bunu öğrenmen gerektiğinde, soyutlama sızdı .


Web formlarının kovasında bo tabanı vardı. Daha da kötüsü, ince örtülü soyutlamaların Http ile tıpkı bir torpido gözünde çalışıyormuşsunuz gibi çalışmak anlamına gelmesiydi.
brumScouse

10

Bir bakıma, önemsiz olmasa da tamamen teorik bir şey.

Bir şeyleri daha kolay kavrayabilmek için soyutlamaları kullanırız. Tek tek öğeler olan sıralı bir karakter kümesiyle uğraştığım gerçeğini gizlemek için bir dilde bir dizgi sınıfı üzerinde çalışabilirim. Sayılarla uğraştığım gerçeğini gizlemek için sıralı bir dizi karakterle uğraşıyorum. 1'ler ve 0'larla uğraştığım gerçeğini gizlemek için sayılarla uğraşıyorum.

Sızdıran bir soyutlama, gizlemesi gereken ayrıntıları gizlemeyen bir soyutlamadır. Java veya .NET'te 5 karakterlik bir dizede string.Length çağrılırsa, bu dillerin karakterleri olarak adlandırdığı uygulama ayrıntıları nedeniyle, bu dillerin 1'i veya 0,5 karakter. Soyutlama sızdırıldı. Yine de sızdırmamak, uzunluğu bulmanın daha fazla depolama alanı gerektireceği (gerçek uzunluğu saklamak için) veya O (1) 'den O (n)' ye (gerçek uzunluğun ne olduğunu bulmak için) değişeceği anlamına gelir. Eğer gerçek yanıtı önemsiyorsam (çoğu zaman gerçekten anlamazsınız) gerçekte neler olup bittiğine dair bilgi üzerinde çalışmanız gerekir.

Bir yöntemin veya özelliğin iç işleyişe girmenize izin verdiği durumlarda, ister soyutlama sızıntıları olsun, isterse daha düşük bir soyutlama düzeyine geçmenin iyi tanımlanmış yolları olsun, bazen insanların üzerinde anlaşamadığı bir konu olabilir.


2
Ve elektronik ve fizikle çalıştığınızı gizlemek için
1'ler ve 0'larla

7

RPC kullanarak örnek vermeye devam edeceğim.

İdeal RPC dünyasında, uzak prosedür çağrısı yerel bir prosedür çağrısı gibi görünmelidir (ya da hikaye böyle devam eder). Programcıya tamamen şeffaf olmalıdır, öyle ki aradıklarında yerel olarak depolanıp çalıştırılmadığı (veya sadece bu konu için) veya uzaktan saklanıp çalıştırılmadığı hakkında SomeObject.someFunction()hiçbir fikirleri olmamalıdır . Teori, bunun programlamayı daha basit hale getirdiği yönünde.SomeObjectsomeFunction

Gerçek farklıdır çünkü yerel bir işlev çağrısı yapmak (dünyanın en yavaş yorumlanan dilini kullanıyor olsanız bile) ile şunlar arasında BÜYÜK bir fark vardır:

  • bir proxy nesnesi aracılığıyla arama
  • parametrelerinizi serileştirmek
  • ağ bağlantısı kurma (henüz kurulmamışsa)
  • verileri uzak proxy'ye iletmek
  • uzak proxy'ye sahip olmak verileri geri yüklemek ve sizin adınıza uzak işlevi çağırmak
  • dönüş değerlerinin serileştirilmesi
  • dönüş değerlerini yerel vekile iletmek
  • serileştirilmiş verilerin yeniden birleştirilmesi
  • uzak işlevden yanıtı döndürmek

Yalnızca zamanda, büyüklük farkının yaklaşık üç mertebesi (veya daha fazlası!). Bu üç + büyüklük sıralaması, performansta büyük bir fark yaratacak ve bu da, bir RPC'yi ilk kez yanlışlıkla gerçek bir işlev çağrısı olarak ele aldığınızda oldukça açık bir şekilde bir prosedür çağrısı sızıntısı soyutlamanıza neden olacak. Ayrıca, kodunuzdaki ciddi sorunları engelleyen gerçek bir işlev çağrısı, uygulama hataları dışında çok az hata noktasına sahip olacaktır. Bir RPC çağrısı, normal bir yerel aramadan beklediğinizden çok, başarısızlık vakaları olarak değerlendirilecek aşağıdaki olası sorunların tümüne sahiptir:

  • yerel proxy'nizi başlatamayabilirsiniz
  • uzak proxy'nizi başlatamayabilirsiniz
  • vekiller bağlanamayabilir
  • gönderdiğiniz parametreler onu sağlam veya hiç yapmayabilir
  • uzaktan kumandanın gönderdiği dönüş değeri onu sağlam veya hiç yapmayabilir

Şimdi, "tıpkı bir yerel işlev çağrısı gibi" olan RPC çağrınız, yerel işlev çağrıları yaparken uğraşmak zorunda kalmayacağınız bir sürü fazladan başarısızlık durumuna sahiptir. Soyutlama daha da zorlaştı.

Sonuçta RPC kötü bir soyutlamadır çünkü her seviyede bir elek gibi sızdırır - başarılı olduğunda ve her ikisinde de başarısız olduğunda.


<pimp> Erlang yaklaşımını daha çok seviyorum çünkü bir işlev çağrısı ile bir sürece mesaj göndermek arasındaki farkı ikisinin çok farklı sözdizimi kullandığı noktaya kadar göndermeye çalışmıyor. Ve aynı genel sözdizimi kullanılıyor olsa da, bir uzak işlem mesajı gönderimi yerel bir işlem göndermesinden çok gözle görülür şekilde farklıdır. </pimp>
JUST MY true OPINION

2
Aslında bu gerçekten iyi bir örnek veren tek cevaptır (okuduğunu anlama, millet), yani +1 alırım.
Mark E. Haase

4

İçinde bir örnek django birçok çoğa örnek ORM :

Örnek API Kullanımında, çoktan çoğa özniteliğine Yayın nesneleri eklemeden önce temel Makale nesnesini a1 .save () kaydetmeniz gerektiğine dikkat edin. Ve çoktan çoğa özniteliğini güncellemenin temel veritabanına hemen kaydettiğine, tekil bir özniteliğin güncellenmesinin .save () çağrılana kadar veritabanına yansıtılmadığına dikkat edin.

Soyutlama, tek değerli niteliklerin ve çok değerli niteliklerin sadece nitelikler olduğu bir nesne grafiğiyle çalışmamızdır. Ancak RDBS'nin bütünlük sistemi bir nesne arayüzünün ince kaplamasıyla göründüğünden, ilişkisel veritabanı destekli veri deposu olarak uygulama sızıntı yapıyor.


3

Soyutlama nedir?

Soyutlama, dünyayı basitleştirmenin bir yoludur. Bu, kaputun altında veya perdenin arkasında gerçekte ne olduğu konusunda endişelenmenize gerek olmadığı anlamına gelir. Bir şeyin aptal kanıtı olduğu anlamına gelir.

Soyutlama Örneği: 737/747 Uçurmanın Karmaşıklıkları "soyutlanmıştır"

Uçaklar çok karmaşık makinelerdir. Jet motorlarınız, oksijen sistemleriniz, elektrik sistemleriniz, iniş takımı sistemleriniz vb. Var ama pilotun jet motorunun karmaşıklığı hakkında endişelenmesine gerek yok ... hepsi "soyutlanmış". Bu, pilotun yalnızca uçağı yönlendirmek için endişelenmesi gerektiği anlamına gelir: sola gitmek için sola ve sağa gitmek için, yükseklik kazanmak için yukarı çekin ve alçalmak için aşağı itin.

Yeterince basit ...... aslında yalan söyledim: direksiyon simidini kontrol etmek biraz daha karmaşık. İdeal bir dünyada, pilotun endişelenmesi gereken tek şey budur . Ancak gerçek hayatta durum böyle değildir: Bir uçağın nasıl çalıştığını veya herhangi bir uygulama detayını bilmeden bir maymun gibi bir uçağı uçurursanız, o zaman büyük olasılıkla çarpışır ve uçaktaki herkesi öldürürsünüz.

737 Örneğinde Sızdıran Soyutlamalar

Gerçekte, bir pilotun birçok önemli şey için endişelenmesi gerekir - her şey soyutlanmamıştır: pilotlar rüzgar hızı, itme kuvveti, saldırı açıları, yakıt, irtifa, hava sorunları, alçalma açıları ve pilot doğru yöne gidiyor. Bilgisayarlar pilota bu görevlerde yardımcı olabilir, ancak her şey otomatik / basitleştirilmiş değildir.

Örneğin, pilot kolonda çok sert kalkarsa - uçak itaat eder, ancak pilot uçağı stall etme riskiyle karşı karşıya kalır ve bir kez durduğunda, yere düşmeden önce kontrolünü geri kazanmak çok zordur. .

Başka bir deyişle, pilotun başka bir şey bilmeden sadece direksiyonu kontrol etmesi yeterli değildir ......... nooooo ....... uçağın altında yatan riskleri ve sınırlamaları bilmelidir. uçmadan önce ....... uçağın nasıl çalıştığını ve uçağın nasıl uçtuğunu bilmelidir; uygulama ayrıntılarını bilmeli ..... çok sert bir şekilde yukarı çekmenin bir stall'a yol açacağını veya çok dik inişin uçağı yok edeceğini bilmelidir.

Bu şeyler soyutlanmış değil. Pek çok şey soyutlandı, ama her şey değil. Pilotun yalnızca direksiyon kolonu ve belki bir veya iki başka şey için endişelenmesi gerekiyor. Soyutlama "sızdırıyor".

Kodda Sızdıran Soyutlamalar

...... kodunuzda aynı şey var. Altta yatan uygulama ayrıntılarını bilmiyorsanız, o zaman çoğu zaman, kendinizi köşeye sıkıştıracaksınız.

İşte kodlamada bir örnek:

ORM'ler, veritabanı sorgularıyla uğraşırken pek çok zorluğu soyutlar, ancak daha önce aşağıdakilere benzer bir şey yaptıysanız

User.all.each do |user|
   puts user.name # let's print each user's name
end

O zaman, birkaç milyondan fazla kullanıcınız varsa, uygulamanızı sonlandırmanın güzel bir yolunun farkına varacaksınız. Her şey soyutlanmadı. User.all25 milyon kullanıcıyla aramanın bellek kullanımınızı artıracağını ve sorunlara yol açacağını bilmelisiniz . Bazı temel ayrıntıları bilmeniz gerekir. Soyutlama sızdırıyor.


0

Bir noktada , ölçeğiniz ve uygulamanız tarafından yönlendirilecek olan gerçeği, neden bu şekilde davrandığını anlamak için soyutlama çerçevenizin uygulama ayrıntılarına aşina olmanız gerekecek.

Örneğin, şu SQLsorguyu düşünün :

SELECT id, first_name, last_name, age, subject FROM student_details;

Ve alternatifi:

SELECT * FROM student_details;

Şimdi, mantıksal olarak eşdeğer çözümler gibi görünüyorlar, ancak birincisinin performansı, tek tek sütun adları spesifikasyonu nedeniyle daha iyi.

Önemsiz bir örnek ama sonunda Joel Spolsky'nin alıntısına geri dönüyor:

Önemsiz olmayan tüm soyutlamalar bir dereceye kadar sızdırıyor.

Bir noktada, operasyonunuzda belirli bir ölçeğe ulaşacağınız zaman, DB'nizin (SQL) çalışma şeklini optimize etmek isteyeceksiniz. Bunu yapmak için ilişkisel veritabanlarının çalışma şeklini bilmeniz gerekir. Başlangıçta size soyutlanmıştı ama sızdırıyor. Bir noktada öğrenmen gerekiyor.


-1

Bir kitaplıkta aşağıdaki koda sahip olduğumuzu varsayalım:

Object[] fetchDeviceColorAndModel(String serialNumberOfDevice)
{
    //fetch Device Color and Device Model from DB.
    //create new Object[] and set 0th field with color and 1st field with model value. 
}

Tüketici API'yi çağırdığında, bir Nesne [] alır. Tüketici, nesne dizisinin ilk alanının renk değerine sahip olduğunu ve ikinci alanın model değeri olduğunu anlamalıdır. Burada soyutlama, kütüphaneden tüketici koduna sızmıştır.

Çözümlerden biri, Cihazın Modelini ve Rengini içeren bir nesneyi döndürmektir. Tüketici, modeli ve renk değerini almak için bu nesneyi arayabilir.

DeviceColorAndModel fetchDeviceColorAndModel(String serialNumberOfTheDevice)
{
    //fetch Device Color and Device Model from DB.
    return new DeviceColorAndModel(color, model);
}

-3

Sızdıran soyutlama, durumu kapsüllemekle ilgilidir. sızdıran soyutlamanın çok basit bir örneği:

$currentTime = new DateTime();

$bankAccount1->setLastRefresh($currentTime);
$bankAccount2->setLastRefresh($currentTime);
$currentTime->setTimestamp($aTimestamp);

class BankAccount {
    // ...

    public function setLastRefresh(DateTimeImmutable $lastRefresh)
    {
        $this->lastRefresh = $lastRefresh;
    } }

ve doğru yol (sızdıran soyutlama değil):

class BankAccount
{
    // ...

    public function setLastRefresh(DateTime $lastRefresh)
    {
        $this->lastRefresh = clone $lastRefresh;
    }
}

daha fazla açıklama burada .

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.