Component'i "mini dialog" gibi düşünmek yanlış olmaz, ama bir istisnayla
troia-platformu-nasil-calisir yazısında component'lerden, TROIA'da fonksiyon/modül import etme kavramı olmadığı için kod tekrarını önlemenin pratik yollarından biri olarak bahsetmiştim. Şimdi bunu biraz daha derinlemesine ele alalım: component'ler, teknik olarak dialog'larla aynı altyapıyı (SYSDIALOGS, SYSDLGTEXTS, SYSDLGCODES, SYSDLGFUNCTEX, SYSCONTROLS, SYSCTLTEXTS) paylaşıyor — kontrolleri, kontrol olaylarını ve metodları olan bir yapı olması bunu mantıklı kılıyor. Ama davranış olarak dialog'dan ayrıştığı kritik bir nokta var: kapsülleme (encapsulation).
Component'in değişkenleri dışarıya kapalı
/* Bu, dialog kodundan ÇALIŞMAZ: */
DEGER = COMPONENT1@ICDEGER;
Belgelerin net ifadesiyle: bir component içinde tanımlanan değişkenlere, dialog kodundan doğrudan erişmek (okumak ya da yazmak) mümkün değil. Bunu yapmak için component'in public metodlarını çağırmanız gerekiyor — yani component'i gerçek anlamda bir "kara kutu" gibi tasarlamanız bekleniyor.
/* Component'in dışarıya açtığı bir metod üzerinden değer set etmek */
C1.SETVALUES('01.01.2016 10:10:10', '01.02.2017 10:10:10');
Bu kısıtlama ilk bakışta can sıkıcı gelebilir ama aslında iyi bir tasarım disiplinini zorluyor: component'i kullanan dialog, component'in iç yapısını bilmek zorunda kalmıyor, sadece public arayüzünü (get/set metodlarını) biliyor. Bu, .NET'teki private alan + public property mantığının TROIA'daki karşılığı gibi düşünülebilir.
Component içinde component: iç içe kullanım
/* Component A'nın içine Component B'yi yerleştirmek */
Belgeler bunun "bir component'i dialog üzerinde kullanmakla tamamen aynı süreç" olduğunu belirtiyor — araç kutusundan bir TROIA Component sürükleyip, Component özelliğinde iç component'in adını belirtiyorsunuz. Bu, karmaşık bir arayüzü (örneğin bir "adres" component'inin içinde bir "il/ilçe seçici" component'i) katmanlı şekilde inşa etmeyi mümkün kılıyor.
Component'ten dialog çağırmanın kapsam etkisi
Şaşırtıcı bir detay: bir component içinden bir dialog çağırırsanız, o dialog'da tanımlanan tüm değişkenler (kod ya da kontrol sembolleriyle) component'in kapsamına dahil olur. Yani component → dialog çağrısı, dialog'u component'in bir uzantısı gibi kapsam içine alıyor; bu davranışı bilmeden, çağrılan dialog'daki bir değişken adının component'teki bir değişkenle çakışması sürpriz bir etkileşime yol açabilir.
Component olaylarını tetiklemek: FIRECOMPONENTEVENT
FIRECOMPONENTEVENT {olayadi};
Bir component'in kendi tanımlı olaylarından birini programatik olarak tetiklemenizi sağlıyor — kullanıcı etkileşimi beklemeden, kod akışının component'in olay mantığını çalıştırmasını istediğinizde kullanılır.
Gerçek bir örnek: tarih aralığı seçen bir component
/* Component'in public SETVALUES metodu, iç ACTIVEROW üzerinden değerleri günceller. */
PARAMETERS:
DATETIME BASLANGIC,
DATETIME BITIS;
MEMBER:
/* Bu üye değişkenlere dialog kodundan doğrudan erişilemez */
DATETIME ICBASLANGIC;
DATETIME ICBITIS;
ICBASLANGIC = BASLANGIC;
ICBITIS = BITIS;
CONTROL1_TEXT = FORMATDATE(ICBASLANGIC, 'dd.MM.yyyy');
CONTROL2_TEXT = FORMATDATE(ICBITIS, 'dd.MM.yyyy');
Dialog tarafında kullanım:
TARIHSECICI1.SETVALUES('01.01.2026 00:00:00', '31.01.2026 23:59:59');
Sık yapılan hatalar
@operatörüyle component'in üye değişkenine dışarıdan erişmeye çalışmak — bu desteklenmiyor; ihtiyacınız olan veriyi component'in yazdığınız bir public getter metoduyla almanız gerekiyor.- Component'i "sadece görsel bir gruplama" gibi tasarlayıp state'i dışarıda tutmak — bu, component'in asıl avantajı olan kapsülleme ve yeniden kullanılabilirliği baştan feda etmek demektir; state component'in içinde kalmalı, dışarıya sadece davranış (metod) açılmalı.
- Component içinden çağrılan dialog'daki değişken adlarını component'in kendi değişkenleriyle çakıştırmak — kapsamın birleştiğini bilmeden aynı adı iki yerde kullanmak, beklenmedik değer üzerine yazmalara yol açabilir.
- Derin iç içe component yapılarını abartmak — component içinde component içinde component şeklinde çok katmanlı bir yapı, teknik olarak mümkün olsa da hata ayıklamayı zorlaştırır; her katmanın gerçek bir yeniden kullanım değeri olduğundan emin olun.
Sıradaki adım
Kalıtımın ikinci yüzü olan Cross mekanizmasına (recompile olmadan davranış değiştirme) ve SUPER'e bir sonraki yazıda değineceğim.
Yorumlar (0)
Yorum Yaz