5 Aralık 2024 Perşembe

Developer Mülakat Soruları - 4 - Patterns & Principles

    Selamün Aleyküm Arkadaşlar,
    Bildiğiniz gibi developer mülakat sorularında daha önce 3 yazı toparlamıştık. Birinci ve ikincisinde
yazılım ile ilgili sorular var iken, üçüncüsünde veri tabanı ve mikroservis mimarisiyle ilgili sorular vardı.
Şimdi ise yazılımdaki tasarım şablonları ve prensiplerini toparlayarak dördüncü yazımıza başlıyoruz.
Çok uzun süredir toplamış olduğum notları toparluyorum, bazılarını nereden buldum, nereden not aldım/
kopyaladım hatırlamıyorum, üzerinden geçip güzel bir şekilde toparlama çalıştım. Hem kendime hem
okuyanlara faydalı olur inşaAllah. Bir duanızı alırım :) Hazırsak başlayalım
A- Gof Patterns (Gördüğüm en iyi Türkçe kaynak olabilir, burayı ziyaret edebilirsiniz, #FreePalestine)
Creational, Structural ve Behivarol 3 başlık altında toplam 23 tasarım şablonu var. Bunların dışında da
elbet birçok tasarım şablonu bulunuyor. Herhangi bir kurala bağlı olmaksızın notlarımı paylaşıyor olacağım.


C - Single: Bir nesnenin bir kereliğine oluşturulup diğer isteklerde aynı nesneyi almasıdır.
    
     2.Not: Nesnenin kimin tarafından oluşturulacağı ve buna kimlerin erişebileceği problemine tek nesne oluşturarak her yerden erişilmesini sağlayan yöntemdir. Başka yerde aynı nesnesnin oluşmaması için kurucu metod private olmalıdır.

C - Factory: Inteface aracılığıyla alt sınıflara ulaşmayı hedefler.

    2.Not: İstemcinin(client) haberi olmaması gereken yapıları izole eder. Her defasında yeni bir nesne
oluşturmaktansa bunu istemciden habersiz bir yerde hallediyoruz. Oluşturduğumuz sınıfıntan birden
fazla nesne oluşturuluyorsa bunu parametre kontrolü yaparak anlayabiliriz.

C - Abstract factory: Çoklu factory yapısını soyut bir yapı altına toplar. Çalışma zamanında (run-time)
hangi sınıfın çağrılacağı belirlenir. Burada soyutlama low coupling avantajı var, fakat her ürün için
     somut sınıf eklenmesi ise dezavantajıdır.
C - Builder: Karmaşık yapılandırıcılar (constructor) yerine nesne üzerinden property setlemesini sağlar.
build.set.set gibi bir kullanımı var.

C - Prototype: Aynı sınıftan üretilen ve birçok ortak özellikleri olan nesnelerin karmaşıklığını azaltıp
maliyetini düşürmeyi hedefler.
S - Composite: Hiyerarşi yapısı kurar. İterate kullanır.

    2.Not: Composite (Bileşik Nesne) : Nesne gruplarının tekil olabileceği gibi bileşik de olabildiği durumlarda aynı arayüzün içine bu nesneleri içeren bir liste yerleştirerek çözme yöntemidir.

İndirim işlemlerinde sıkça görülen problem farklı indirimlerin birlikte nasıl uygulanacağı bu yöntemle çözülebilir. Müşteriden mi yana olsun , şirketten mi yana veya bu tür isteklere farklı sınıflardan çözümler üretebilir. 

S - Proxy: Bir tür cache'leme yapısı sunar. Singleton yapısından farklı olarak lazy mantığında çalışır.
Yani siz çağırmadığınız sürece çalışmaz.
S - Adapter: Dışarıdan gelen servisin sisteme göre adapte edilmesini sağlar. Unit test yazmayı kolaylaştırır.
Yoksa integration test yapmak durumunda kalır, istemediğimiz bağımlılıklar oluşur.

    2.Not: Adapter (Uyarlayan): Bir arayüzü başka işleve dönüştürmektir.  İstenilen işi yapan fakat farklı arayüzleri benzer olan arayüzleri adaptör nesnesi oluşturarak başka bir arayüze çevirebiliriz. Özetle eski ve karışık sistemi tek nesne üzerinden yönetmek diyebiliriz.

S - Facade: Nesnelerin alt sistemlerine basitleştirilmiş bir arayüz sağlar. Alt sistemin kendisi Facade
arayüzünden habersizdir. Alt sistem içerisinde tüm nesneler doğrudan birbirleriyle iletişim kurabilirler.
Çoklu parametreyi modele çekmek gibi düşünülebilir.

    2.Not: Facade (Önyüz) : Karışık, değişen veya değişmesi muhtemel alt yapıya bağlanmayı tek ortak nokta üzerinden erişilmesini sağlar. Sistemden bir şey değiştiğinde önyüz değişecek ve asıl sistem bundan etkilenmeyecektir. Bu önyüz nesnesi singleton özelliğine sahiptir. 
S - Decorator: Dinamik olarka nesneseye sorumluluk yükler. Ürüne, şirket bazlı indirim yapılmasını
sağlar.

    2.Not: Strateji kalıbı ile çözülmeyen , nesneye dinamik davranış eklenerek çözebilen şablondur. 

Strateji kalıbında aynı işlemi farklı şekillerde yapan sınıflar varken burada farklı işlemler farklı sıralarda olabilir. Fakat bu farklı işlemlerin de çeşitleri varsa bu kalıp yetersiz kalır. Tüm bu işlemler aynı soyut sınıftan türetilir. Daha sonra ana sınıf (somut) da buna dahil edilerek işlemler listeye eklenir ve sırayla çağrılır. Sıraya konma işleminde somut/dekörator -> deköratör -> somut bu dizilime dikkat edilmelidir.

S - Bridge: Belirlenen nesneyi çağırdığımiz yerde set ederiz. Build time'de çalışır.

    2.Not: Bridge (Köprü): Soyutlama ve gerçekleme işlemlerinin birbirinden bağımsız tutularak ikisinin de değiştirme özelliği tanıyan şablondur. En karışık ve en çok kullanılan yöntemlerdendir. Bunu çözebilmenin birden fazla yolu var. Bunlar da nesne yönelimli programlamaya uygundur fakat tasarım değiştikçe bunları yönetme güçleşir. O yüzden köprü şablonunu kullanmak en doğru yol olacaktır. Bu konu oldukça geniştir. Köprüye gelinceye kadar yapılmaması gereken işler vardır. Yaptığını şeyin mantığını daha iyi anlamak açısından bunların neden uygun olmayacağını görmek çok önemlidir.
B - Strategy: Bridge ile farkı yok gibi. Setlenen sınıfa göre metot çağrılır. Çalışma anında (run-time) çalışır.
    
    2.Not: Birbiriyle ilgili fakat farklılık gösteren (pos cihazlarındaki farklı indirimler gibi) algoritmaları farklı sınıf aynı arayüz içinde implemente edilmesi yöntemidir. 

B - Visitor: Belirli bir hiyerarşi sistemine göre işlevler yapılır. CoR ile benzerlik içerir.

    2.Not: Sınfa eklenen metodların düzenlemesiyle ilgilidir. Bunun için 2 yöntem var. Ya inteface eklersin -
bu metodu kullanmayan sınıflar olursa ISP'ye uymaz, veyahut tek tek sınıflara eklersin o da kod
bakımını zorlaştırır. Bunların yerine bu şablon tercih edilir.
B - Observer: Kendisini takip eden abonelere herhangi bir değişiklikte haber vermeyi sağlar.
Mvc'de backend'de veri değiştiğinde ön tarafın bundan haberdar olması gibi. Observer’ın amacı ise
bazı nesneler ile onlara bağlı olan diğer nesneler arasında dinamik tek yönlü bağlantıyı kurmaktır.

    2.Not (Gözlemci): Bir olay veya işlem olduğunda kendisinden haber bekleyen birimlere haber vermeyi sağlayan yöntemdir. Haber bekleyen birime nesne ile bağlanmaktansa interface ile kendisine bağlanan ve haber beklediğini bildiren birimlere haber vermeyi amaçlar. Bu sayede bağımlılığı azaltır. Masaüstü event’lerde bu yöntem kullanılır.
B - Chain of responbility: Hiyerarşi tarzında işlemler olduğunda kullanılması gereken şablondur. B - Memento: Bir hafıza oluşturarak verileri eski haline almayı sağlar. Ctrl+Z gibi düşünülebilir. B - Command: Crtl+Z işini yapan bir tasarım kalıbı. Memento şablona benzer. Tüm komutları toplar sonra
hepsini aynı anda yapar. Sepete ürün ekle en son hepsini aynı anda satın al mantığında düşünebiliriz. B - Template method: Aynı işi farklı değerlerle kullanmak istediğimizde kullanırız. Birden çok metdou
aynı taslak altında çalıştırırız.

    2.Not: Bir operasyonu gerçekleştirmek için gerekli olan adımlar ve bu adımları çalıştıracak metotlar
abstract bir sınıfa tanımlanır. Bu abstract sınıfı uygulayan gerçek sınıflar gerekli adımları override eder
ve abstract sınıfında bu adımları kullanan metotlar çağrılarak işlem gerçekleştirilir. Böylece kod
tekrarının önüne geçilmiş olunur.
B - State: Nesnenin durumuma göre iş yapılmasını sağlar. B - Iterator: Sırasıyla sonraki elemena erişmeyi sağlar.

B - Mediator: Bir tür organizator işlevi yapar. Ara katman olur. Nesneler(sistemler) arasında iletişim
merkezidir. Nesneler yalnızca Mediator nesnesini bilir ve birbirleriyle doğrudan iletişim kurmazlar.
Mediator’ın birincil amacı nesneler arasındaki karşılıklı bağımlılıkları ortadan kaldırmaktır.
Bunun için bu nesneleri tek bir Mediator nesneye bağımlı hale getiririz. Bunda en çok verilen örnek
ise uçakların birbiriyle değil kule gibi merkezi bir yapı ile konuşması olarak gösterilir.
B- Interpreter: Belirli bir düzene sahip olan metinlerin sayısal ve mantıksal oluşmasını sağlar.


B- Microservice Patterns: Mikroservis ile birlikte kullanılan bazı tasarım şablonlarına göz atacağız.
                                                                            Kaynak

Saga pattern: Dağıtık sistemlerde veri tutarlığını sağlamaya yönelik bir tasarım kalıbıdır.


C - Anti Patterns: Doğru sanılan ya da zamanla anti pattern olan tasarım şablonlardan bahsedeceğiz.
   Buradaki notlarımı buradan aldığımı bulabildim. Burak Selim Hoca'ya yine sevgiler/saygılar

                                                                Yukarıdaki yazıdan alındı.


Lava Flow - Programming: Lüzumsuz veya düşük kaliteli kodları, kaldırma maliyetlerinin yüksek olması
veya ön görülemeyen sebepler nedeniyle barındırmaya devam etme

Cargo Cult Programming - Programming: Desen ve metodları ne/nasıl/niçin olduğunu anlamadan kullanma

Boat Anchor – Programming: Herhangi bir amaçla kullanılmayan bir sistem parçasını tutmak/unutma

Vendor Lock-In – Organizational: Bir sistemin dışarıdan sağlanan bir bileşene aşırı bağımlı
tasarlanması/geliştirilmesi/yürütülmesi

Analysis Paralysis - Organizational: Bir projenin analizine orantısız ölçüde yüksek efor harcamak.

Reinventing the Square Wheel - Methodological: Var olan bir çözüm yerine ondan daha kötü olan özel
bir çözüm üretme hatasına düşmek.

Golden Hammer – Methodological: Favori bir çözümün evrensel anlamda kabul gördüğünü varsaymak.

OverEngineering – Project Management: Bir projeyi gereğinden daha karmaşık ve güçlü hale getirmek
için kaynak harcamak.

Magic PushButton – Software Design: Soyutlama kullanmadan arayüz üzerinde doğrudan uygulama
mantığı kodlamak. Ör, Masaustu programlarndaki click programcilig
Prensipler: Burada yazılım prensiplerinden bazılarından herhangi bir kural gözetmeksizin bahsedeceğiz.
Buradaki listede birçokları var.

KISS (Keep it simple stupid): Yapacağınız işi basit düşünün, küçük başlayın, sonra işiniz tutarsa
büyütürsünüz mantığıyla olaylara ve kodlara yaklaşmayı gerektiriyor. Fazlası over-engineering olur.

WET (Write everything twice): “Her şeyi iki defa yaz” prensibidir. İki defa yazılan şey için tasarım
yapmaya vakit kaybı olarak bakılır. Daha fazla bu durum tekrarlanırsa o zaman buna kafa yor diyor. DRY (Don’t repeat yourself) Prensibi bu prensibin zıttı olan WET prensibine tepki olarak ortaya atılmış.
Kendini tekrarlama diyerek, olması gerekeni yap ve kod tekrarına düşmeye karşı çıkar.
Composition > Inheritance” veya “Composition Over Inheritance” karmaşık görünmese rağmen
güç durumlarla başa çıkmaya yardımcı olan bir kodlama prensibi. Separation of Concerns: Buna göre programın içindeki bölümler kısımlara ayrılmalı ve bu kısımlar
bir diğerinin ne yaptığından haberdar olmamalıdır. MVC en büyük örneğidir.

Dependency Inversion Principle: Sınıflar arası bağımlılıkların asgari olması gerektiğini söyler.

Inversion of Control: Bağımlılıkların dışarıya devretmesi gerektiğini söyler. En yaygın yöntemi DI'dir.

YAGNI (You aren’t gonna need it): “Salla gitsin, buna nasıl olsa ihtiyacın olmayacak” prensibidir.
Bu prensibe göre gelecekte ihtiyaç duyabileceğinizi düşündüğünüz hiçbir fonksiyonel kodu
sisteme eklemiyorsunuz (Eklerseniz yine over-engineering olur). Avoid Premature Optimization: Sisteminizin henüz yavaş olduğunu görmeden
“Dur ben bunu hızlandırayım” ifadesi altında yaptığınız optimizasyonların tamamını içeriyor.

Reuse Release Equivalence: Bir komponent değiştirilmeden farklı projelerde kullanılması gerekir.

Common Closure: Birbiriyle ilgili yapıların birlikte bulunması gerektiğini savunur. Yani bir yerde
yapılacak değişiklik ilgili yerlerle de birlikte yapılabilinmelidir.



D - Diğerleri

Depency Injection: somut sınıflara olan bağımlılığı ortadan kaldırır. IoC için Ninja vb araçlar kullanılabilir.
Null object: Testte kullanılacak objenin null geçebilmesini sağlar. Specification pattern: En basit haliyle, istediğimiz domain bilgilerini/kurallarını encapsulate ederek
tekrar kullanılabilir parçalar oluşturabilmemize olanak sağlayan bir tasarım şablonu diyebiliriz.
Genellikle filtreleme için kullanılır. Böylece uygulama içerisinde aynı domain kuralına ait
lambda ifadeleri yaymak yerine, single responsibility prensibine bağlı kalarak ilgili tüm domain
kurallarını tek bir noktadan yönetip tekrar kullanılabilir bir hale getirebilmekteyiz.

Multiton: Singleton geliştirilmiş hali gibi düşünebilirsiniz. Belli gruplar için aynı nesneyi üretir.

Concrete Factory : (Abstract Factory is harder than) : Oluşturulan adaptör nesnesinin kimden oluşacağı problemine çözüm arar. Bu nesnelerin uyumluluğunı artırmak ve diğer işlemlerden ayrılmak makasadıyla yapay(normal/sanal) sınıf olan fabrika sınıfına atanır. Özetle nesnelerin oluşturulmasını yönetir.


E - Birbirine alternatif veya karıştırılacak bazı tasarım kalıpları

Builder vs Abstract Factory: Builder deseni istemcinin ihtiyaç duyduğu ve üretimi karmaşık olan
nesnelerin adım adım oluşturulmasını esas almaktadır. Abstract Factory üretimin karmaşık veya basit
olmasına bakmaksızın bir ürün aile grubunu baz alır. Builder ürünü son adımda üretmeyi önerirken,
Abstract Factory kalıbı ürünün anında üretilip istemciye verilmesine odaklanır. Abstract Factory
deseninde yer alan fabrikanın metotları fabrikaya ait nesnelerin yaratılmasından sorumludur.
Builder deseninde istemci, ürünlerin ne şekilde oluşturulacağına Builder kalıbının metotları ile karar
verir ve üretilen nesneyi Builder' dan tekrar talep eder.

Decator vs Strategy: Asloan işlemin yanında farklı işlemler yapılabilecekse bu yöntemi kullanmak            uygundur. Fakat aslonan işlemin farklı çalışma tarzları varsa strateji kullanılabilir.

Adapter vs Facade : Façade tek nesne ile basitleştirme yaparken, adapte polimorfizm ile olanı benzetme         işlemine tabi tutar.
Strategy Pattern(run time) vs Template Method Pattern(design): Strategy algoritmayı kullanma üzerine
odaklanırken (interface ile çalışır), Template ise var olan yapıyı ezerek onu kullanmaya odaklanır. Adapter Pattern vs Bridge Pattern: İkisi de soyutlama yaparak sistemi esnek tutsa da Adapter eski olan
bir sistemi modern sisteme uyumlu hale getirmeyi hedeflerken Bridge ise yeni oluşturulan bir sistemin
daha esnek olarak genişlemesine olanak sağlar. State Pattern vs Strategy Pattern: Birbirine benzer çok notkası olsa da State durumlar arası geçiş
sağlarken strategy algoritmalar arası geçiş sağlar. Özetle biri durum üzerinden sistemi inşa ederken
diğeri dışarıdan gelen istekler üzerinden sistemi inşa eder.
Proxy Pattern vs Decorator Pattern: Her iki parrern de sarmalamayı run-time'de tercih etse de proxy bir
    nesneye erişimi konu edenirken decorator ise onu genişletmeyi hedefler. Adapter Pattern vs Facade Pattern: Ortak amaçları kodu basitleştirip onu kullanmayı kolay hale getirmek.
Kapsam olarak adapter tek bir nesneyi veya sınıfı konu edinirken facade daha fazlası konu edenierek
sistemi basitleşmeyi hedef alır. Özetle biri sistemler arası uyumluluğu, diğer basitliği sağlar.
Strategy Pattern vs State Pattern: Temelde her ikisi de nesnenin davranışı değiştirir. Strategy farklı
    algoritmalarla kullanıcıdan gelen isteklere göre bunu yaparken, State nesneyi bundan bağımsız otomatik
olarak durumunu değiştirerek yapar.


    Yazıyı kolaylığın önemine vurgu yapan aşağıdaki hadis ile bitirelim
"Din kolaydır. Kimse ona zorluk getirmeye kalkmasın. Kimse dinin sınırlarını zorlayarak  
ağırlaştırmaya çalışırsa, o din onu yenip devirecektir. O yüzden doğru yolda sabırla ilerleyin."  
(Buhari, Kitab-ül İlim, Hadis No: 39)


Hiç yorum yok:

Yorum Gönder