Strateji Modelinin Avantajları


15

Eğer if / then durumunda kodunuzu yazabiliyorsanız strateji modelini kullanmak neden yararlıdır?

Örneğin: Bir TaxPayer sınıfım var ve yöntemlerinden biri farklı algoritmalar kullanarak vergileri hesaplıyor. Öyleyse neden if / then durumlarına sahip olamaz ve strateji modelini kullanmak yerine bu yöntemde hangi algoritmayı kullanacağını anlayamıyor? Ayrıca, neden TaxPayer sınıfındaki her algoritma için ayrı bir yöntem uygulayamıyorsunuz?

Ayrıca, algoritmanın çalışma zamanında değişmesi ne anlama gelir?


2
Bu ödev mi? Öyleyse bunu önceden belirtmek daha iyidir.
Fuhrmanator

2
@Fuhrmanator no it isnt
Armon Safai

Yanıtlar:


20

Bir kere, büyük if/elseblok kümeleri kolayca test edilemez . Her yeni "dal" başka bir yürütme yolu ekler ve böylece siklomatik karmaşıklığı arttırır . Kodunuzu iyice test etmek isterseniz, tüm yürütme yollarını kapsamalısınız ve her koşul en az bir test daha yazmanızı gerektirir (küçük, odaklanmış testler yazdığınız varsayılarak). Öte yandan, stratejileri uygulayan sınıflar genellikle sadece 1 kamusal yöntemi ortaya koyar ve bu da test edilmesi kolaydır.

Bu nedenle, iç içe if/elseyerleştirme ile kodunuzun tek bir kısmı için birçok test alırsınız; Strateji ile birden çok daha basit stratejinin her biri için birkaç testiniz olur. İkincisi ile, daha iyi kapsama alanına sahip olmak kolaydır, çünkü yürütme yollarını kaçırmak daha zordur.

Genişletilebilirliğe gelince , kullanıcıların kendi davranışlarını enjekte edebilecekleri bir çerçeve yazdığınızı düşünün. Örneğin, bir çeşit vergi hesaplama çerçevesi oluşturmak ve farklı ülkelerin vergi sistemlerini desteklemek istiyorsunuz. Hepsini uygulamak yerine, çerçeve kullanıcılarına bazı belirli vergilerin nasıl hesaplanacağına dair bir uygulama sağlama şansı vermek istiyorsunuz.

İşte strateji modeli:

  • Örneğin TaxCalculation, bir arayüz tanımlarsınız ve çerçeveniz vergileri hesaplamak için bu türden örnekleri kabul eder
  • Çerçevenin bir kullanıcısı, bu arabirimi uygulayan ve onu çerçevenize geçiren bir sınıf oluşturur, böylece hesaplamaların bir kısmını gerçekleştirmek için bir yol sağlar

Aynı şeyi yapamazsınız if/else, çünkü bu çerçevenin kodunu değiştirmeyi gerektirir, bu durumda artık bir çerçeve olmaz. Çerçeveler genellikle derlenmiş biçimde dağıtıldığından, bu tek seçenek olabilir.

Yine de, sadece düzenli bir kod yazsanız bile, Strateji faydalıdır çünkü niyetlerinizi daha açık hale getirir. "Bu mantık takılabilir ve koşullu" diyor, yani kullanıcı eylemlerine, yapılandırmaya ve hatta platforma bağlı olarak değişebilen birden fazla uygulama olabilir.

Strateji modelinin kullanılması okunabilirliği artırabilir , çünkü belirli bir stratejiyi uygulayan bir sınıf tipik olarak açıklayıcı bir ada sahip olmalıdır, örneğin USAIncomeTaxCalculator, if/elsebloklar "isimsiz" dir, en iyi durumda sadece yorumlanır ve yorumlar yalan söyler. Ayrıca, fr benim kişisel zevk, sadece if/elseüst üste 3 blok olması okunabilir değildir ve iç içe bloklar ile oldukça kötü olur.

Açık / kapalı prensibi yukarıdaki örnekte açıklandığı gibi, Strateji siz "değişiklik için kapalı" (bu parçaların yeniden yapılandırmaya ihtiyaç olmadan kod ( "uzantısı için açık") bazı kesimlerinde bir mantık uzatmak için izin verir, çünkü aynı zamanda çok alakalı ).


1
if/elseayrıca kod okunabilirliğini de azaltır. Strateji modeline gelince, Açık / Kapalı prensibi IMO'dan bahsetmeye değer.
Maciej Chałapuk

1
Ahlaksızlık bunun en büyük nedenidir. (Çoğu) Kodunuzdaki her dal test edilmelidir. Ne kadar çok ifparanız varsa, kodunuzda o kadar çok yol vardır, daha fazla sınama yazmanız ve bu yöntemin başarısız olması için daha fazla yol vardır. Eğer rahmetli Yogi Berra'dan alıntı yapabilirsem: "Eğer yoldaki bir çatala gelirsen al." Bu, birim testi için mükemmel bir şekilde geçerlidir. Ayrıca, birçok ififade bu koşullar için mantığı tekrarlayabileceğiniz anlamına gelir ve test yükünüzü daha da artırır ve hataların ortaya çıkma riskini artırır.
Greg Burghardt

cevap için teşekkür ederim. Öyleyse neden aynı sınıftaki farklı algoritmalar için ayrı yöntemler kullanamıyorum?
Armon Safai

Yapabilirsiniz, ancak yine de if/elseonları aramak için bir grup bloğa ihtiyacınız olacaktır (veya içlerinde bir şey yapıp yapmayacağını belirlemek için), bu yüzden belki de daha okunabilir kod dışında bir yardım değildir. Ve o zaman varsayımsal çerçevenizdeki kullanıcılar için de genişletilebilirlik yok.
scriptin

1
Test etmenin neden daha kolay olduğu konusunda daha net olabilir misiniz? Bir vaka ifadesini (veya eğer / sonra) bir polimorfik yönteme (stratejinin temeli) yeniden düzenleme örneğini test etmek oldukça kolaydır. refactoring.com/catalog/replaceConditionalWithPolymorphism.html Test edilecek tüm koşulları biliyorsam, her biri için bir test yazarım. Eğer stratejilerim varsa, her biri için bir tane oluşturmalı ve uygulamalıyım. Strateji yaklaşımının test edilmesi nasıl daha kolay? Stratejiye odaklandığınızda karmaşık iç içe geçmiş ifs hakkında konuşmuyoruz.
Fuhrmanator

5

Eğer if / then durumunda kodunuzu yazabiliyorsanız strateji modelini kullanmak neden yararlıdır?

Bazen if / then komutunu kullanmalısınız. Okunması kolay basit bir koddur.

Basit if / then koduyla ilgili iki temel sorun, açık kapalı prensibini ihlal edebilmesidir . İçeri girmeniz ve bir koşul eklemeniz veya değiştirmeniz gerekiyorsa, bu kodu değiştirirsiniz. Daha fazla koşul olmasını bekliyorsanız, yeni bir strateji eklemek daha basit / daha temiz / kırılma olasılığı daha düşüktür.

Diğer sorun ise kuplaj. İf / then komutunu kullanarak, tüm uygulamalar bu uygulamaya bağlıdır ve gelecekte değiştirilmelerini zorlaştırır. Stratejiyi kullanarak, tek bağlantı stratejinin arayüzüdür.


if / then kodundaki kodu değiştirmenin sorunu nedir? algoritmalardan birinin işlevini değiştirmeye karar verirseniz, strateji modelindeki kodu değiştirmeniz gerekmez mi?
Armon Safai

@armonsafai - stratejiyi değiştirirseniz, stratejiyi test etmeniz yeterlidir. Tüm algoritmaları değiştirirseniz, tüm algoritmaları test etmeniz gerekir. Daha da kötüsü, yeni bir strateji eklerseniz, stratejiyi test etmeniz yeterlidir. Yeni bir koşul eklerseniz, tüm koşulları test etmeniz gerekir.
Telastyn

4

Strateji, if/thenkoşullar http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html adresinde açıklandığı gibi türlere dayandığında yararlıdır.

Tip kontrol koşullarının genellikle yüksek bir siklomatik karmaşıklığı yoktur, bu yüzden Stratejinin orada olan şeyleri zorunlu olarak geliştirdiğini söyleyemem.

Stratejinin ana nedeni, kalıbı tanıtan sf.316 GoF kitabında açıklanmaktadır:

Strateji modelini şu durumlarda kullanın:

...

  • bir sınıf birçok davranışı tanımlar ve bunlar işlemlerinde çoklu koşullu ifadeler olarak görünür. Birçok koşul yerine, ilgili koşullu dalları kendi Strateji sınıflarına taşıyın.

Diğer cevaplarda belirtildiği gibi, uygun şekilde uygulanırsa Strateji modeli, kodun geri kalanında değişiklik yapılmasına gerek kalmadan yeni uzantıların (somut stratejiler) eklenmesine izin verir. Bu, Açık-Kapalı prensibi veya Korumalı Varyasyonlar prensibi olarak adlandırılır . Tabii ki, hala yeni somut stratejiyi kodlamanız gerekiyor ve müşteri kodu stratejileri eklentiler olarak tanımalı (bu önemsiz değil).

İle if/thenKoşullamalar etmesi şartına mantığı içeren sınıfın kodunu değiştirmek için gereklidir. Diğer yanıtlarda belirtildiği gibi, bazen yeniden derleme yapmadan yeni işlevler (eklentiler) eklemeyi desteklemek için karmaşıklık eklemek istemediğinizde bu sorun olmaz.


3

[...] if / then durumunda kodunuzu yazabilirseniz?

Stratejik modelin en büyük yararı budur. Koşulları yok.

Sınıflarınızın / yöntemlerinizin / işlevlerinizin olabildiğince basit ve kısa olmasını istiyorsunuz. Kısa kodun test edilmesi ve okunması çok kolaydır.

Koşullar ( if/ elseif/ else) sınıflarınızı / yöntemlerinizi / işlevlerinizi uzun yapar, çünkü genellikle bir kararın değerlendirildiği kod kararın değerlendirildiği truebölümden farklıdır false.


Strateji modelinin bir diğer büyük yararı, tüm projeniz boyunca yeniden kullanılabilir olmasıdır.

Strateji tasarım modelini kullanırken, muhtemelen bir numaralandırıcı üyesi olabilecek bir getById(int id)yöntemle, bir arabirimin istenen uygulamasını elde ettiğiniz bir çeşit IoC konteynerine sahip olmanız muhtemeldir id.

Bu, uygulamanın oluşturulması kodunuzun yalnızca bir yerinde olduğu anlamına gelir.

Daha fazla uygulama eklemek isterseniz, yeni uygulamayı getByIdyönteme eklersiniz ve bu değişiklik, kodu çağırdığınız kodun her yerine yansıtılır.

if/ elseif/ İle elsebunu yapmak imkansızdır. Yeni bir uygulama ekleyerek, yeni bir elseifblok eklemeniz ve uygulamaların kullanıldığı her yerde yapmanız gerekir, aksi takdirde uygulamayı yapısına eklemeyi unuttuğunuz için geçersiz bir kodla karşılaşabilirsiniz.


Ayrıca, algoritmanın çalışma zamanında değişmesi ne anlama gelir?

Benim örnekte, idbir kullanıcı girişi dayalı doldurulur bir değişken olabilir. Kullanıcı A düğmesine id = 2tıklarsa B düğmesine tıklarsa id = 8.

Farklı iddeğer nedeniyle , IoC kapsayıcısından farklı bir arabirim uygulaması elde edilir ve kod farklı işlemler gerçekleştirir.


cevap için teşekkür ederim. Öyleyse neden aynı sınıftaki farklı algoritmalar için ayrı yöntemler kullanamıyorum?
Armon Safai

@ArmonSafai Ayrı yöntemler gerçekten her şeyi çözer mi? Ben öyle düşünmüyorum. Sorunu bir yerden başka bir yere taşıyorsunuz ve hangi yöntemin çağrılacağına karar, bir koşulun sonucuna göre verilecek. Yine, bir if/ elseif/ elsedurumu. Öncekiyle aynı, sadece farklı bir yerde.
Andy

Peki if / then davaları ana hak mıdır? Strateji modeli için temel olarak eğer / sonra vakaları kullanmak zorunda kalmaz mıydınız?
Armon Safai

1
@ArmonSafai Hayır. idDeğişken üzerinde getByIdyöntemde belirli bir uygulamaya dönecek bir anahtarınız olacaktır. Arayüzün bir uygulamasına her ihtiyacınız olduğunda, IoC kapsayıcısının size teslim etmesini istersiniz.
Andy

1
@ArmonSafai Ayrıca getSortByEnumType(SortEnum type), bir Sortarabirimin uygulanmasını döndüren bir yönteminiz olabilir , getSortTypebir SortEnumdeğişkeni döndüren ve bir koleksiyonu parametre olarak alan bir getSortByEnumTypeyönteminiz olabilir ve yöntem, typeparametre üzerinde size doğru sıralama algoritmasını döndüren bir anahtar içerebilir . Yeni bir sıralama algoritması eklemeniz gerekiyorsa, yalnızca numaralandırmayı ve bir yöntemi düzenlemeniz gerekir. Ve hazırsınız.
Andy

2

Eğer if / then durumunda kodunuzu yazabiliyorsanız strateji modelini kullanmak neden yararlıdır?

Strateji Kalıbı, algoritmalarınızı (ayrıntılar) iş mantığınızdan (üst düzey politika) ayırmanıza olanak tanır. Bu iki şey sadece karıştırıldığında okumak kafa karıştırıcı değil, aynı zamanda değişmek için çok farklı nedenlere de sahiptir.

Burada önemli bir ekip çalışması ölçeklenebilirlik faktörü de var. Bu muhasebe paketinde birçok kişinin çalıştığı büyük bir programlama ekibi düşünün. Vergi algoritmalarının tümü TaxPayer sınıfında veya modülündeyse, birleştirme çakışmaları olası hale gelir. Birleştirme çakışmaları zaman alıcıdır ve çözüme açıktır. Bu kez drenaj ekipten verimliliği azaltır ve kötü birleşmelerin getirdiği hatalar müşterilerle güvenilirliğe zarar verir.

Ayrıca, algoritmanın çalışma zamanında değişmesi ne anlama gelir?

Çalışma zamanında değişen bir algoritma, davranışı yapılandırma veya içeriğe göre belirlenen algoritmadır. Mevcut bir if / then yaklaşımı, etkin olarak kullanılan mevcut sınıfların yeniden yüklenmesini içerdiği için bunu etkili bir şekilde etkinleştirmez. Strateji Deseni ile, her algoritmayı uygulayan strateji nesneleri kullanım sırasında oluşturulabilir. Sonuç olarak, bu algoritmalarda (hata düzeltmeleri veya geliştirmeler) değişiklikler yapılabilir ve çalışma zamanında yeniden yüklenebilir. Bu yaklaşım, sürekli kullanılabilirliği ve sıfır kesinti sürelerini serbest bırakmak için kullanılabilir.


1

if/elseKendi başına yanlış bir şey yok . Birçok durumda if/elsemantığı ifade etmenin en basit ve okunaklı yolu. Bu nedenle tarif ettiğiniz yaklaşım birçok durumda mükemmel şekilde geçerlidir. (Ayrıca mükemmel bir şekilde test edilebilir, bu yüzden bu bir sorun değildir.)

Ancak, bir strateji modelinin genel kodun sürdürülebilirliğini artırabileceği bazı özel durumlar vardır. Örneğin:

  • Belirli vergi hesaplama algoritmaları birbirinden ve temel mantıktan bağımsız olarak değişebiliyorsa. Bu durumda, değişiklikler yerelleştirileceğinden, onları farklı sınıflara ayırmak güzel olurdu.
  • Çekirdek mantık değişmeden gelecekte yeni algoritmalar eklenebilirse.
  • İki algoritma arasındaki farkın nedeni kodun diğer kısımlarını da etkiler. Vergi mükellefinin gelir grubuna göre iki algoritma arasında seçim yaptığınızı varsayalım. Bu gelir dilimi ayrıca koddaki farklı yerleri seçmenize neden oluyorsa, kodun üzerine dağılmış birden fazla if / else dalına sahip olmak yerine, gelir kümesine karşılık gelen bir stratejiyi bir kez başlatmak ve gerektiğinde çağırmak daha temiz olur.

Strateji modelinin anlamlı olması için, temel mantık ve vergi hesaplama algoritmaları arasındaki arayüz , tek tek bileşenlerden daha kararlı olmalıdır . Bir gereksinim değişikliğinin arayüzün değişmesine neden olması muhtemelse, strateji modeli aslında bir yükümlülük olabilir.

Her şey, "vergi hesaplama algoritmaları" nın onu çağıran temel mantıktan temiz bir şekilde ayrılabilip ayrılamayacağıdır. Bir strateji modelinin a ile karşılaştırıldığında bir miktar ek yükü vardır if/else, bu nedenle yatırımın buna değip değmeyeceği duruma göre karar vermeniz gerekecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.