Soru tarihçesi:
Rust'ta modül sistemi dosyalar ve modüller arasındaki hiyerarşiyi ve bağımlılıkları sıkı bir şekilde kontrol eder. Proje büyüdükçe, kod parçaları arasında karmaşık bağımlılıkları organize etme görevi ortaya çıkar (örneğin, bir modüldeki türlerin diğerinde gerekli olması durumunda). Diğer dillerde (örneğin, C/C++) bu durum döngüsel bağımlılıklara, örtük çatışmalara ve derleme hatalarına yol açabilir.
Sorun:
Rust'ta doğrudan döngüsel bağımlılıklar oluşturmak mümkün değildir (her modül yalnızca hiyerarşide yukarı ya da aşağıya referans verebilir). Dolayısıyla, örneğin, modül mod_a'dan A türü, mod_b'den B türünü kullanıyorsa ve mod_b de A türünü kullanmak istiyorsa, kötü bir durum ortaya çıkar. Yanlış bir organizasyon projenin bağımsız bileşenlere ayrılmasını engelleyebilir veya kodun kopyalanmasına neden olabilir.
Çözüm:
Rust, ortak türleri ve trait'leri ayrı modüllere veya crates'lere taşımayı ve aralarındaki ilişkilerde dış referanslar (tam nitelikli yollar) kullanmayı önerir. Bazen arayüzlerin (trait) ayrı bir ara bağlantıya taşınması işe yarar. Böylece, bağımlılıklar yönlendirilmiş hale gelir ve derleme aşamasında daha kolay analiz edilebilir.
Kod örneği:
// src/common.rs pub trait Drawable { fn draw(&self); } // src/shapes/mod.rs use crate::common::Drawable; pub struct Circle { pub r: f64 } impl Drawable for Circle { fn draw(&self) { /* ... */ } } // src/scene.rs use crate::common::Drawable; pub struct Scene<T: Drawable> { pub items: Vec<T> }
Ana özellikler:
Döngüsel bağımlılıkları aşmak için pub use kullanılabilir mi ve bir modülü kendisinden ithal edebilir misiniz?
Hayır, pub use döngüsel bağımlılıklar için çözüm değildir: sadece zaten tanımlanmış bir öğenin yeniden export edilmesi için çalışır. Henüz derlenmemiş veya bildirilmemiş bir modülü pub use etmeye çalışmak, derleme hatasına neden olur.
C/C++'da olduğu gibi modüllerin ön bildirimini yapmak neden mümkün değildir?
Rust'ta türlerin veya modüllerin önceden bildirilmesi mekanizması yoktur: tüm modüller, türler ve sabitler derleme aşamasında tanımlanmalı ve belirlenmelidir. Bu, derleyicinin tür hiyerarşisini tamamen doğrulamasına ve beklenmeyen çatışmalardan kaçınmasına olanak tanır. Ön bildirim, tür sisteminin bütünlüğünü sağlama garantilerini zayıflatır.
İki modül arasındaki yapıların birbirine karşılıklı referanslarını Box veya Rc ile uygulamak mümkün mü?
Evet, türler bağımlılık açısından (örneğin, trait veya ortak enum aracılığıyla) uyumluysa, yapıların arasında dolaylı referanslar (Box, Rc, Arc) kullanılabilir. Ancak bu, onları gerçekten döngüsel modüller oluşturmayan görünür alanlarda tanımlama gereksinimini ortadan kaldırmaz.
Projede shapes/mod.rs ve render/mod.rs adında ayrı modüller oluşturuldu, ancak ikisi de birbirlerinin türlerini doğrudan kullanmaya başladı. Bu, bağımlılık döngüsü oluşturdu ve derleyici unresolved import hatası verdi.
Artılar:
Eksiler:
Ortak türler common modülüne taşındı, trait'ler de taşındı ve bağımlılıklar tek yönlü hale geldi (scene shapes'ten, shapes ve scene common'dan bağımlı).
Artılar:
Eksiler: