Delphi Can

Orjinalini görmek için tıklayınız: Büyük Projelerde Form İsimleri Algoritması
Şu anda (Arşiv) modunu görüntülemektesiniz. Orjinal Sürümü Görüntüle internal link
Merhaba Arkadaşlar;

Proje büyüdükçe çok fazla modül altında alt modüller vb. olduğunda. Form ve Frame sayıları da doğru orantılı olarak artıyor, herhangi bir form veya frame ulaşmak zaman alabiliyor bu konuda sizler nasıl bir algoritma kuruyorsunuz. 

Bunlarla birlikte form içinde formlar veya form içinde frame'ler de oluyor, bu konuda izlediğiniz yöntemleri öğrenmek isterim.

Saygılarımla
Teşekkürler.
(20-10-2016, Saat: 11:56)pro_imaj Adlı Kullanıcıdan Alıntı: [ -> ]Merhaba Arkadaşlar;

Proje büyüdükçe çok fazla modül altında alt modüller vb. olduğunda. Form ve Frame sayıları da doğru orantılı olarak artıyor, herhangi bir form veya frame ulaşmak zaman alabiliyor bu konuda sizler nasıl bir algoritma kuruyorsunuz. 

Bunlarla birlikte form içinde formlar veya form içinde frame'ler de oluyor, bu konuda izlediğiniz yöntemleri öğrenmek isterim.

Saygılarımla
Teşekkürler.

Merhaba,
En önemlisi isimlendirmelerin, fonksiyon/modulü hatırlatmaya yönelik olması ve belli bir algoritmaya göre tanımlanması şarttır. 
Örnek;
Ticari bir yazılımda Personel modülümüz (veya Satış, Stok, Fatura, Rapor, Analiz vb. bir çok modül içerisinde alt modüller de olabilir.) olsun. 

Personel alt modülleri;

Personel Kayıt,
Personel Kayıt Düzenleme/Silme/Güncelleme
Personel Kariyer/Analiz

Projede Personel formu ve bunun üzerinde create edilen TFrame yapısındaki alt modüller olmalıdır. Daha esnek olması açısından da yalnızca Ana Form TForm yapısında olabilir. Diğer modüller de ana form üzerinde Layout/Panel/'ler içerisinde oluşturulacak TFrame yapıları (alt modüller) olabilir.

frm1.png


İsimlendirme ve Form/Frame organizasyonu doğru yapıldığında; hangi modül altında ne vardı gibi bir arayışa girmeden Kod editöründe çabucak ulaşabilirsiniz.

frm2.png

İyi çalışmalar...
İster büyük, ister orta çaplı olsun; projelerimde daima ara katmanlar kullanırım. Örneğin, uygulamaya yeni bir form ekleyecek isem; normal form ekler gibi ekler sonra TForm'dan türediği kısmı değiştiririm, yani araya katmanlar eklerim.

Misal; belirli bir görselliğe ya da işlevselliğe sahip formları TXForm olarak oluşturur ve o görselliği ya da işlevselliği kullanacak formlarımı TXForm'dan türetirim, bir başka görsellik ve işlevsellik için TYForm oluştutur ve ondan türetirim. Mix durumlarda TXForm'dan türeyen bir TZForm üretir ve yeni formlarımı TZForm'dan türetirim.

 Bu sayede uygulamanızdaki formlar katmanlı bir mimariye sahip olmuş olur. TXForm içine yeni bir özellik/çalışma mantığı eklediğimde otomatikman tüm formlarada uygulanmış olur. Projenizi yönetmenizi ve tek merkezden değişiklik yapmanızı kolaylaştırır.

Kısaca mümkün mertebe object oriented düşünürseniz uygulamalarınızda, OOP'nin nimetlerinden nasiplenir ve tadını aldığınız bu nimetleri bir daha da bırakmak istemezsiniz.
Çok değerli cevaplarınız için teşekkür ederim.

Fesih hocamın bahsetttiğine yakın bir kullanım yapıyorum, Tuğrul hocam bahsettiğiniz mantığı bir türlü kafamda oturtamamıştım bi 10 yıl kadar önce hala da öyle.

Form isimleri olarak bende bahsettiklerinizin yanında, her module bir numaralandırma veriyorum ve aynı module bağlı olanları bulmak daha kolay oluyor.

Örn;
MDL01StokIslemleri
MDL01StokTanim
MDL01StokEnvanter

Yukarıdaki gibi modülleri ayırırken sayısal ibare kullanıyorum ("01") modül ararken kolay oluyor fakat kod yazarken modül kodu hatırlama sorunu oluyor.
(20-10-2016, Saat: 13:46)pro_imaj Adlı Kullanıcıdan Alıntı: [ -> ]Çok değerli cevaplarınız için teşekkür ederim.

Fesih hocamın bahsetttiğine yakın bir kullanım yapıyorum, Tuğrul hocam bahsettiğiniz mantığı bir türlü kafamda oturtamamıştım bi 10 yıl kadar önce hala da öyle.

Form isimleri olarak bende bahsettiklerinizin yanında, her module bir numaralandırma veriyorum ve aynı module bağlı olanları bulmak daha kolay oluyor.

Örn;
MDL01StokIslemleri
MDL01StokTanim
MDL01StokEnvanter

Yukarıdaki gibi modülleri ayırırken sayısal ibare kullanıyorum ("01") modül ararken kolay oluyor fakat kod yazarken modül kodu hatırlama sorunu oluyor.

 Benim bahsettiğim tam olarak sizin sorduğunuz değildi zaten. Sizin bahsettiğiniz; bir nevi syntatic sugar. İşin süsü. Değişken adlandırmada ne kullanıyorsanız form adlandırmada da benzerlerini kullanabilirsiniz. İşlevsellik anlamında bunun müspet/menfi bir etkisi görülmez. Nasıl hatırlayabiliyorsanız ya da gözünüze nasıl hoş geliyor ise o şekilde kullanmanız evladır.

Lâkin, benim dediğim tamamen işlevsellik ile ilgili. Inheritance ve nispeten Polymorphism ile alakalı. Örneğin;

  TXFrame = class(TFrame, IcxLookAndFeelNotificationListener, IAbortable, ICustomRight)
    GestureManager1: TGestureManager;
   ComponentPrinter: TdxComponentPrinter;
   ADefaultGridPrinter: TdxCustomContainerReportLink;
   BasePopup: TdxRibbonRadialMenu;
   ImgExpandCollapseList: TcxImageList;
 private
   AGrid                 : TcxGridDBTableView;

   fCallProc             : TVarParamProc;

   OldMouseUpEvent       : TMouseEvent;
   fDataSetListForRights : TList<TDataSet>;
   fDataSetEventList     : TObjectList<TInternalDataSetEventItem>;

   procedure InternalBeforeDelete(DataSet : TDataSet);
   procedure InternalNewRecord(DataSet : TDataSet);

   function GetGrid: TcxGridDBTableView;
   procedure SetGrid(const Value: TcxGridDBTableView);

   function GetObject: TObject;
   procedure MasterLookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues);
   procedure MasterLookAndFeelDestroying(Sender: TcxLookAndFeel);

   procedure SetMouseUpEvent;
   procedure XFormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

   procedure HideColumnsForFilter;

   procedure WMLoadSettings(var Message : TMessage); message WM_LOAD_SETTINGS;
 protected
   IniFile     : TIniFile;
   IsChanged   : Boolean;
   fUserRight  : TUserRight;

   procedure CMChildKey(var Message: TCMChildKey); message CM_CHILDKEY;

    procedure SetLookupList;

   procedure AbortWork; virtual;

   procedure PrepareDestruction; virtual;

   procedure SaveInternalSettings;
   procedure LoadInternalSettings;

   procedure SaveSettings; virtual;
   procedure LoadSettings; virtual;

   procedure SaveDefaults;
   procedure LoadDefaults;

   procedure SaveData; virtual;

   procedure CreateWnd; override;

   procedure Expand;
   procedure Collapse;

   function GetReportLink : TBasedxReportLink; virtual;

   property Grid : TcxGridDBTableView read GetGrid write SetGrid;
   property DataSetListForRights : TList<TDataSet> read fDataSetListForRights;
 public
   class function NewInstance: TObject; override;
   class function IsEvrak : Boolean; virtual;
   class function EvrakList : TList<TPair<String, String>>; virtual; //TDictionary<String, String>; virtual;
   class function EvrakSPList : TDictionary<String, String>; virtual;

   function GetCaption : String; virtual;
   procedure ReQuery; virtual;
   procedure RefreshAfterLogin; virtual;

   procedure ShowPopup;

   procedure Alert(const UserName, Caption, Message : String);
   procedure GestureEvent(Sender: TObject; const EventInfo: TGestureEventInfo; var Handled: Boolean);

   procedure CloseThis; virtual;
   procedure Print; virtual;
   procedure ExportData; virtual;
   procedure Customize; virtual;
   procedure ResetSettings; virtual;

   function CanBrowse: Boolean; // NewInstance'da kontrol ettik.
    function CanDelete: Boolean;
   function CanExport: Boolean;
   function CanImport: Boolean;
   function CanNew: Boolean;
   function CanPrint: Boolean;
   function CanRefresh: Boolean;
   function CanSave: Boolean; // SaveData'da kontrol ettik.
   function CanSearch: Boolean;

   function CanCustomize : Boolean; virtual;
   function CanResetSettings : Boolean; virtual;
   function CanRequery : Boolean;

   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;

   procedure AfterConstruction; override;

   procedure SetLookupNull;

   property CallProc: TVarParamProc read fCallProc write fCallProc;
   property UserRight : TUserRight read fUserRight;
 end;

Yukarıdaki gibi temel bir frame'im var. Bu frame'den türeyen tüm frame'ler; buradaki static metodları aynen kullanabilecekleri gibi, virtual metodlarında çalışma tarzlarını değiştirebilirler. Misal olarak; SaveData'yı vereyim. Bu metod ilgili formun üzerindeki Kaydet button'u altında çağrılıyor ve frame üzerindeki veri girişlerini veritabanına kayıt etmek ile görevli. Sizin de takdir edeceğiniz gibi her frame üzerindeki veri kayıt işi birbirinden farklıdır.(Farklı tablolara yazar, siler günceller vs.) Bu neden ile ilgili metod virtual olarak tanımlanmış. Bu frame'den miras alan diğer frame'ler ilgili metodu override(yani çalışma şeklini özelleştiriyorlar, eziyorlar) ediyorlar. Diğer virtual metodlar için de durum benzer.

 Static metodlar ise bu frame ve bundan türeyen tüm frame'lere özgü ortak bir kod içeriyorlar.

Bu şekilde uygumanızda, araya katmanlar koyar iseniz; benim örneğimde TXForm içindeki ilgili metodların kodlarını değiştirerek tüm projeyi bir anda değiştirmiş olursunuz. Bir hata buldu iseniz, sadece bir yerde bu hatayı engelleyerek heryerde düzeltmiş olursunuz. Çalışma tarzında bir değişiklik yapacak iseniz, TXFrame 'de bunu implemente ederek her yerin etkilenmesini sağlayabilirsiniz.
Açıklayıcı bilgi için teşekkür ederim Tuğrul hocam.
Ben ameleliğe devam edeceğim alışkanlıklardan dolayı.

Bu konuyla ilgili müsait olursanız bir makale yazarsanız çok faydalı olacağı görüşündeyim Smile

Teşekkürler.
(20-10-2016, Saat: 17:00)pro_imaj Adlı Kullanıcıdan Alıntı: [ -> ]Açıklayıcı bilgi için teşekkür ederim Tuğrul hocam.
Ben ameleliğe devam edeceğim alışkanlıklardan dolayı.

Bu konuyla ilgili müsait olursanız bir makale yazarsanız çok faydalı olacağı görüşündeyim Smile

Teşekkürler.

Estağfirullah, lakin bu konular ile alakalı yeterince makale vardır zaten. Nesneye yönelik programlama(OOP), kalıtım(Inheritance), çok şekillilik(Polymorphism) ile ilgili makalelerde zaten izah etmeye çalıştığım hususlar vardır. İkinci olarak, Delphi'de Form'lar için bu konuya Visual Form Inheritance diyorlar genelde Wink
(20-10-2016, Saat: 17:14)Tuğrul HELVACI Adlı Kullanıcıdan Alıntı: [ -> ]
(20-10-2016, Saat: 17:00)pro_imaj Adlı Kullanıcıdan Alıntı: [ -> ]Açıklayıcı bilgi için teşekkür ederim Tuğrul hocam.
Ben ameleliğe devam edeceğim alışkanlıklardan dolayı.

Bu konuyla ilgili müsait olursanız bir makale yazarsanız çok faydalı olacağı görüşündeyim Smile

Teşekkürler.

Estağfirullah, lakin bu konular ile alakalı yeterince makale vardır zaten. Nesneye yönelik programlama(OOP), kalıtım(Inheritance), çok şekillilik(Polymorphism) ile ilgili makalelerde zaten izah etmeye çalıştığım hususlar vardır. İkinci olarak, Delphi'de Form'lar için bu konuya Visual Form Inheritance diyorlar genelde Wink

Tuğrul hocam şimdi  hatırladım Smile konuyu biraz araştırayım derken sizin makaleye denk geldim.
Teşekkür ederim.

İyi çalışmalar.
(20-10-2016, Saat: 13:46)pro_imaj Adlı Kullanıcıdan Alıntı: [ -> ]Örn;
MDL01StokIslemleri
MDL01StokTanim
MDL01StokEnvanter

Yukarıdaki gibi modülleri ayırırken sayısal ibare kullanıyorum ("01") modül ararken kolay oluyor fakat kod yazarken modül kodu hatırlama sorunu oluyor.

Fesih beyin önerdiği gibi, türe göre sabit bir önek(prefix) ile başlaması güzel bir isimlendirme.
Eğer formsa FormX,FormY veya Frame ise FrameX, FrameY gibi.
Eğer frameler ilgili bir kod yazmayı düşünüyorsam, Frame yazdığımda intellisence Frame ile ilgili olanları zaten listeleyecektir.

Hatta prefix unit' isimlerinden tutunda klasör isimlerine kadar uygulanabilir.

Bunun dışında bir map/eşleme mantığı yapabilinir belki...
Bir TDictionary nesnesinde Key/Value olarak bir eşleşme yapılıp, Key değerinden forma erişilebilinir. Key değeri aşağıda ki bir enum yapılabilinir.

  TFormTypes =
 (
     ftStokIslemleri
   , ftStokTanim
   , ftStokEnvanter
 );

Yukarıda ki her bir enum değeri, bir form ismine karşılık gelecek şekilde olabilir.
Enum Key değerlerinden formlara erişeceğimiz için,form isminin çok da bir önemi olmayabilir bizim için.
Ama yinede düzgün bir isim vermekte fayda var.


var
 AMap : TDictionary<TFormTypes,TClass>;

Map'leme işlemini yapalım.
procedure CreateMap();
begin
 AMap.Add(ftStokIslemleri,TForm2);
 AMap.Add(ftStokTanim,TForm3);
 AMap.Add(ftStokEnvanter,TForm4);
end;


Enum değerinden formun bulunması
function GetForm(AFormType:TFormTypes):TForm;
var
cls : TClass;
begin
 AMap.TryGetValue(AFormType,cls);
end;


Kullanmaya gelince
  CreateMap();

 GetForm(ftStokIslemleri);
 GetForm(ftStokTanim);
 GetForm(ftStokEnvanter);



"Tabi burada yazdıklarım sembolik ifadeden ibaret". Eksikler mevcut. Örneğin GetForm methodu içersinde TryGetValue sonrasında dönen class tipi ile ilgili işlemin yapılıp geriye döndürülmesi gerekiyor vs.

Yani form isimlerini hatırlamakta zorlanıyorsak, yada projede arıyorsak bunların yerine formlara karşılık gelen, daha iyi hatırlayabileceğimiz ve tek bir yere bakacağımız enum değerleri olma üzerine kurulu bir mantık.
Tıpkı herhangi bir siteye girmek istediğimizde, sitenin IP adresini yazmak yerine  sitenin domain adresini yazarak girmemiz yada telefon rehberimizde ki kayıtlı kişilere ulaşmak için ilk önce ismini bulup, sonra numarasına erişmemiz günlük hayatta sık yaptığımız insani davranışlardan...