.NET modülleri neden modül dosya adlarını ad alanlarından ayırır?


9

Şema programlama dili uygulamalarında (R6RS standardı) bir modülü aşağıdaki gibi içe aktarabilirim:

(import (abc def xyz))

Sistem bir dosyayı aramak için çalışacağız Eğer Şema modüllerini tutmak bazı dizindir. modülün kaynak kodudur ve gerekirse anında derlenir.$DIR/abc/def/xyz.sls$DIRxyz.sls

Ruby, Python ve Perl modül sistemleri bu açıdan benzerdir.

Öte yandan C # biraz daha dahil.

İlk olarak, proje bazında başvurmanız gereken dll dosyaları var. Her birine açıkça başvurmalısınız. Bu, bir dizindeki dll dosyalarını bırakarak ve C # adıyla onları almak zorunda daha söylemek daha dahil.

İkinci olarak, dll dosya adı ile dll tarafından sunulan ad alanları arasında bire bir adlandırma yazışmaları yoktur. Bu esnekliği takdir edebilirim, ama aynı zamanda kontrolden çıkabilir (ve olabilir).

Bu somutlaştırmak için, bunu söylediğimde using abc.def.xyz;, C #, C # 'ın abc/def/xyz.dllbakmayı bildiği bazı dizinde (proje bazında yapılandırılabilir) bir dosya bulmaya çalışırsa iyi olurdu .

Modülleri işlemenin Ruby, Python, Perl, Scheme yöntemini daha zarif buluyorum. Görünüşe göre, ortaya çıkan diller daha basit tasarıma sahip olma eğilimindedir.

Neden .NET / C # dünyası işleri bu şekilde, fazladan bir dolaylama ile yapıyor?


10
.NET'in montaj ve sınıf çözümleme mekanizması 10 yılı aşkın süredir gayet iyi çalışıyor. Sanırım neden bu şekilde tasarlandığı hakkında temel bir yanlış anlamadan (veya yeterli araştırmadan) yoksun - örneğin bağlama zamanında montaj yeniden yönlendirmeyi vb. Desteklemek ve diğer birçok yararlı çözüm mekanizması
Kev

Using deyiminden DLL çözümünün yan yana yürütmeyi kıracağından eminim. Ayrıca 1'e 1 varsa, mscorlib'deki tüm ad alanları için 50 dll'ye ihtiyacınız olurdu veya ad alanları fikrini bırakmak zorunda kalacaklardı
Conrad Frix

Fazladan bir dolaylama seviyesi? Hmmmmm .... dmst.aueb.gr/dds/pubs/inbook/beautiful_code/html/Spi07g.html
user541686

@gilles Soruyu düzenlediğiniz ve geliştirdiğiniz için teşekkürler!
dharmatech

Puanlarınızdan bazıları Visual Studio'ya özgüdür ve bunları bir dil ile karşılaştırmak oldukça adil değildir ( örn . Projelerdeki DLL başvuruları). Tam .NET ortamı için daha iyi bir karşılaştırma Java + Eclipse olacaktır.
Ross Patterson

Yanıtlar:


22

Çerçeve Tasarım Yönergeleri Bölüm 3.3'te aşağıdaki açıklama . Montajların ve Dll'lerin Adları, ad alanlarının ve montajların neden ayrı olduğu konusunda fikir verir.

BRAD ABRAMS CLR'nin tasarımının başlangıcında, platformun geliştirici görünümünü (ad alanları) platformun paketleme ve dağıtım görünümünden (montajlar) ayırmaya karar verdik. Bu ayırma, her birinin kendi kriterlerine göre bağımsız olarak optimize edilmesini sağlar. Örneğin, montajları performans (yükleme süresi), devreye alma, servis veya sürüm oluşturma nedenleriyle faktörlere bağlanabilirken, ad alanlarını işlevsel olarak ilişkili olan grup türlerine (ör. System.IO'daki tüm G / Ç öğeleri) faktör olarak ekleyebiliriz. .


Şimdiye kadarki en yetkili kaynak gibi görünüyor. Teşekkürler Conrad!
dharmatech

Lanet olası-yetkili yanıtı almak için +1. Ama aynı zamanda, her " neden C # <X> yapıyor? " Sorusunun da " Java <X> yaptığı gibi " merceğinden görülmesi gerekir : ... ", çünkü C # Sun'ın ve Microsoft'un Windows'ta Java için farklı gündemleri.
Ross Patterson

6

Esneklik sağlar ve talep üzerine kütüphaneleri (sorunuza modül dediğiniz şey) yüklemenize izin verir.

Bir ad alanı, birden fazla kütüphane:

Avantajlarından biri, bir kütüphaneyi kolayca diğeriyle değiştirebilmemdir. Diyelim ki bir ad alanım ve veritabanına özgü olabilecek tüm SQL sorgularını ve diğer şeyleri içeren MyCompany.MyApplication.DALbir kütüphanem var DAL.MicrosoftSQL.dll. Uygulamanın Oracle ile uyumlu olmasını istersem, sadece DAL.Oracle.dllaynı ad alanını koruyarak eklerim . Şu andan itibaren uygulamayı Microsoft SQL Server ile uyumluluk isteyen müşteriler için bir kütüphane ve Oracle kullanan müşteriler için diğer kütüphane ile sunabiliyorum.

Bu düzeyde ad alanının değiştirilmesi, ya yinelenen kodlara ya da usingher bir veritabanı için kaynak kodunun içindeki tüm s'leri değiştirme ve değiştirme zorunluluğuna yol açar .

Bir kütüphane, birden çok ad alanı:

Bir kütüphanede birden fazla isim alanına sahip olmak da okunabilirlik açısından avantajlıdır. Bir sınıfta, ad alanlarından yalnızca birini kullanırsam, bunu dosyanın üstüne koyarım.

  • Büyük bir kütüphanenin tüm ad alanlarına sahip olmak, hem kaynak kodu okuyan kişi hem de yazar için kafa karıştırıcı olacaktır, Intellisense'nin belirli bir bağlamda önerecek çok fazla şeyi vardır.

  • Daha küçük kitaplıklara sahip olmak için, dosya başına bir kitaplığın performans etkisi olacaktır: her kitaplık bellekte isteğe bağlı olarak yüklenmeli ve uygulamayı çalıştırırken sanal makine tarafından işlenmelidir; yüklenecek daha az dosya, biraz daha iyi performans anlamına gelir.


İkinci durumda, dosya adlarının ad alanlarından ayrı olmasını gerektirmez (bu tür bir ayırmaya izin vermek ayırmayı önemli ölçüde kolaylaştırır), çünkü belirli bir derleme kolayca çok sayıda alt klasöre ve dosyaya sahip olabilir. Ayrıca, aynı DLL (örneğin, ILMerge kullanarak ) içine birden fazla derleme gömmek de mümkündür . Java çalışmaları bu yaklaşımı benimser.
Brian

2

Hem "ad alanı" hem de "modül" terminolojisini aşırı yüklemeyi seçtiğiniz anlaşılıyor. Tanımlarınıza uymadıklarında şeyleri "dolaylı" olarak görmeniz sürpriz olmamalıdır.

C # dahil ad alanlarını destekleyen çoğu dilde, ad alanı bir modül değildir. Bir ad alanı, isimleri kapsamasının bir yoludur. Modüller bir kapsam belirleme davranışıdır.

Genel olarak, .Net çalışma zamanı bir modül fikrini desteklerken (örtük olarak kullandığınızdan biraz farklı bir tanımla), nadiren kullanılır; Ben sadece SharpDevelop inşa projelerde kullanılan gördüm, çoğunlukla farklı dillerde inşa modüller tek bir DLL inşa edebilirsiniz. Bunun yerine, dinamik olarak bağlı bir kitaplık kullanarak kitaplıklar oluşturuyoruz.

C # 'da, ad alanları, hepsi aynı ikili dosyada olduğu sürece herhangi bir "dolaylı katman" olmadan çözümlenir; gereken herhangi bir dolaylama, çok düşünmeniz gerekmeyen derleyici ve bağlayıcıların sorumluluğundadır. Birden çok bağımlılığı olan bir proje oluşturmaya başladığınızda, harici kitaplıklara başvurursunuz. Projeniz bir dış kitaplığa (DLL) başvurduğunda, derleyici onu sizin için bulur.

Şemada, harici bir kitaplık yüklemeniz gerekiyorsa (#%require (lib "mylib.ss")), hatırladığım gibi, ilk gibi bir şey yapmanız veya doğrudan yabancı işlev arabirimini kullanmanız gerekir. Harici ikili dosyalar kullanıyorsanız, harici ikili dosyaları çözmek için aynı miktarda işiniz vardır. Büyük olasılıkla, çoğunlukla sizden soyutlayan bir Şema tabanlı şim var, ancak üçüncü taraf bir kütüphane ile kendi entegrasyonunuzu yazmak zorunda kalırsanız, "yüklemek için biraz iş yapmanız gerekecek" " kütüphane.

Ruby'de, Modüller, Ad Alanları ve Dosya Adları aslında sandığınızdan çok daha az bağlantılıdır; LOAD_PATH işleri biraz karmaşık hale getirir ve Modül bildirimleri her yerde olabilir. Python muhtemelen Şema'da gördüğünüz şekilde bir şeyler yapmaya daha yakındır, ancak C'deki üçüncü taraf kütüphaneleri hala (küçük) bir kırışıklık ekler.

Ayrıca, Ruby, Python ve Lisp gibi dinamik olarak yazılan diller genellikle statik olarak yazılan dillerle "sözleşmeler" ile aynı yaklaşıma sahip değildir. Dinamik olarak yazılan dillerde, genellikle yalnızca kodun belirli yöntemlere yanıt vereceği bir tür "Centilmenlik anlaşması" oluşturur ve sınıflarınız aynı dili konuşuyor gibi görünüyorsa, her şey yolunda demektir. Statik olarak yazılan diller, derleme zamanında bu kuralları uygulamak için ek mekanizmalara sahiptir. C # 'da, böyle bir sözleşme kullanmak, bu arabirimlere en azından orta derecede kullanışlı bağlılık garantisi vermenizi sağlar; Ruby veya Scheme'de, çalışma zamanında çalışan testler yazarak bu sözleşmeleri doğrularsınız.

Bir yöntem çağırma işlemi çift dağıtım gerektirmediğinden, bu derleme zamanı garantilerinden ölçülebilir bir performans avantajı vardır. Bu avantajları Lisp, Ruby, JavaScript veya başka bir yerde elde etmek için, şimdi uzman VM'lerde tam zamanında statik olarak derleme sınıflarının biraz egzotik mekanizmaları olan şey gereklidir.

C # ekosisteminin hala nispeten olgunlaşmamış desteğe sahip olduğu bir şey, bu ikili bağımlılıkların yönetimi; Java, gerekli tüm bağımlılıklara sahip olduğunuzdan emin olmak için birkaç yıldır Maven'e sahipken, C #, dosyaları stratejik olarak vaktinden önce doğru yere yerleştirmeyi içeren oldukça ilkel bir MAKE benzeri yaklaşıma sahiptir.


1
Bağımlılıkların yönetimi ile ilgili olarak NuGet'e bakmak isteyebilirsiniz . İşte Phil Haack'ten güzel bir makale
Conrad Frix

Kullandığım R6RS Şeması uygulamalarında (örneğin Ikarus, Chez ve Ypsilon) bağımlılıklar kütüphane ithalatına göre otomatik olarak işlenir. Bağımlılıklar bulunur ve gerekirse gelecekteki ithalatlar için derlenir ve önbelleğe alınır.
dharmatech

Nuget'e aşina oldum ve bu yüzden benim yorumum "nispeten olgunlaşmamış"
JasonTrue
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.