En Boy Odaklı Programlama ve Nesne Odaklı Programlama


199

Buradaki ve tüm dünyadaki çoğu geliştirici gibi ben de yıllardır nesne yönelimli programlama (OOP) tekniklerini kullanarak yazılım sistemleri geliştiriyorum. Bu yönlere yönelik programlamayı (AOP) okuduğumda, geleneksel OOP'nin tamamen veya doğrudan çözemediği sorunların çoğuna hitap ettiğimde, duraklatıyorum ve düşünüyorum, gerçek mi?

Bu AOP paradigmasının anahtarlarını öğrenmeye çalışan birçok bilgiyi okudum ve aynı yerde yaşıyorum, bu yüzden gerçek dünya uygulama geliştirmedeki faydalarını daha iyi anlamak istedim.

Birinin cevabı var mı?


7
Tüm cevaplar çok iyi oldu, bu tek bir topluluk tarafından düzenlenmiş ve hepsini birleştirecek mükemmel bir durum. Hepsi aynı şeyi ama farklı şekillerde söylüyor ve toplam değere katkıda bulunan farklı örnekler kullanıyor
Vinko Vrsalovic

Yanıtlar:


323

Neden "vs"? "Vs" değildir. En Boy Odaklı programlamayı işlevsel programlamayla birlikte, aynı zamanda Nesne Odaklı programla birlikte kullanabilirsiniz. "Vs" değil, " Nesne Tabanlı Programlama ile Unsur Odaklı Programlama" dır .

Bana göre AOP bir çeşit "meta-programlama". AOP'nin yaptığı her şey, sadece daha fazla kod ekleyerek onsuz da yapılabilir. AOP sadece bu kodu yazmanızı sağlar.

Wikipedia bu meta-programlama için en iyi örneklerden birine sahiptir. Birçok "set ... ()" yöntemine sahip bir grafik sınıfınız olduğunu varsayın. Her ayar yönteminden sonra grafiklerin verileri değişti, böylece grafikler değişti ve grafiklerin ekranda güncellenmesi gerekiyor. Grafikleri yeniden boyadığınızı varsayalım, "Display.update ()" olarak adlandırmalısınız. Klasik yaklaşım bunu daha fazla kod ekleyerek çözmektir . Her set yönteminin sonunda yazıyorsunuz

void set...(...) {
    :
    :
    Display.update();
}

3 set yönteminiz varsa, bu bir sorun değildir. 200 (varsayımsal) varsa, bunu her yere eklemek çok acı verici oluyor. Ayrıca, yeni bir set yöntemi eklediğinizde, bunu sonuna kadar eklemeyi unutmayın, aksi takdirde sadece bir hata oluşturdunuz.

AOP bunu tonlarca kod eklemeden çözer, bunun yerine bir özellik eklersiniz:

after() : set() {
   Display.update();
}

Ve bu kadar! Güncelleme kodunu kendiniz yazmak yerine, sisteme bir set () nokta kesimine ulaşıldıktan sonra bu kodu çalıştırması gerektiğini ve bu kodu çalıştıracağını söylersiniz. 200 yöntemi güncellemeye gerek yok, bu kodu yeni bir set yöntemine eklemeyi unutmadığınızdan emin olmanıza gerek yok. Ek olarak sadece bir noktaya ihtiyacınız var:

pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);

Bu ne anlama geliyor? Ne olursa olsun yöntemi döndürür (ilk yıldız) ya da ne alır (üçüncü yıldız) parametreleri ne bir yöntem olarak adlandırılır eğer vasıtası Buna "set *" (herhangi bir ad kümesi sonra arkasından gelebilecek * vasıta) ve bunun MyGraphicsClass bir yöntemdir ve bu class "com.company. *" paketinin bir parçasıdır, o zaman bu bir set () nokta kesimidir. Ve ilk kodumuz " sonra bir dizi pointcut olan herhangi bir yöntemi çalıştıran, aşağıdaki kodu çalıştırın".

AOP'un sorunu burada nasıl zarif bir şekilde çözdüğünü görüyor musunuz? Aslında burada açıklanan her şey derleme zamanında yapılabilir. AOP ön işlemcisi, sınıfın kendisini derlemeden önce kaynağınızı değiştirebilir (örn. Her set-pointcut yönteminin sonuna Display.update () eklenmesi).

Bununla birlikte, bu örnek AOP'nin büyük dezavantajlarından birini de göstermektedir. AOP aslında birçok programcının " Anti-Pattern " ( Desen Karşıtı) olduğunu düşündüğü bir şey yapıyor . Kesin patern " Uzaktan hareket " olarak adlandırılır .

Uzaktan eylem, bir programın bir bölümündeki davranışın, programın başka bir bölümündeki işlemleri tanımlamak zor veya imkansız olarak çılgınca değiştiği bir anti-modeldir (tanınan bir yaygın hata).

Bir projeye yeni başlayan biri olarak, herhangi bir set yönteminin kodunu okuyabilir ve ekranı güncellemiyor gibi göründüğünü kırık olarak düşünebilirim. Ben sadece bir set-yöntemin koduna bakarak görmüyorum , çalıştırıldıktan sonra, bazı diğer kod "sihirli" ekranı güncellemek için yürütülecek. Bunu ciddi bir dezavantaj olarak görüyorum! Bir yöntemde değişiklik yapılarak garip hatalar ortaya çıkabilir. Belirli şeylerin doğru çalıştığı, ancak açık olmadığı (kodun söylediği gibi, sadece sihirli bir şekilde çalışıyorlar ... bir şekilde) olduğu kod akışını daha da anlamak gerçekten zor.

Güncelleme

Sadece açıklığa kavuşturmak için: Bazı insanlar AOP'nin kötü bir şey olduğunu ve kullanılmaması gerektiğini söylediğim izlenimine sahip olabilirler. Söylediğim bu değil! AOP aslında harika bir özellik. Ben sadece "Dikkatle kullan" diyorum. AOP yalnızca normal Unsuru ve AOP'yi aynı Unsur için karıştırırsanız sorunlara neden olur . Yukarıdaki örnekte, grafiksel bir nesnenin değerlerini güncelleme ve güncellenmiş nesneyi boyamak gibi bir amacımız var. Bu aslında tek bir özellik. Bunun yarısını normal kod, diğer yarısını en boy oran olarak kodlamak, sorunu ekleyen şeydir.

AOP'yi tamamen farklı bir yön için (örneğin, günlüğe kaydetme için) kullanırsanız, desen karşıtı sorunuyla karşılaşmazsınız. Bu durumda projeye bir acemi "Tüm bu günlük mesajları nereden geliyor? Kodda herhangi bir günlük çıkışı görmüyorum" merak edebilir, ama bu büyük bir sorun değil. Program mantığında yaptığı değişiklikler kütük tesisini zorlukla bozar ve kütük tesisinde yapılan değişiklikler program mantığını zorlukla bozar - bu yönler tamamen ayrılır. Günlüğe kaydetme için AOP kullanmanın avantajı, program kodunuzun yapması gereken her şeyi yapmaya konsantre olabilmesidir ve kodunuzun her yerde yüzlerce günlük iletisi tarafından dağıtılmasına gerek kalmadan yine de gelişmiş günlük kaydı yapabilirsiniz. Ayrıca yeni kod eklendiğinde, sihirli bir şekilde günlük iletileri doğru zamanda doğru içerikle görünecektir.

Örneğimde AOP'un iyi kullanımı, herhangi bir değer ayarlanmış bir yöntemle güncellenmişse her zaman günlüğe kaydetmek olacaktır. Bu bir anti-desen oluşturmayacak ve neredeyse hiçbir sorunun nedeni olmayacaktır.

Birisi, çok fazla sorun yaratmak için AOP'yi kolayca kötüye kullanabiliyorsanız, hepsini kullanmak kötü bir fikirdir. Ancak hangi teknoloji suistimal edilemez? Veri kapsüllemesini kötüye kullanabilir, mirası kötüye kullanabilirsiniz. Hemen hemen her kullanışlı programlama teknolojisi kötüye kullanılabilir. Sadece istismar edilemeyen özellikler içerecek şekilde sınırlı bir programlama dili düşünün; özelliklerin yalnızca başlangıçta kullanılması amaçlandığı gibi kullanılabildiği bir dil. Böyle bir dil o kadar sınırlı olurdu ki, gerçek dünya programlama için bile kullanılabilirse tartışılabilir.


4
Günlüğe kaydetme, AOP'nin Uzaktaki Eylem ile sonuçlanmadığı belirli bir örnek gibi görünmektedir. Şu anda, wikipedia, güvenlik kontrolleri gibi şeyler için en boy oranını kullanmanın bir örneği olarak, program akışını gerçekten çok daha fazla anlamasını sağlıyor.
kizzx2

7
@ kizzx2: Günlüğe kaydetmede harika bir nokta, aslında - AOP hakkında çok şey bilmeden AOP'nin gücünü şimdiye kadar gördüğüm en iyi örnek. Paylaşım için teşekkürler!
gaflar

@Mecki, Örneğiniz aşırı basitleştirilmiştir ve genel kullanım durumunu yansıtmaz. Örneğin, Display.updateherhangi bir argüman almaz. Bağımsız değişkenleri iletmemiz gerekiyorsa (örneğin, genellikle bir logişlev bir messageparametre gerektirir )? Daha sonra AOP yolunu yapmak için çok sayıda ortak kod eklememiz gerekmez mi?
Pacerier

3
@Pacerier SO bir öğretim forumu olmadığından örneğim basitleştirildi. Muhtemelen gerekli olandan çok daha ayrıntılı olan soru soranın sorusunu cevaplıyordum. AOP hakkında daha fazla bilgi edinmek istiyorsanız, bazı programcı belgelerini okumayı deneyin ve ayrıntılı bir sorunuz varsa, neden burada sormuyorsunuz? Hayır, hiçbir açıklamada, gidip çünkü yeni bir soru oluşturmak olduğunu SO tüm hakkında ne olduğunu. Eminim birisi cevaplarınızda şüphelerinizi giderebilir.
Mecki

2
@Pacerier Üzgünüm, ama ne demek istediğini göremiyorum Buraya bakın: stackoverflow.com/a/8843713/15809 Bu kod, tüm yöntem bağımsız değişken türleri ve değerleri dahil olmak üzere her genel yönteme yapılan her çağrıyı günlüğe kaydeder. Bunu tam olarak bir kez yazıyorsunuz ve herhangi bir yönteme sıfır demirbaş plakası eklendi, sadece cevapta gösterilen kod.
Mecki

29

en-boyuna yönelmiş programlama, günlük kaydı, güvenlik gibi kesişen endişeleri uygulamak için güzel bir yol sağlar. Bu kesişen konserler, birçok yerde uygulanması gereken ancak aslında iş mantığıyla hiçbir ilgisi olmayan mantık parçalarıdır.

AOP'yi OOP'un yerine, daha güzel bir eklenti olarak görmemelisiniz, bu da kodunuzu daha temiz, gevşek bağlı ve iş mantığına odaklanır. Böylece AOP uygulayarak 2 ana avantaj elde edersiniz:

  1. Her bir kaygının mantığı, kod tabanının her tarafına dağılmak yerine artık tek bir yerde.

  2. sınıflar daha temizdir, çünkü yalnızca birincil kaygıları (veya temel işlevleri) için kod içerirler ve ikincil kaygılar yönlere taşınmıştır.


27

OOP ve AOP birbirini dışlamaz. AOP, OOP'ye iyi bir katkı olabilir. AOP, yöntem kodunu bu standart kodla tıkamadan yöntemlere günlüğe kaydetme, performans izleme vb. Gibi standart kod eklemek için özellikle kullanışlıdır.


10

Bu soruya genel bir cevap olmadığını düşünüyorum, ancak dikkat edilmesi gereken bir şey, AOP'nin OOP'nin yerini almaması, ancak baskın kompozisyonun ( 1 ) (veya çapraz kesişen endişelerin) sözde zulmüne hitap eden belirli ayrışma özellikleri eklemesidir.

Belli durumlarda, belirli bir proje için kullanılacak araçları ve dilleri kontrol ettiğiniz sürece yardımcı olur, ancak aynı zamanda unsurların etkileşimi ve hala anlamak için AJDT gibi ek araçlara ihtiyaç duyulması konusunda yeni bir karmaşıklık düzeyi ekler. programınız.

: Gregor Kiczales kez ben izlerken tavsiye Google Tech Görüşmelerinde de AOP ilginç bir tanıtım konuşma yaptı Aspect Oriented Programming: Modülerlik Radikal Araştırma .


8

Her şeyden önce AOP, OOP'nin yerini almayacaktır. AOP, OOP'yi uzatır. OOP'nin fikirleri ve uygulamaları ilgili olmaya devam eder. İyi bir nesne tasarımına sahip olmak, muhtemelen onu yönleriyle genişletmeyi kolaylaştıracaktır.

Bence AOP'nin getirdiği fikirler önemli. Sınıfları değiştirmek zorunda kalmadan, programınızdaki farklı sınıflar üzerinde kesişen endişeler uygulamak için yollar bulmamız gerekiyor. Ancak AOP'nin sonunda ayrı bir araç veya teknik değil, kullandığımız diğer araçların bir parçası olacağını düşünüyorum. Bunun olduğunu zaten görüyoruz.

Ruby ve Python gibi birkaç dinamik dil, aynı sorunları çözen mixins gibi dil yapılarına sahiptir. Bu AOP'ye çok benziyor, ancak dile daha iyi entegre ediliyor.

Spring ve Castle ve diğer birkaç bağımlılık enjeksiyon çerçevesi, enjekte ettikleri sınıflara davranış ekleme seçeneklerine sahiptir. Bu, çalışma zamanı dokuma yapmanın bir yolu ve bence bunun çok fazla potansiyeli var.

AOP'yi kullanmak için tamamen yeni bir paradigma öğrenmeniz gerektiğini düşünmüyorum. Fikirler ilginçtir, ancak mevcut araçlar ve diller tarafından yavaşça emilmektedir. Sadece haberdar olun ve bu araçları deneyin.



1

Bu soruyu cevaplamak için geç kaldım ama bu benim en sevdiğim konulardan biri bu yüzden görüşümü paylaşmama izin verin.

OOP esas sizin düzenlemek için kullanılır iş mantığını ise AOP sizin düzenlemenize yardımcı olur işlevsel olmayan şeyleri Denetim, Kerestecilik, İşlem Yönetimi, Güvenlik vb gibi

Bu şekilde iş mantığınızı, kodu daha temiz yapan kurgusal olmayan mantıkla ayırabilirsiniz.

Su samuru avantajı, iş mantığına dokunmadan değişiklik için büyük esneklik sağlayan herhangi bir arabirim uygulamadan tavsiyeyi (örnek denetim) çok tutarlı bir şekilde uygulayabilmenizdir.

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.