15 Mayıs 2020 Cuma

Antipattern - God Object

Giriş
Çok fazla şey yapan sınıf anlamına gelir. Aynı zamanda Jack of All Trades olarak anılırlar.

1. God Object Nasıl Ortaya Çıkar?
Genellikle şöyle oluyor. Elimizde iki tane birbiriyle ilişkili nesne olsun. Bunlara A ve B diyelim. A ve B'nin birbirlerini kullandıkları metodları A'ya ekleyelim. 

Daha sonra ortaya yeni sınıflar da çıkınca lazım tüm metodlar A'da olduğu için işin kolayına kaçıp A ve C metodları da A'ye ekleniyor. Böylece A sınıfı gittikçe kalabalıklaşıyor.

Örnek
Elimizde User ve ChatRoom sınıfları olsun. Yani A ve B. A sınıfında şöyle metodlar olsun
User.JoinChatRoom()
User.WriteChatRoomMessage()
User.Authenticate()
User.JoinGroup()
Burada eksiklik, iki tane sınıf arasındaki bağı temsil eden şeyi bulamamak. Bunun için bu ilişkiyi daha kolay yöneteceğimiz yeni bir sınıf tanımlarız. Örneğin şöyle yaparız
var participant = new ChatRoomParticipant(chatRoom, user);

participant.SendMessage("Hey, everyone. I'm new here!");
participant.SendImage(File.Open("@"C:\Cat Pictures\Fluffy playing with catnip.jpg"));
participant.SendMessage("Oops. Gotta go. Someone's at my door.");
participant.LeaveChatRoom();
Burada Participant sınıfının ismi Group/Connection gibi bir şey de olabilir. Önemli olan şey One To Many ilişkide, araya many tarafını yönetecek bir kademe eklemek.

Özellikle bazı nesnelere bir sürü Many nesne takılması gerekiyor. Açıklaması şöyle
In your case, you have users vs. Chatrooms. If you have methods that concern both, you could put them into either class, not much difference.

However: You will have not only users vs. Chatrooms, you will have Users vs. bills, users vs. Support requests, users vs. 100 other things. If you do things consistently by putting methods into the user class, it will explode in size.

The other problem is that whoever maintains the chatroom code probably knows better how to add a user to a chatroom then the person maintaining the user code. Adding a user is probably not trivial and will require calls to various chatroom methods that you’d prefer to be private. So you will get simpler code written by the person who knows about chatrooms if you add the method to the chatroom class.
Eğer bu takmak işlemini yani bağlantıyı temsil edecek bir nesne kullanırsak her şey daha kolay oluyor. Açıklaması şöyle.
What is that thing that represents a user who has joined a chat room? That is the abstraction you are missing. Other answers are hinting at this.
3. God Object İçindeki Hesaplama (Computation) Metodları
Bu metodlar çok rahatlıklar God Object içinden dışarı çıkarılabilir. Özellikle stateless computation metodları bu iş için ideal.

2. God Object Çok Fazla Ara yüzü Gerçekleştirir Durum Değişir mi?
God Object diyelim ki şöyle işleri yapıyor olsun.
1. Bordro Oku,
2. Bordro Hesapla ve
3. Bordro Yazdır.

Ben bu işler için
IBordroOku,
IBordroHesapla ve
IBordroYazdır

ara yüzleri tanımlayabilirim. Ve God Object'i bu ara yüzler üzerinden kullanabilirim. Ancak bu sadece gerçekleri gizleme. God Object halen çok fazla iş yapmaktadır. Açıklaması şöyle.
This comes from low adherence to the "cohesion" requirements of the two major design methodologies; if you have an object with 23 interfaces, you have an object that knows how to be 23 different things to its users, and those 23 different things are likely not along the lines of a single task or area of the system.
Örnek
Bir projede her panel sınıfının şu arayüzleri gerçekleştirdiklerini gördüm.
- IFooPanel - diğer arayüzlerden kalıtır ve FooPanel için tüm metodlar toparlar
- IFooPanelViewData - ekran bileşenlerine getter/setter
- IFooPanelDB - veritabanı işlemleri
- IFooPanelListeners - paneldeki bileşenlere listener takma metodları
- IFooPanelUtility - panel'in kullanıcısı için yardımcı metodlar

Paneller genelde kalabalık sınıflar oluyorlar. Bu kadar arayüze de bölsek bence faydası yok.



Hiç yorum yok:

Yorum Gönder