none
Sınıf icerisinde Statik Metot Kullanımı RRS feed

  • Soru

  • Merhaba, 

    Kullandığım bir sınıfta, sınıfı çağıran client için instance gerektirmeyen işler için statik metot kullanmayı düşünüyorum. Örnek aşağıdaki kodda da olduğu gibi kullanıcı bilgisini id'ye göre getirme işlemi.

    Web uygulaması olacağı için, farklı isteklerin karışıp birbirlerinin verisini okumasını da istemiyorum. Aşağıdaki kodun statik metot kullanma açısından güvenliği hakkında yorumlarınızı almak istedim. (public static User getUserByUserId(int userId) kısmı)

    	public class User
    	{
    		public int UserId { get; set; }
    		public string UserName { get; set; }
    		public string Password { get; set; }
    		public string Email { get; set; }
    		public string Status { get; set; }
    
    
    		public User()
    		{
    			
    		}
    
    		public User(string userName, string password, string email, string status)
    		{
    			this.UserName = userName;
    			this.Password = password;
    			this.Email = email;
    			this.Status = status;
    		}
    
    		public User createUser()
    		{
    			//TODO create user
    			return null;
    		}
    
    		public static User getUserByUserId(int userId)
    		{
    			User user = new User();
    			//TODO veritabanından kullanıcı bilgilerini id'ye göre çek ve user nesnesini doldur.
    			return user;
    		}
    
    	}
    

    Metodu çağıracak kısım;

    		static void Main(string[] args)
    		{
    			User ilker = User.getUserByUserId(3);
    		}


    30 Ocak 2017 Pazartesi 10:24

Yanıtlar


  • User aslında bir Model / DTO ve hatta  POCO değil mi? Herhangi bir iş yapması -kendi türdeşini getirmesi dahi- pek mantıklı gözükmüyor. Sonuçta bu türden bir nesneyi istemciye yolladığında bu metotlara sahip olmayacak.

    Verilerin karışması işine gelince, static metot kullandığında değil de static değişken kullandığında bu durum ile karşılaşırsın. Ne kullandığına dikkat etmen ve test etmen önemli.

    Bunun yerine Factory pattern kullanabilirsin. Ben patterni biraz daha sadeleştirip senin için şu hale getirdim :

    Veriyi DB den çektiğin kısımda ise Repository Pattern uygulaman daha iyi olacaktır.

    void Main()
    {
    
        MyUser myUser = EntityFactory.GetById<MyUser>(4);
     
    }
    
    
    public abstract class Entity {}
    
    public sealed class MyUser : Entity
    {
        public int UserId { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public string Status { get; set; }
    }
    
    public static class EntityFactory
    {
        public static T GetById<T>(int id) where T : Entity
        {
            if (typeof(T) == typeof(MyUser))
            {
                return new MyUser() { UserId = id } as T;
            }
            return null;
        }
    }

    30 Ocak 2017 Pazartesi 11:17

Tüm Yanıtlar


  • User aslında bir Model / DTO ve hatta  POCO değil mi? Herhangi bir iş yapması -kendi türdeşini getirmesi dahi- pek mantıklı gözükmüyor. Sonuçta bu türden bir nesneyi istemciye yolladığında bu metotlara sahip olmayacak.

    Verilerin karışması işine gelince, static metot kullandığında değil de static değişken kullandığında bu durum ile karşılaşırsın. Ne kullandığına dikkat etmen ve test etmen önemli.

    Bunun yerine Factory pattern kullanabilirsin. Ben patterni biraz daha sadeleştirip senin için şu hale getirdim :

    Veriyi DB den çektiğin kısımda ise Repository Pattern uygulaman daha iyi olacaktır.

    void Main()
    {
    
        MyUser myUser = EntityFactory.GetById<MyUser>(4);
     
    }
    
    
    public abstract class Entity {}
    
    public sealed class MyUser : Entity
    {
        public int UserId { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        public string Status { get; set; }
    }
    
    public static class EntityFactory
    {
        public static T GetById<T>(int id) where T : Entity
        {
            if (typeof(T) == typeof(MyUser))
            {
                return new MyUser() { UserId = id } as T;
            }
            return null;
        }
    }

    30 Ocak 2017 Pazartesi 11:17
  • Çok teşekkür ediyorum.

    Aslında kafamdaki diğer bir soru işareti de buydu fakat net olarak problemi ifade edemediğim için soramıyordum.

    Pattern kitaplarında genelde (araba üret,  vs.. gibi örneklerde) class içindeki metotlara bazı sorumluluklar yüklüyorlar fakat gerçek hayatta kullandığımız veritabanı bağlantısı vs.. gibi katmanları bu patternlerde bir türlü yerleştiremiyordum açıklamanız çok yardımcı oldu tekrar teşekkür ederim.

    Bu doğrultuda Model olarak tasarladığımız sınıflar için doğru yaklaşım metot kullanımından kaçınmak mıdır ya da hangi tür metotları kullanabiliriz ? 

    30 Ocak 2017 Pazartesi 13:46
  • Sınıf uygulamadan dışarı/içeri veri aktarma amacı güdüyorsa bu şekilde kullanman uygun olur. POCO, DTO gibi terimleri araştır. 

    Bu tip sınıflara hiç bir iş yüklememek en doğrusu olacaktır. Kendi iç mantığında bu sınıflara işler yaptırmak istiyorsan Extension Method, Attribute kullanımlarını düşünebilirsin. Zorda kalırsan da Decorator pattern'i imdadına yetişecektir. :)

    30 Ocak 2017 Pazartesi 14:10
  • Tekrar teşekkür ederim. Çok faydalı oldu yanıtlarınız.

    Çok vaktinizi aldım lütfen kusura bakmayın ama kurmayı planladığım yapı ile ilgili iki sorum daha olacak. (Umarım son iki soru olur çünkü mahçup oldum size karşı :) ) 

    1- Projede 3 katman planlıyorum. Veri katmanı, model katmanı ve Controller katmanı. 

    Veri katmanında veritabanı ile ilgili CRUD işlemler olacak. 

    Model katmanında sizden aldığım geri bildirim üzerine sınıflar sadece property'leri ile tanımlı olacak. Herhangi bir metotları bulunmayacak.

    Controller web servisimin dışarı açılan metotlarının bulunacağı katman olacak. Bu metotlar içerisinde Business kısmını da halletmeyi düşünüyorum. Sizce uygun mudur yoksa business ile web servis metotlarını da ayırmalı mıyım ? 


    Örnek olarak user sınıfı için data katmanında createUser metodum olduğunu düşünelim. Bu metot, Single responsibility prensibinden dolayı kendisine parametre olarak gelen User nesnesini sadece veritabanına kayıt mı yapmalı yoksa bu kullanıcı adında daha önceden kayıt var mı diye sorgulamayı da kendisi mi yapmalı ? Eğer sadece veritabanına kayıt işi ile ilgilenecekse bu tür kontrolleri de Controller katmanında yapmayı düşünüyorum. Sizce doğru mudur ?  

    2- Model katmanında metotları kaldırdığım için, controller katmanı direk olarak veri katmanına erişebilecek. Aslında ben controller => model => veri katmanı diye düşünmüştüm. Model'de tanımlı metotlar aradaki iletişimi sağlıyordu. Controller ile veri katmanının tek yönlü olarak iletişimde olması bir problem teşkil eder mi ? 


    31 Ocak 2017 Salı 05:43
  • Ben bussinessı da ayırmayı tercih ediyorum. Servisi ne kadar iyi kurgularsan kurgula kullanım sırasında gelen talepler doğrultusunda zamanla tutarsız bir yapıya dönüşüyor. Bu durumda v2,v3 servislerini aynı BLLi kullanarak hızlıca çıkartabiliyorsun. BLLde güncelleme yapınca tüm versiyonların güncellenmiş oluyor. 

    Ayrıca prensip açısından da daha doğru, her sınıfın sadece bir işi olmalı.

    31 Ocak 2017 Salı 06:32
  • Ben bussinessı da ayırmayı tercih ediyorum. Servisi ne kadar iyi kurgularsan kurgula kullanım sırasında gelen talepler doğrultusunda zamanla tutarsız bir yapıya dönüşüyor. Bu durumda v2,v3 servislerini aynı BLLi kullanarak hızlıca çıkartabiliyorsun. BLLde güncelleme yapınca tüm versiyonların güncellenmiş oluyor. 

    Ayrıca prensip açısından da daha doğru, her sınıfın sadece bir işi olmalı.

    Teşekkür ederim yanıtlarınız için

    31 Ocak 2017 Salı 11:28