Yöntemlerimin ne kadar tekrar kullanılabilir olması gerektiğini nasıl bilebilirim? [kapalı]


133

Evde kendi işime bakıyorum ve karım bana geliyor ve diyor

Tatlım .. Dünyadaki tüm Gün Işık Tasarruflarını konsolda 2018 için basabilir misiniz? Bir şeyi kontrol etmem gerekiyor.

Ve çok mutluyum çünkü Java deneyimim boyunca hayatım boyunca beklediğim şey buydu ve:

import java.time.*;
import java.util.Set;

class App {
    void dayLightSavings() {
        final Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        availableZoneIds.forEach(
            zoneId -> {
                LocalDateTime dateTime = LocalDateTime.of(
                    LocalDate.of(2018, 1, 1), 
                    LocalTime.of(0, 0, 0)
                );
                ZonedDateTime now = ZonedDateTime.of(dateTime, ZoneId.of(zoneId));
                while (2018 == now.getYear()) {
                    int hour = now.getHour();
                    now = now.plusHours(1);
                    if (now.getHour() == hour) {
                        System.out.println(now);
                    }
                }
            }
        );
    }
}

Ama sonra o sadece bir etik eğitimli yazılım mühendisi olup olmadığı beni test söylüyor ve o zamandan beri (alınan değilim gibi görünüyor bana söyler burada ) ..

Etik olarak eğitilmiş hiçbir yazılım mühendisinin bir DestroyBaghdad prosedürü yazma konusunda hiçbir zaman rıza göstermeyeceği belirtilmelidir. Temel mesleki etik onun yerine Bağdat'ın parametre olarak verilebileceği bir DestroyCity prosedürü yazmasını gerektirir.

Ve ben iyiyim, tamam, tamam, beni yakaladın .. İstediğin yıl geç , buraya git:

import java.time.*;
import java.util.Set;

class App {
    void dayLightSavings(int year) {
        final Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        availableZoneIds.forEach(
            zoneId -> {
                LocalDateTime dateTime = LocalDateTime.of(
                    LocalDate.of(year, 1, 1), 
                    LocalTime.of(0, 0, 0)
                );
                ZonedDateTime now = ZonedDateTime.of(dateTime, ZoneId.of(zoneId));
                while (year == now.getYear()) {
                    // rest is same..

Ama ne kadar (ve ne) parametreleştireceğimi nasıl bilebilirim? Ne de olsa, diyebilir ki ..

  • Özel bir dize biçimlendiricisi geçmek istiyor, belki de zaten yazdırdığım biçimi beğenmiyor: 2018-10-28T02:00+01:00[Arctic/Longyearbyen]

void dayLightSavings(int year, DateTimeFormatter dtf)

  • sadece belirli ay aralıklarında ilgileniyor

void dayLightSavings(int year, DateTimeFormatter dtf, int monthStart, int monthEnd)

  • belli saatlerde ilgileniyor

void dayLightSavings(int year, DateTimeFormatter dtf, int monthStart, int monthEnd, int hourStart, int hourend)

Somut bir soru arıyorsanız:

Eğer destroyCity(City city)daha iyidir destroyBaghdad(), olduğu takeActionOnCity(Action action, City city)daha da iyi? Neden / neden olmasın?

Ne de olsa ilk ile diyebilirsin Action.DESTROYo zaman Action.REBUILD, değil mi?

Fakat şehirlerde harekete geçmek benim için yeterli değil, peki takeActionOnGeographicArea(Action action, GeographicalArea GeographicalArea)? Sonuçta, aramak istemiyorum:

takeActionOnCity(Action.DESTORY, City.BAGHDAD);

sonra

takeActionOnCity(Action.DESTORY, City.ERBIL);

ve ne zaman yapabilirim:

takeActionOnGeographicArea(Action.DESTORY, Country.IRAQ);

ps Sorumu yalnızca bahsettiğim alıntı etrafında oluşturdum, dünyadaki herhangi bir ülkeye, dine, ırka veya her şeye karşı hiçbir şeyim yok. Sadece bir şey anlatmaya çalışıyorum.



71
Burada yaptığınız nokta, defalarca ifade etmeye çalıştığım bir konu: genellik pahalı ve bu nedenle belirli, açık yararlarla haklı gösterilmeli . Fakat bundan daha derine iniyor; programlama dilleri tasarımcıları tarafından bir takım genelliği diğerlerinden daha kolay hale getirmek için oluşturulur ve bu da geliştiriciler olarak seçimlerimizi etkiler. Öyle kolay bir değerle bir yöntem parametreleştirmenin ve bu sizin araç kutusundaki var en kolay aracı olduğunda, günaha olursa olsun kullanıcı için mantıklı olmadığına bakılmaksızın onu kullanmaktır.
Eric Lippert

30
Yeniden kullanmak, kendi iyiliği için istediğin bir şey değil. Yeniden kullanıma öncelik veriyoruz çünkü kod yapılarının inşa edilmesinin pahalı olduğu ve bu nedenle bu senaryolarda bu maliyeti amorti etmek için mümkün olduğu kadar çok senaryoda kullanılabilir olması gerektiğine inanıyoruz. Bu inanç sıklıkla gözlemlerle haklı gösterilmemektedir ve bu nedenle tekrar kullanılabilirlik için tasarım önerileri sıklıkla yanlış uygulanmaktadır . Uygulamanın toplam maliyetini düşürmek için kodunuzu tasarlayın .
Eric Lippert

7
Karın sana yalan söyleyerek vaktini boşa harcayan etik değil. Bir cevap istedi ve önerilen bir araç verdi; Bu sözleşmeyle, bu çıktının nasıl elde edileceği yalnızca siz ve kendiniz arasındadır. Ayrıca, destroyCity(target)çok daha etik değil destroyBagdad()! Ne tür bir canavar, bir şehri silmek için bir program yazıyor, dünyanın her hangi bir şehri olsa bile. Ya sistemin tehlikeye atılması durumunda ?! Ayrıca, zaman / kaynak yönetimi (harcanan çaba) etikle ne yapmak zorundadır? Sözlü / yazılı sözleşme, kararlaştırıldığı gibi tamamlandığı sürece.
Tezra

25
Bence bu şeye çok fazla okuyor olabilirsiniz. Bu, bilgisayar programcılarının kötü etik kararlar almaya nasıl geldiği hakkında şaka yapıyor, çünkü çalışmalarının insanlar üzerindeki etkileri konusunda teknik düşüncelere öncelik veriyorlar. Program tasarımı hakkında iyi bir tavsiye olması amaçlanmamıştır.
Eric Lippert

Yanıtlar:


114

Tamamen aşağı kaplumbağalar.

Veya bu durumda soyutlamalar.

İyi uygulama kodlaması, sınırsız biçimde uygulanabilecek bir şeydir ve bir noktada soyutlama uğruna soyutladınız, bu da çok ileri götürdüğünüz anlamına gelir. Bu çizgiyi bulmak, çevreye çok bağlı olduğu için, kurallara uyması kolay bir şey değildir.

Örneğin, önce basit uygulamalar istediği, sonra genişletmeler istediği bilinen müşterilerimiz oldu. Ayrıca ne istediklerini isteyen ve genellikle bir genişleme için bize geri dönmeyen müşterilere de sahibiz.
Yaklaşımınız müşteri başına değişecektir. İlk müşteri için, kodu önceden etkin bir şekilde soyutlamak için para ödeyecektir, çünkü gelecekte bu kodu tekrar gözden geçirmeniz gerektiğinden oldukça eminiz. İkinci müşteri için, uygulamayı herhangi bir noktada genişletmek istemiyorsanız, bu ekstra çabayı yatırmak istemeyebilirsiniz (not: bu iyi bir uygulama izlememeniz anlamına gelmez, sadece şu anda gerekenden daha fazlasını yapmaktan kaçındığınızı .

Hangi özellikleri uygulayacağımı nasıl bilebilirim?

Yukarıdakilerden bahsetmemin nedeni, zaten bu tuzağa düştüğünüz için:

Ama ne kadar (ve ne) parametreleştireceğimi nasıl bilebilirim? Ne de olsa söyleyebilir .

“Söyleyebilir” mevcut bir iş gereksinimi değildir. Gelecekteki bir iş gereksiniminde bir tahmin. Genel bir kural olarak, kendinizi tahminlere dayandırmayın, sadece şu anda gerekli olanı geliştirin.

Bununla birlikte, burada bağlam geçerlidir. Ben karını tanımıyorum Belki de aslında bunu isteyeceğini kesin olarak ölçtün. Ancak yine de müşteriyle bunun gerçekten istediklerinin ne olduğunu doğrulamalısınız , çünkü aksi halde asla kullanmayacağınız bir özelliği geliştirmek için zaman harcayacaksınız.

Hangi mimariyi uygulayacağımı nasıl bilebilirim?

Bu daha zorlu. Müşteri dahili kodu önemsemediğinden, ihtiyaç duyup duymadıklarını soramazsınız. Konuyla ilgili görüşleri çoğunlukla alakasızdır.

Bununla birlikte, müşteriye doğru soruları sorarak bunu yapmanız gerekliliğini onaylayabilirsiniz . Mimarlık hakkında soru sormak yerine, gelecekteki gelişim beklentilerini veya kod tabanına genişletilmelerini sorun. Ayrıca, geçerli hedefin bir son tarihi olup olmadığını da sorabilirsiniz, çünkü fantezi mimarinizi gereken zaman aralığında uygulayamayabilirsiniz.

Kodumu ne zaman daha fazla soyutlayacağımı nasıl bilebilirim?

Nerede okuduğumu bilmiyorum (eğer biri biliyorsa, bilmeme izin ver ve kredi vereceğim), ancak iyi bir kural, geliştiricilerin mağara adamı gibi saymaları gerektiğidir: bir, iki kişi .

görüntü tanımını buraya girin XKCD # 764

Başka bir deyişle, belirli bir algoritma / şablon üçüncü kez kullanıldığında, tekrar kullanılabilecek şekilde soyutlanmalıdır (= birçok kez kullanılabilir ).

Sadece açık olmak gerekirse, kullanılan algoritmanın sadece iki örneği olduğunda tekrar kullanılabilir kod yazmamanız gerektiğini ima etmiyorum. Elbette, bunu da soyutlayabilirsiniz, ancak kural, soyutlamanız gereken üç örnek için olmalıdır .

Yine, bu beklentilerinizi faktörler. Zaten üç veya daha fazla örneğe ihtiyacınız olduğunu biliyorsanız, tabii ki hemen soyutlayabilirsiniz. Ancak, bunu yalnızca daha fazla kez uygulamak isteyeceğinizi tahmin ederseniz, soyutlamanın uygulanmasının doğruluğu, tahmininizin doğruluğuna bağlıdır.
Doğru tahmin edersen, kendine biraz zaman kazandırdın. Yanlış tahmin ettiyseniz, zamanınızı ve çabanızı boşa harcadınız ve muhtemelen ihtiyaç duymadığınız bir şeyi uygulamak için mimarinizden ödün verdiniz.

Eğer destroyCity(City city)daha iyidir destroyBaghdad(), olduğu takeActionOnCity(Action action, City city)daha da iyi? Neden / neden olmasın?

Bu çok şeylere bağlıdır:

  • Herhangi bir şehirde gerçekleştirilebilecek birden fazla eylem var mı?
  • Bu işlemler birbirlerinin yerine kullanılabilir mi? Çünkü eğer "yok et" ve "yeniden inşa et" eylemleri tamamen farklı işlemlere sahipse, ikisini tek bir takeActionOnCityyöntemle birleştirmenin bir anlamı yoktur .

Ayrıca, yinelemeli bir şekilde soyutlarsanız, o kadar soyut bir yöntemle sonuçlanacağını, başka bir yöntemi çalıştırmak için bir konteynerden başka bir şey olmadığını, yani yönteminizi alakasız ve anlamsız hale getirdiğinizi unutmayın.
Metodunuzun tamamı takeActionOnCity(Action action, City city)bitmiyorsa action.TakeOn(city);, takeActionOnCitymetodun gerçekten bir amacı olup olmadığını merak etmelisiniz .

Fakat şehirlerde harekete geçmek benim için yeterli değil, peki takeActionOnGeographicArea(Action action, GeographicalArea GeographicalArea)?

Aynı soru burada ortaya çıkıyor:

  • Coğrafi bölgeler için kullanım durumunuz var mı?
  • Bir şehir ve bir bölgedeki eylemin yürütülmesi aynı mıdır?
  • Herhangi bir bölge / şehirde herhangi bir işlem yapılabilir mi?

Üçüne de kesin olarak "evet" cevabını verirseniz, bir soyutlama garanti edilir.


16
Yeterince "bir, iki, çok" kuralını vurgulayamam. Bir şeyi soyutlamak / parametreleştirmek için sınırsız olanaklar var, ancak faydalı altküme küçük, çoğunlukla sıfır. Tam olarak hangi varyantın değere sahip olduğunu bilmek yalnızca geriye dönük olarak belirlenebilir. Bu yüzden acil gereksinimlere * bağlı kalın ve yeni gereksinimler veya ön görüntünün gerektirdiği şekilde karmaşıklık ekleyin. * Bazen problem alanını iyi biliyorsunuzdur, o zaman bir şeyler eklemek uygun olabilir çünkü yarın ihtiyacınız olduğunu biliyorsunuzdur. Ancak bu gücü akıllıca kullanın, ayrıca mahvedebilir.
Christian Sauer

2
> "Nerede okuduğumu bilmiyorum [..]". Kodlama Korku: Üçün Kuralı'nı okuyordunuz .
Rune,

10
"Bir, iki, birçok kural", DRY'yi kör kullanarak uygulayarak yanlış soyutlamayı oluşturmanızı engellemek için gerçekten var. Mesele şu ki, iki kod parçası neredeyse tamamen aynı gözükmeye başlayabilir, bu yüzden farklılıkları soyutlamak çekicidir; fakat daha önce, kodun hangi kısımlarının sağlam, hangilerinin sağlam olmadığını bilmiyorsunuz; Bunun yanında, aslında bağımsız olarak gelişmeleri gerekebileceği ortaya çıktı (farklı değişim kalıpları, farklı sorumluluk kümeleri). Her iki durumda da, yanlış bir soyutlama size karşı çalışır ve yoluna girer.
Filip Milovanović

4
İkiden fazla "aynı mantık" örneğini beklemek, neyin soyutlanması gerektiğine ve bunun nasıl yapılacağına (ve gerçekten, bu, farklı değişim düzenleriyle kod arasındaki bağımlılıkların / eşleşmenin yönetilmesiyle ilgili) daha iyi bir yargıç olmanıza izin verir.
Filip Milovanović

1
@kukis: Gerçekçi çizgi 2'ye çekilmelidir (Baldrickk'ün yorumuna göre): sıfır-bir-çok (veritabanı ilişkileri için olduğu gibi). Ancak, bu gereksiz kalıp arayışı davranışına kapıyı açar. İki şey belli belirsiz görünebilir ama bu aslında aynı oldukları anlamına gelmez. Bununla birlikte, üçüncü bir örnek hem birinci hem de ikinci vakayı andıran yıpranmaya girdiğinde, benzerliklerinin gerçekten de yeniden kullanılabilir bir kalıp olduğu konusunda daha kesin bir yargıya varabilirsiniz. Öyleyse sağduyu çizgisi 3'te çiziliyor, ki bu sadece iki örnek arasında "kalıpları" tespit ederken insan hatalarında etkili oluyor.
Flast

44

Uygulama

Bu, Software Engineering SE'dir, ancak yazılımçılık, mühendislikten çok daha fazla bir sanattır. Yeniden kullanılabilirliğin ne kadar yeterli olduğunu bulmak için izlenecek evrensel bir algoritma veya ölçüm yoktur. Her şeyde olduğu gibi, programları ne kadar çok uygularsanız o kadar iyi olursunuz. "Yeterince" olanı daha iyi hissedeceksiniz, çünkü neyin yanlış gittiğini ve çok fazla veya çok az parametre belirlediğinizde nasıl yanlış gittiğini göreceksiniz.

Şimdilik pek yardımcı olmuyor , peki ya bazı yönergeler?

Soruna tekrar bak. "Söyleyebileceği" ve "Yapabileceğim" de var. Gelecekteki ihtiyaçlar hakkında teori yapan birçok ifade. İnsanlar geleceği tahmin etmekte çok çekişiyorlar. Ve sen (muhtemelen) bir insansın. Yazılım tasarımının ezici sorunu, bilmediğiniz bir geleceği hesaba katmaya çalışıyor.

Kılavuz İlke 1: İhtiyacınız olmayacak

Ciddi anlamda. Sadece dur. Çoğu zaman, bu hayal edilen gelecekteki problem ortaya çıkmaz - ve kesinlikle sizin hayal ettiğiniz gibi görünmeyecektir.

2. Kılavuz: Maliyet / Fayda

Harika, o küçük program belki de yazman birkaç saat sürdü. Peki ya karınız geri gelir ve bunları isterse ? En kötü durumda, bunu yapmak için başka bir programı bir araya getirmek için birkaç saat daha harcarsınız. Bu durumda, bu programı daha esnek hale getirmek için çok fazla bir zaman değil. Ve çalışma zamanı hızına veya bellek kullanımına fazla bir şey katmayacak. Ancak önemsiz olmayan programların farklı cevapları vardır. Farklı senaryoların farklı cevapları vardır. Bir noktada, maliyetlerin net olmayan gelecekteki söyleme becerilerinde bile faydaya değmeyeceği açıktır.

Kılavuz İlke 3: Sabitlere odaklanmak

Soruya geri dön. Orijinal kodunuzda çok fazla sabit girdi var. 2018, 1. Sabit girdiler, sabit dizeler ... Sabit olmamaları gereken en muhtemel şeyler bunlar . Daha da iyisi, parametreleştirmek için sadece biraz zaman alırlar (ya da en azından gerçek sabitler olarak tanımlarlar). Ancak dikkat edilmesi gereken bir başka şey sürekli davranış . System.out.printlnÖrneğin. Kullanımla ilgili bu tür bir varsayım, gelecekte değişecek bir şey olma eğilimindedir ve düzeltilmesi çok masraflı olma eğilimindedir. Sadece bu değil, bunun gibi IO da işlevi zorlaştırıyor (saat diliminin bir miktar getirilmesiyle birlikte). Bu davranışın parametreleştirilmesi, işlevi daha saf hale getirerek esnekliği ve test edilebilirliği arttırır. Minimum maliyetle büyük avantajlar (özellikle de System.outvarsayılan olarak kullanan bir aşırı yükleme yaparsanız ).


1
Bu sadece bir rehber, 1'ler iyi ama onlara bakıyorsunuz ve “bu hiç değişecek mi?” Diyorsunuz. Ve println daha yüksek bir sıra işlevi ile parametrelendirilebilir - Java bu konuda pek iyi değildir.
Telastyn

5
@KorayTugay: Eğer program gerçekten evde karınız için geldiyse, YAGNI size ilk sürümünüzün mükemmel olduğunu söyler ve sabitleri veya parametreleri tanıtmak için daha fazla zaman harcamamalısınız. YAGNI içeriğe ihtiyaç duyuyor - programınız bir kaçınılmaz çözüm mü, yoksa sadece birkaç ay boyunca süren bir göç programı mı, yoksa birkaç on yıl boyunca kullanılması ve sürdürülmesi amaçlanan büyük bir ERP sisteminin parçası mı?
Doktor Brown

8
@KorayTugay: G / Ç'yi hesaplamadan ayırmak temel bir program yapılandırma tekniğidir. Verilerin filtrelenmesinden verilerin dönüşümünden, verilerin tüketiminden verilerin sunumuna kadar verilerin üretilmesi. Bazı fonksiyonel programları incelemelisiniz, o zaman bunu daha net göreceksiniz. İşlevsel programlamada, sınırsız miktarda veri üretmek, yalnızca ilgilendiğiniz verileri filtrelemek, verileri ihtiyacınız olan formata dönüştürmek, bir dize oluşturmak ve bu dizeyi 5 farklı işlevde yazdırmak oldukça yaygındır. her adım için bir tane.
Jörg W Mittag

3
YAGNI'yi kuvvetli bir şekilde izleyen bir rapor olarak, sürekli refraktöre ihtiyaç duyulmasına yol açmaktadır: "Sürekli refactoring olmadan kullanıldığında, düzensiz kod ve teknik borç olarak bilinen büyük yeniden işleme yol açabilir." Bu nedenle, YAGNI genel olarak iyi bir şey olsa da, her geliştirici / şirketin yapmak istediği bir şey değil, kodu tekrar gözden geçirme ve yeniden değerlendirme sorumluluğu ile geliyor.
Flater

4
@Telastyn: “Bu asla değişmeyecek mi ve kodun amacı sürekli olarak adlandırılmadan kolayca okunabilir mi?” Sorusunu genişletmenizi öneririm .
Flater

27

Birincisi: Hiçbir güvenlikli yazılım geliştiricisi, herhangi bir nedenden dolayı bir Yetkilendirme Simgesini geçmeden bir DestroyCity yöntemi yazmaz.

Ben de başka bir bağlamda uygulanmadan bilgeliği belli olan bir zorunluluk olarak her şeyi yazabilirim. Bir dize bitiştirme yetkisi neden gerekli?

İkincisi: Yürütüldüğünde tüm kod tamamen belirtilmelidir .

Kararın yerine sabit kodlanması veya başka bir katmana ertelenmesi önemli değildir. Bir noktada, bazı dillerde, neyin imha edileceğini ve nasıl talimat verileceğini bilen bir kod parçası var.

Bu aynı nesne dosyasında destroyCity(xyz)olabilir ve bir yapılandırma dosyasında destroy {"city": "XYZ"}"olabilir : veya bir UI'de bir dizi tıklatma ve tuşa basma olabilir.

Üçüncüsü:

Tatlım .. Dünyadaki tüm Gün Işık Tasarruflarını konsolda 2018 için basabilir misiniz? Bir şeyi kontrol etmem gerekiyor.

çok farklı gereksinimler kümesidir:

özel bir dize formatlayıcıyı geçmek istiyor, ... yalnızca belirli ay dönemleriyle ilgileniyor, ... ve belirli saat dönemleriyle ilgileniyor ...

Şimdi ikinci gereksinimler kümesi açıkça daha esnek bir araç yaratıyor. Daha geniş bir hedef kitleye ve daha geniş bir uygulama alanına sahiptir. Buradaki tehlike, dünyadaki en esnek uygulamanın makine kodu için bir derleyici olmasıdır. Kelimenin tam anlamıyla o kadar genel bir programdır ki, bilgisayarı (donanımının kısıtlamaları dahilinde olmak üzere) ihtiyacınız olan her şeyi yapmak için her şeyi inşa edebilir.

Genel olarak, yazılıma ihtiyaç duyan insanlar genel bir şey istemezler; özel bir şey istiyorlar. Daha fazla seçenek vererek, aslında yaşamlarını daha karmaşık hale getiriyorsunuz. Bu karmaşıklığı istiyorlarsa, sizden istemeyen bir derleyici kullanıyorlardı.

Karınız işlevsellik istiyordu ve onun gereksinimlerini size yeterince belirtmedi. Bu durumda görünüşte amaçlıydı ve genel olarak daha iyisini bilmiyorlardı. Aksi takdirde derleyiciyi daha yeni kullanırlardı. Bu yüzden ilk sorun, tam olarak ne yapmak istediği hakkında daha fazla ayrıntı istemediğinizdir. Bunu birkaç yıl boyunca çalıştırmak istedi mi? Bir CSV dosyasında mı istedi? Hangi kararları kendisi almak istediğini ve sizden ne yapıp karar vermenizi istediğini bilmiyordunuz. Hangi kararların ertelenmesi gerektiğine karar verdikten sonra, bu kararların parametrelerle (ve diğer yapılandırılabilir araçlarla) nasıl iletileceğini anlayabilirsiniz.

Bununla birlikte, çoğu müşteri, kendilerini gerçekten yapmak istedikleri veya gerçekten yapmak istemedikleri (gerçekten harika geliyor) bazı ayrıntıları (yani, kararları) yanlış iletir, varsayar veya bilmezden gelir. Bu yüzden PDSA (plan-geliştir- çalış -hareket) gibi çalışma yöntemleri önemlidir. Çalışmayı gereksinimler doğrultusunda planladınız ve sonra bir takım kararlar (kod) geliştirdiniz. Şimdi, kendiniz veya müşterinizle birlikte çalışmanın ve yeni şeyler öğrenmenin zamanı geldi ve bunlar ileriye dönük düşüncelerinizi bilgilendirir. Sonunda yeni görüşlerinize göre hareket edin - gereklilikleri güncelleyin, süreci iyileştirin, yeni araçlar edinin, vb. Sonra yeniden planlamaya başlayın. Bu, zaman içinde herhangi bir gizli gereksinimi ortaya çıkarırdı ve birçok müşteriye ilerleme olduğunu kanıtlardı.

En sonunda. Zamanınız önemlidir ; çok gerçek ve çok sonlu. Verdiğiniz her karar, diğer birçok gizli kararları gerektirir ve bu, gelişen yazılım ile ilgili. Bir kararı argüman olarak ertelemek mevcut işlevi daha kolaylaştırabilir, ancak başka bir yerde daha karmaşık hale getirir. Bu karar diğer yerle alakalı mı? Burada daha mı alakalı? Gerçekten kimin kararı? Buna karar veriyorsun; bu kodlama. Karar setlerini sık sık tekrarlarsanız, onları bir soyutlamanın içinde kodlamanın çok gerçek bir faydası vardır. XKCD'nin burada yararlı bir bakış açısı var. Ve bu, bir fonksiyon, modül, program, vb. Gibi bir sistem düzeyinde ilgilidir.

Başlangıçtaki öneri, fonksiyonunuzun vermeye hakkı olmayan kararların bir argüman olarak kabul edilmesi gerektiği anlamına gelir. Sorun şu ki, bir DestroyBaghdadişlev aslında bu hakka sahip olan işlev olabilir.


+1 derleyici ile ilgili kısmı sev!
Lee

4

Burada çok uzun soluklu cevap var, ama dürüst olmak gerekirse, bence süper basit.

İşlevinizde, işlev adının bir parçası olmayan tüm kodlanmış bilgiler bir parametre olmalıdır.

yani fonksiyonunda

class App {
    void dayLightSavings() {
        final Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        availableZoneIds.forEach(zoneId -> {
            LocalDateTime dateTime = LocalDateTime.of(LocalDate.of(2018, 1, 1), LocalTime.of(0, 0, 0));
            ZonedDateTime now = ZonedDateTime.of(dateTime, ZoneId.of(zoneId));
            while (2018 == now.getYear()) {
                int hour = now.getHour();
                now = now.plusHours(1);
                if (now.getHour() == hour) {
                    System.out.println(now);
                }
            }
        });
    }
}

Var:

The zoneIds
2018, 1, 1
System.out

Bu yüzden bütün bunları bir biçimde veya başka bir parametreye taşıyacağım. ZoneIds'ın işlev adında gizli olduğunu iddia edebilirsiniz, belki de bunu "DaylightSavingsAroundTheWorld" olarak değiştirerek daha da fazlasını yapmak istersiniz.

Bir biçim dizgene sahip değilsiniz, bu nedenle bir özellik isteği eklemek ve karınızı aileniz Jira örneğine yönlendirmeniz gerekir. İstisnaya alınabilir ve uygun proje yönetim komitesi toplantısında önceliklendirilebilir.


1
Siz (kendimi OP’ye hitaben) kesinlikle bir format dizesi eklememelisiniz, çünkü hiçbir şey basmamanız gerekir. Bu kodla ilgili tekrar kullanımını kesinlikle önleyen tek şey, yazdırmasıdır. DST'den çıktıklarında bölgeleri veya bölgelerin haritasını döndürmelidir. (Sadece tanımlayan neden olduğunda gitmek rağmen kapalı DST değil üzerinde DST, anlamıyorum Sorun ifadeyle eşleşebilir görünmüyor..)
David Conrad

gereksinim konsola yazdırmaktır. çıkış akışını benim önerdiğim gibi bir parametre olarak geçirerek sıkışıklığı azaltabilirsiniz
Ewan

1
Buna rağmen, kodun tekrar kullanılabilir olmasını istiyorsanız, konsola yazdırmamalısınız. Sonuçları döndüren bir yöntem yazın ve ardından onları alan ve basan bir arayanı yazın. Bu da test edilebilir hale getirir. Çıktı üretmesini istiyorsanız, bir çıktı akışından geçmezdim, Tüketici'den geçiririm.
David Conrad

bir çıkış akışı bir tüketicidir
Ewan

Hayır, bir OutputStream Tüketici değil .
David Conrad,

4

Kısacası, yazılımınızı yeniden kullanılabilirlik için tasarlamayın, çünkü işlevlerinizin tekrar kullanılıp kullanılmayacağını son kullanıcı umursamaz. Bunun yerine, tasarım anlaşılabilirliği için mühendis - kodum başkası için kolay mı yoksa geleceğim için unutkan bir benlik mi? - ve tasarım esnekliği- kaçınılmaz olarak hataları düzeltmem, özellikler eklemem veya işlevleri değiştirmem gerektiğinde kodum değişikliklere ne kadar direnç gösterecek? Müşterinizin umursadığı tek şey bir hatayı bildirdiğinde veya bir değişiklik istediğinde ne kadar çabuk cevap verebileceğinizdir. Tasarımınızla ilgili bu soruları sormak, tekrar kullanılabilecek bir kodla sonuçlanma eğilimindedir, ancak bu yaklaşım, söz konusu kodun kullanım ömrü boyunca karşılaşacağınız gerçek sorunlardan kaçınmaya odaklanmanızı sağlar; "mühendislik" boyun sakallarını memnun etmek için idealdir.

Sağladığınız örnek kadar basit bir şey için, ilk uygulamanızın ne kadar küçük olduğundan dolayı gayet iyi, ancak bu kadar basit bir tasarımın (esnekliğin aksine) çok fazla işlevsel esneklik sıkıştırarak denemeyi zorlaştırması bir prosedür. Aşağıda, kendileriyle ne demek istediğimi göstereceğimi umduğum gibi anlaşılabilirlik ve esneklik için karmaşık sistemler tasarlamaya tercih ettiğim yaklaşımım açıklanmaktadır. Bu stratejiyi tek bir prosedürde 20 satırdan daha az satırda yazılabilecek bir şey için kullanmayacağım, çünkü çok küçük bir şey zaten olduğu gibi anlaşılabilirlik ve esneklik kriterlerime uyuyor.


İşlemler değil Nesneler

Eski okul modülleri gibi sınıfları, yazılımınızın yapması gereken şeyleri yerine getirmek için çağırdığınız bir grup yordamı kullanmak yerine, etki alanını elinizdeki görevi gerçekleştirmek için etkileşime giren ve işbirliği yapan nesneler olarak modellemeyi düşünün. Nesneye Yönelik bir paradigmadaki yöntemler, aslında, nesneler arasındaki sinyaller olarak yaratıldı; böylece , ne olduğunu ve muhtemelen bir geri dönüş sinyali Object1alabileceğini söyleyebildi Object2. Bunun nedeni, Nesne Yönelimli paradigmanın, emeratif paradigmanın aynı eski işlevlerini ve prosedürlerini düzenlemek için süslü bir yol yerine etki alanlarınızı ve etkileşimlerini modellemektir. Durumundavoid destroyBaghdadÖrneğin, Bağdat'ın ya da başka bir şeyin (hızlı, karmaşık, anlaşılması zor ve kırılgan bir şekilde büyüyebilecek olan) imhasını ele almak için bağlamsız bir jenerik yöntem yazmaya çalışmak yerine, yok edilebilecek her şeyin nasıl olduğunu anlamaktan sorumlu olması gerekir. kendini yok etmek. Örneğin, yok edilebilecek şeylerin davranışını tanımlayan bir arayüze sahipsiniz:

interface Destroyable {
    void destroy();
}

O zaman bu arayüzü uygulayan bir şehir var:

class City implements Destroyable {
    @Override
    public void destroy() {
        ...code that destroys the city
    }
}

Bir örneğin imhasını gerektiren hiçbir şey bunun Citynasıl olacağını asla umursamaz, bu nedenle, bu kodun dışında bir yerde var olmanın hiçbir nedeni yoktur City::destroyve gerçekten de, Citykendi dışının iç işleyişine ilişkin samimi bilgiler, azalan sıkı bir bağlantı olacaktır. felksilite, o dış unsurları göz önünde bulundurmanız gerektiğinden, davranışını değiştirmek zorunda kalmanız gerekir City. Kapsüllemenin arkasındaki asıl amaç budur. Her nesnenin kendi API'sine sahip olduğunu ve onunla ihtiyaç duyduğunuz her şeyi yapmanıza izin vermesi gerektiğini düşünerek isteklerinizi yerine getirme konusunda endişelenmesine izin verin.

Delegasyon, "Kontrol" değil

Şimdi, uygulayıcı sınıfınızın olup olmadığı Cityveya Baghdadşehri tahrip etme sürecinin ne kadar jenerik olduğuna bağlı. Her ihtimalde, Citykentin toplam yıkımını gerçekleştirmek için ayrı ayrı yok edilmesi gereken daha küçük parçalardan oluşacak bir irade olacak, bu durumda, bu parçaların her biri de uygulanacak Destroyableve her biri tarafından Cityimha edilmesi talimatı verilecek . kendileri de aynı şekilde dışarıdan biri Citykendini yok etmesini istedi .

interface Part extends Destroyable {
    ...part-specific methods
}

class Building implements Part {
    ...part-specific methods
    @Override
    public void destroy() {
       ...code to destroy a building
    }
}

class Street implements Part {
    ...part-specific methods
    @Override
    public void destroy() {
        ...code to destroy a building
    }
}

class City implements Destroyable {
    public List<Part> parts() {...}

    @Override
    public void destroy() {
        parts().forEach(Destroyable::destroy);            
    }
}

Gerçekten delirmek ve Bombbir yere düşmüş olan fikrini uygulamak ve belirli bir yarıçaptaki her şeyi yok etmek istiyorsanız, şuna benzer bir şey olabilir:

class Bomb {
    private final Integer radius;

    public Bomb(final Integer radius) {
        this.radius = radius;
    }

    public void drop(final Grid grid, final Coordinate target) {
        new ObjectsByRadius(
            grid,
            target,
            this.radius
        ).forEach(Destroyable::destroy);
    }
}

ObjectsByRadiusBombGirişlerden hesaplanan bir nesne kümesini temsil eder, çünkü Bombbu hesaplamanın nesnelerle çalışabildiği sürece nasıl yapıldığını önemsemez. Bu tesadüfen tekrar kullanılabilir, ancak asıl amaç hesaplamayı bırakma işlemlerinden izole etmektir.Bomb nesneleri ve tahrip etme böylece her bir parçayı ve bunların nasıl bir araya geldiğini ve tüm algoritmayı yeniden şekillendirmek zorunda kalmadan tek bir parçanın davranışını nasıl değiştirebileceğinizi kavrayabilmek. .

Etkileşimler, Algoritmalar değil

Karmaşık bir algoritma için doğru sayıda parametreyi tahmin etmeye çalışmak yerine, işlemi her biri son derece dar rollere sahip bir dizi etkileşim nesnesi olarak modellemek daha mantıklıdır, çünkü size karmaşıklığınızı modelleme yeteneği verecektir. Bu iyi tanımlanmış, anlaşılması kolay ve neredeyse değişmeyen nesneler arasındaki etkileşimler yoluyla işlem yapar. Doğru yapıldığında, bu bile bir arayüz ya da iki uygulama ve sizin için hangi nesnelerin başlatıldığını yeniden işleme gibi önemsiz en karmaşık değişikliklerden bazıları yaparmain() yönteminizde .

Size orjinal örneğinize bir şey verirdim, ama dürüst olmak gerekirse, "Gündüz Işık Tasarrufu" nu basmanın ne demek olduğunu çözemiyorum. Bu sorun kategorisi hakkında söyleyebileceğim, bir hesaplama yaptığınız zaman, bunun sonucu olarak birkaç şekilde biçimlendirilebilecek olan, yıkmak için tercih ettiğim yol şudur:

interface Result {
    String print();
}

class Caclulation {
    private final Parameter paramater1;

    private final Parameter parameter2;

    public Calculation(final Parameter parameter1, final Parameter parameter2) {
        this.parameter1 = parameter1;
        this.parameter2 = parameter2;
    }

    public Result calculate() {
        ...calculate the result
    }
}

class FormattedResult {
    private final Result result;

    public FormattedResult(final Result result) {
        this.result = result;
    }

    @Override
    public String print() {
        ...interact with this.result to format it and return the formatted String
    }
}

Örnekte Java kütüphanesinden bu tasarımı desteklemeyen sınıflar kullandığından, ZonedDateTimedoğrudan API'sini kullanabilirsiniz . Buradaki fikir, her bir hesaplamanın kendi nesnesi içinde kapsüllenmesidir. Kaç kez çalışması gerektiği veya sonucu nasıl biçimlendirmesi gerektiği konusunda hiçbir varsayımda bulunmaz. Sadece hesaplamanın en basit halini almakla ilgilidir. Bu, hem değişimini kolay hem de esnek hale getirir. Aynı şekilde, Resultsadece hesaplamanın sonucunu kapsamaya almakla ilgilenir ve FormattedResultsadece Resultonu tanımladığımız kurallara göre biçimlendirmekle etkileşime girmekle ilgilenir . Böylece,Her biri iyi tanımlanmış bir göreve sahip olduklarından, her bir yöntemimiz için mükemmel argüman sayısı bulabiliriz . Arayüzler değişmediği sürece ilerlemenin değiştirilmesi de çok daha basittir (nesnelerinizin sorumluluklarını gerektiği gibi en aza indirmişseniz, bunun yapılması muhtemel değildir). Yöntemimizmain()şöyle görünebilir:

class App {
    public static void main(String[] args) {
        final List<Set<Paramater>> parameters = ...instantiated from args
        parameters.forEach(set -> {
            System.out.println(
                new FormattedResult(
                    new Calculation(
                        set.get(0),
                        set.get(1)
                    ).calculate()
                ).print()
            );
        });
    }
}

Nitekim, Nesne Yönelimli Programlama, özel olarak, Zorunlu paradigmanın karmaşıklığı / esneklik sorununa bir çözüm olarak icat edildi çünkü optimal olarak nasıl yapılacağına dair iyi bir cevap (herkesin hemfikir olabileceği veya bağımsız olarak gelebileceği). Deyim içindeki Emir Kipleri ve İşlevleri belirtiniz.


Bu çok ayrıntılı ve düşünülmüş bir cevap, ancak ne yazık ki OP'nin gerçekte ne istediği konusundaki işareti özlediğini düşünüyorum. Spesifik örneğini çözmek için iyi OOP uygulamaları hakkında bir ders istemiyordu, çözüm veya genelleme için bir zaman yatırımına karar verdiğimiz kriterler hakkında sorular soruyordu.
maple_shaft

@maple_shaft Belki işareti kaçırdım, ama sanırım sizde de var. OP, zamana karşı genelleme yatırımını sormuyor. “Yöntemlerimin ne kadar tekrar kullanılabilir olması gerektiğini nasıl bilebilirim?” Diye soruyor. “DestroyCity (Şehir Şehri) Destroy'dan (Bağdat) daha iyiyse, ActionOnCity (Aksiyon eylemi, Şehir Şehri) daha iyi mi? Neden / neden olmasın?” Sorusu sormaya devam ediyor. Mühendislik çözümlerine alternatif bir yaklaşım ortaya koydum ve iddiamı destekleyecek örnekler vermenin ne kadar jenerik olduğunu çözme sorununu çözdüğünü düşünüyorum. Üzgünüm beğenmedin.
Stuporman

@maple_shaft Açıkçası, sadece OP, cevabımın sorumuyla alakalı olup olmadığını belirleyebilir, çünkü geri kalanımız niyetleri hakkındaki yorumlarımızı savunan savaşlarla mücadele edebilir, hepsi de aynı derecede yanlış olabilir.
Stuporman

@maple_shaft Soruyla nasıl ilişkili olduğunu açıklığa kavuşturmak için bir intro ekledim ve cevap ile örnek uygulama arasında net bir açıklama sağladım. Bu daha iyi mi?
Stuporman

1
Dürüst olmak gerekirse, tüm bu prensipleri uygularsanız, cevap doğal olarak gelecek, pürüzsüz ve okunaklı olacak. Ayrıca, fazla telaşsız bir şekilde değiştirilebilir. Kim olduğunu bilmiyorum ama keşke daha fazla olsaydın! İyi OO için Reaktif kodları kopyalamaya devam ediyorum ve bu HER ZAMAN yarı boyutunda, daha okunabilir, daha kontrol edilebilir ve hala iş parçacığı / bölme / haritalama var. Bence React, daha önce listelediğiniz "temel" kavramları anlamayan insanlar içindir.
Stephen J

3

Deneyim , Etki Alanı Bilgisi ve Kod İncelemeleri.

Ve, ne kadar veya ne kadar az tecrübe , etki alanı bilgisi veya ekibiniz olursa olsun , ihtiyaç duyduğunuz şekilde yeniden denetleme ihtiyacından kaçınamazsınız .


Deneyim ile , yazdığınız alana özgü olmayan yöntemlerde (ve sınıflarda) kalıpları tanımaya başlayacaksınız. Ve eğer DRY koduyla tamamen ilgileniyorsanız , gelecekteki varyasyonlarını yazacağınızı içgüdüsel olarak bildiğiniz bir yöntem yazmak üzereyken kendinizi kötü hissedeceksiniz . Böylece, sezgisel olarak parametreli bir en az ortak payda yazacaksınız.

(Bu deneyim içgüdüsel olarak etki alanınızdaki bazı nesnelere ve yöntemlere de aktarılabilir.)

Etki Alanı Bilgisi ile , hangi işletme kavramlarının yakından ilişkili olduğunu, hangi kavramların oldukça statik olan değişkenlerin olduğunu vb.

Kod yorumlar ile üretim kodu hale gelmesinden önce eş (umarım) benzersiz deneyimler ve bakış açıları olacak çünkü alt ve üst sınırını parametreleriyle daha muhtemel üzerine, her iki yakalanacak etki ve genel olarak kodlama.


Bununla birlikte, yeni geliştiricilerin genellikle bu Spidey Duyularına ya da hemen üzerine yaslanacak deneyimli bir akran grubuna sahip olmayacaklarını söyledi . Deneyimli geliştiriciler bile , yeni gereksinimler veya beyin sisli günler boyunca onları yönlendirmek için temel bir disiplinden faydalanır. İşte size başlangıç ​​olarak önereceğim şey :

  • Saf uygulama ile başlayın, minimum parametre ile.
    ( İhtiyacınız olacağını bildiğiniz tüm parametreleri ekleyin , açıkçası ...)
  • Sihirli sayıları ve dizeleri kaldırın, bunları config ve / veya parametrelere taşıyın
  • Faktör "büyük" yöntemleri daha küçük, iyi adlandırılmış yöntemlere dönüştürün
  • Refactor çok fazla yedekli yöntemler (uygunsa) ortak bir payda haline getirerek farklılıkları parametreleştirir.

Bu adımların mutlaka belirtilen sırada olması gerekmez. Mevcut bir yöntemle fazlasıyla gereksiz olduğunu bildiğiniz bir yöntem yazmak için oturuyorsanız , uygunsa doğrudan yeniden düzenlemeye geçin . (Yeniden ateşlemek için sadece iki yöntemi yazmaktan, test etmekten ve sürdürmekten daha fazla zaman almayacaksa)

Ancak, çok fazla tecrübe sahibi olmanın yanı sıra, oldukça minimalist bir kod KURUTMA tavsiye ediyorum. Açık ihlalleri yeniden düzenlemek zor değil. Ve eğer çok kıskanıyorsanız , “WET” eşdeğerinden daha okuması, anlaması ve bakımı daha zor olan “over-DRY” koduna sahip olabilirsiniz.


2
Yani doğru bir cevap yok If destoryCity(City city) is better than destoryBaghdad(), is takeActionOnCity(Action action, City city) even better?mu? Bu evet / hayır sorusudur, ancak bir cevabı yoktur, değil mi? Ya da ilk varsayım yanlıştır, destroyCity(City)mutlaka daha iyi olmayabilir ve buna bağlı olarak ? Bu, etik olarak eğitilmiş bir yazılım mühendisi olmadığı anlamına gelmez, çünkü doğrudan herhangi bir parametre olmadan doğrudan uyguladım? Demek istediğim, sorduğum somut sorunun cevabı nedir?
Koray Tugay

Sorunuz bir kaç soru sorar. Başlık sorusunun cevabı, "deneyim, etki alanı bilgisi, kod incelemeleri ... ve ... refactor'dan korkma" şeklindedir. Herhangi bir somut cevaba "bunlar ABC yöntemi için doğru parametrelerdir" sorusu ... "Bilmiyorum. Neden soruyorsun? Şu anda sahip olduğu parametrelerin sayısında bir sorun mu var? Düzelt. Düzelt. " ... daha fazla rehberlik için sizi "POAP" sayfasına götürebilirim : Ne yaptığınızı neden yaptığınızı anlamanız gerekiyor!
svidgen

Yani ... hadi destroyBaghdad()yöntemden bir adım geriye gidelim . Bağlam nedir? Bağdat'ta oyunun bitimine neden olan bir video oyunu mu ??? Öyleyse ... destroyBaghdad()son derece makul bir yöntem adı / imzası olabilir ...
svidgen

1
Demek sorumdaki alıntıya katılmıyorsunuz değil mi? It should be noted that no ethically-trained software engineer would ever consent to write a DestroyBaghdad procedure.Nathaniel Borenstein'la odada olsaydınız, gerçekten bağlı olduğunu ve ifadesinin doğru olmadığını iddia ederdiniz. Yani, birçok insanın cevap vermesi, zamanını ve enerjisini harcaması çok güzel, ama hiçbir yerde tek bir somut cevap göremiyorum. Spidey-duyuları, kod incelemeleri .. Ama cevabı ne is takeActionOnCity(Action action, City city) better? null?
Koray Tugay

1
@svidgen Elbette, bunu fazladan çaba göstermeden soyutlamanın başka bir yolu da bağımlılığı tersine çevirmek - fonksiyonun üzerlerinde herhangi bir işlem yapmak yerine şehirlerin listesini döndürmesini sağlamaktır (orijinal koddaki "println" gibi). Gerekirse bu daha da soyutlanabilir, ancak yalnızca bu değişiklik kendi başına eklenmiş soruya eklenen gereksinimlerin yaklaşık yarısını önemser - ve her türlü kötü şeyi yapabilen saf olmayan bir işlev yerine, sadece bir işleviniz vardır Bu bir liste döndürür ve arayan kişi kötü şeyler yapar.
Luaan

2

Kalite, kullanılabilirlik, teknik borç vb. İle aynı cevabı:

Sizin gibi tekrar kullanılabilir , kullanıcı, 1 olma

Bu temelde bir yargılama çağrısıdır - soyutlamanın tasarlanması ve sürdürülmesinin maliyetinin geri ödenip ödenmeyeceği (= zaman ve efor) sizi bu çizgiden kurtaracaktır.

  • "Satırdan aşağıya" ifadesini not edin: Burada bir ödeme makamı var, bu yüzden bu kodla ne kadar çalışacağınıza bağlı olacaktır. Örneğin:
    • Bu bir kereye mahsus bir proje mi, yoksa uzun bir süre içinde aşamalı olarak iyileştirilecek mi?
    • Tasarımınıza güveniyor musunuz, yoksa bir sonraki proje / dönüm noktası için onu büyük ölçüde hurdaya çıkarmak veya başka şekilde değiştirmek zorunda kalacak mısınız (örneğin, başka bir çerçeve deneyin)?
  • Öngörülen fayda aynı zamanda geleceği tahmin etme yeteneğinize de bağlıdır (uygulamada değişiklikler). Bazen, uygulamanızın alacağı mekanları / yerleri makul bir şekilde görebilirsiniz. Çoğu zaman yapabileceğini düşünüyorsun ama yapamazsın. Buradaki kurallar, YAGNI ilkesi ve üç kuraldır - ikisi de bildiğiniz şeyin dışında çalışmayı vurgular .

1 Bu bir kod yapısıdır, bu durumda bu durumda "kullanıcı" sınız - kaynak kodun kullanıcısı


1

Takip edebileceğiniz net bir süreç var:

  • Başlı başına "bir şey" olan tek bir özellik için başarısız bir test yazın (yani, her ikisinin de gerçek anlamda anlamadığı bir özelliğin keyfi olarak bölünmesi değil).
  • Bir satırdan fazla değil, yeşil renkte geçmesi için mutlak minimum kodu yazın.
  • Durulayın ve tekrarlayın.
  • (Gerekirse acımasızca refactor, bu harika test kapsamı nedeniyle kolay olmalıdır.)

Bu, en azından bazılarının görüşüne göre - mümkün olduğunca küçük olduğundan, en uygun kod olduğundan, her bitmiş özelliğin mümkün olduğunca az zaman almasını sağlar (bitmiş bakarsanız doğru olabilir veya olmayabilir) refactoring sonrası ürün) ve test kapsamı çok iyi. Ayrıca, aşırı tasarlanmış çok genel yöntemlerden veya sınıflardan fark edilir bir şekilde kaçınır.

Bu aynı zamanda ne zaman bir şeyleri genel hale getireceğiniz ve ne zaman uzmanlaştıracağınız konusunda çok net talimatlar verir.

Senin şehir örneğini tuhaf buluyorum; Büyük ihtimalle hiçbir zaman bir şehir adını kodlamam. Yaptığınız her ne olursa olsun, ek şehirlerin daha sonra dahil olacağı çok açık. Ancak başka bir örnek renkler olacaktır. Bazı durumlarda, "kırmızı" veya "yeşil" kodlama olasılığı olabilir. Örneğin, trafik ışıkları öylesine bir renktedir ki ondan kurtulabilirsiniz (ve her zaman yeniden yansıtıcı olabilirsiniz). Aradaki fark, "kırmızı" ve "yeşil" in dünyamızda evrensel, "kodlanmış" bir anlamı olması, bunun asla değişmeyeceği ihtimalinin inanılmaz olması ve gerçekten de bir alternatif olmaması.

İlk günışığı tasarruf yönteminiz basitçe bozuldu. Şartnamelere uygun olmasına rağmen, 2018 kodlu kod özellikle kötüdür, çünkü a) teknik "sözleşmede" belirtilmemiştir (bu durumda yöntem adına) ve b) çok geçmeden güncel olmayacaktır Başlarken dahil. Zaman / tarih ile ilgili şeyler için, zaman geçtikten sonra belirli bir değeri kodlamak nadiren mantıklı olacaktır. Fakat bunun dışında, her şey tartışma için hazır. Basit bir yıl verirseniz ve her zaman bütün yılı hesaplarsanız, devam edin. Listelenen şeylerin çoğu (biçimlendirme, daha küçük bir aralık seçimi, vb.) Yönteminizin çok fazla iş yaptığını haykırır ve bunun yerine arayanın biçimlendirmeyi / filtrelemeyi yapabilmesi için büyük olasılıkla bir değer / liste dizisi döndürmelidir.

Ancak günün sonunda, bunun çoğu görüş, lezzet, deneyim ve kişisel önyargıdır, bu yüzden fazla endişelenmeyin.


İkinci ve son paragrafınızla ilgili olarak - başlangıçta verilen "gereksinimlere", yani ilk yöntemin dayandığı noktalara bakın. 2018'i belirtir, bu nedenle kod teknik olarak doğrudur (ve muhtemelen özellik odaklı yaklaşımınızla eşleşir).
dwizum

@ dwizum, gereksinimlerle ilgili olarak doğru, ancak yöntem adı yanıltıcı. 2019'da, sadece yöntem adına bakan herhangi bir programcı, ne yaptığını varsayar (belki de cari yıl için değerleri döndürür), 2018'e değil ... Ne demek istediğimi daha net hale getirmek için bir cümle ekleyeceğim.
Saat

1

İki çeşit tekrar kullanılabilir kod olduğunu düşünüyorum.

  • Yeniden kullanılabilir kod çünkü bu çok temel, temel bir şey.
  • Yeniden kullanılabilir kod çünkü her yerde parametreler, geçersiz kılmalar ve kancalar var.

İlk yeniden kullanılabilirlik türü genellikle iyi bir fikirdir. Listeler, hashpalar, anahtar / değer depoları, katar eşleştiriciler (örneğin, regex, glob, ...), perdeler, birleşme, arama ağaçları (derinlik ilk önce, genişlik ilk, yinelemeli derinleşme, ...) gibi şeyler için geçerlidir. , ayrıştırıcı birleştiricileri, önbellekleri / hatıraları, veri biçimi okuyucular / yazarları (s ifadeleri, XML, JSON, protobuf, ...), görev sıraları vb.

Bu şeyler o kadar genel ki, çok soyut bir şekilde, günlük programlamanın her yerinde yeniden kullanılıyor. Kendinizi daha soyut / genel yapılıyorsa daha kolay olacak özel amaçlı bir kod yazarken bulursanız (örneğin, "müşteri siparişleri listesi" varsa, "liste" almak için "müşteri siparişi" öğelerini "atabiliriz" ) o zaman bunu çıkarmak iyi bir fikir olabilir. Yeniden kullanılmasa bile, ilgisiz işlevselliği birleştirmemize izin verir.

İkinci sıralama, gerçek bir sorunu çözen bazı kararlar verdiğimiz bazı somut kurallara sahip olduğumuz yerdir. Bu kararları "yumuşak kodlama" ile daha genel / yeniden kullanılabilir hale getirebiliriz, örneğin bunları parametrelere dönüştürmek , uygulamayı karmaşıklaştırmak ve daha da somut ayrıntılarda pişirmek (örneğin geçersiz kılmak için hangi kancaları isteyeceğimizi bilmek). Örneğiniz bu tür görünüyor. Bu türden yeniden kullanılabilirlikle ilgili sorun, başkalarının kullanım durumlarını veya gelecekteki kendimizi tahmin etmeye çalışmamız olabilir. Sonunda, kodumuzun kullanılamayacağı kadar çok parametreye sahip olabiliriz., yeniden kullanılabilir tek başına bırak! Başka bir deyişle, onu çağırırken sadece kendi versiyonumuzu yazmaktan daha fazla çaba harcar. YAGNI'nin (İhtiyacınız olmayacak) önemli olduğu yer burasıdır. Çoğu zaman, "yeniden kullanılabilir" kodundaki bu tür girişimler tekrar kullanılmaz, çünkü bu kullanım durumları ile parametrelerin temelde gösterebileceğinden daha temel bir şekilde uyumsuz olabilir veya potansiyel kullanıcılar kendi tercihlerini yerine getirebilir (heck, hepsine bak. Yazarlar "Basit" kelimesiyle ön eklenmiş standartlar ve kütüphaneler, onları öncekilerden ayırmak için!).

Bu ikinci "yeniden kullanılabilirlik" formu temel olarak ihtiyaç duyulduğu şekilde yapılmalıdır. Elbette, bazı "belirgin" parametreleri oraya yapıştırabilirsiniz, ancak geleceği tahmin etmeye çalışmayın. YAGNI.


İlk çekimimin iyi geçtiğini, yılın bile kodlandığı yerleri kabul edebileceğinizi söyleyebilir miyiz? Ya da başlangıçta bu gereksinimi yerine getiriyorsanız, yılı ilk almanızın parametresi haline getirir miydiniz?
Koray Tugay

İlk almanız iyi oldu, çünkü gereksinim bir şeyi kontrol etmek için tek seferlik bir komut dosyasıydı. 'Etik' sınavında başarısız olur, ancak 'dogma yok' sınavında başarısız olur. "Söyleyebilir ..." İhtiyacınız olmayacak gereksinimleri icat ediyor.
Warbo

Hangi şehri yok etmenin "daha iyi" olduğunu daha fazla bilgi olmadan söyleyemeyiz: destroyBaghdadtek seferlik bir betiktir (ya da en azından, önemsiz). Belki herhangi bir şehri yıkmak bir gelişme olabilir, fakat ya destroyBaghdadDicle'yi su basarsa çalışırsa? Musul ve Basra için tekrar kullanılabilir, ancak Mekke veya Atlanta için değil.
Warbo

Görüyorum ki teklifin sahibi Nathaniel Borenstein ile aynı fikirde değilsin. Tüm bu yanıtları ve tartışmaları okuyarak yavaş yavaş anlamaya çalışıyorum.
Koray Tugay

1
Bu farklılaşmayı seviyorum. Her zaman net değil ve her zaman "sınır davaları" var. Ama genel olarak, aynı zamanda tamamen işlevsel ve düşük seviyeli "yapı taşları" (genellikle staticyöntem şeklinde ) hayranıyım ve bunun aksine, "parametreleri ve kancaları yapılandırma" hakkında karar vermek genellikle haklı gösterilmesini isteyen bazı yapılar inşa etmeniz gerekiyor.
Marco13 21

1

Zaten birçok mükemmel ve ayrıntılı cevaplar var. Bazıları derinlemesine özel ayrıntılara giriyor, genel olarak yazılım geliştirme metodolojileri hakkında bazı bakış açıları ortaya koyuyor ve bazıları kesinlikle tartışmalı unsurlara veya "fikirlere" sahip.

Warbo tarafından verilen cevap, farklı yeniden kullanılabilirlik türlerine dikkat çekti . Yani, temel bir yapı taşı olduğu için bir şeyin tekrar kullanılabilir olup olmadığı ya da bir şekilde “jenerik” olduğu için bir şeyin tekrar kullanılabilir olup olmadığı. İkincisine atıfta bulunarak, yeniden kullanılabilirlik için bir tür önlem olarak kabul edeceğim bir şey var :

Bir yöntemin diğerini taklit edip etmeyeceği .

Sorudan örnekle ilgili olarak: Yöntemin olduğunu düşünün

void dayLightSavings()

Bir müşteri tarafından talep edilen bir fonksiyonelliğin uygulanmasıydı. Bu yüzden bir şey olacak diğer programcılar kullanmak gerekiyordu ve böylece, bir olmak , kamu gibi yöntem

publicvoid dayLightSavings()

Bu, cevabınızda gösterildiği gibi uygulanabilir. Şimdi, biri bunu yılla parametreleştirmek istiyor. Böylece bir yöntem ekleyebilirsiniz

publicvoid dayLightSavings(int year)

ve orijinal uygulamayı sadece

public void dayLightSavings() {
    dayLightSavings(2018);
}

Bir sonraki "özellik istekleri" ve genellemeler aynı kalıbı izler. Yani eğer ve eğer sadece en genel şekli için talep var, bu en genel formu daha spesifik olanlar önemsiz uygulamaları için izin verdiğini bilerek, bunu uygulayabilirsiniz:

public void dayLightSavings() {
    dayLightSavings(2018, 0, 12, 0, 12, new DateTimeFormatter(...));
}

Gelecekteki uzantıları ve özellik isteklerini önceden tahmin etmiş olsaydınız ve emrinizde biraz zaman geçirdiyseniz ve (potansiyel olarak işe yaramaz) genellemelerle sıkıcı bir hafta sonu geçirmek isterseniz , en genel olandan başlayarak başlayabilirsiniz . Ama sadece bir olarak özel yöntemle. Yalnızca müşterinin genel yöntem olarak talep ettiği basit yöntemi gösterdiğiniz sürece, güvende olursunuz.

tl; dr :

Asıl soru, aslında "bir yöntemin ne kadar yeniden kullanılması gerektiği" değil. Sorun, bu yeniden kullanılabilirliğin ne kadarının açığa çıktığı ve API'nin neye benzediğidir. Zaman testine dayanabilen güvenilir bir API oluşturmak (daha sonraki gereksinimler daha sonra ortaya çıksa bile) bir sanat ve zanaattır ve konu burada ele alınamayacak kadar karmaşıktır. Bu sunuma bir başlangıç ​​için Joshua Bloch veya API tasarım kitabı wiki'den bir göz atın .


dayLightSavings()aramak dayLightSavings(2018)bana iyi bir fikir gibi gelmiyor.
Koray Tugay

@KorayTugay İlk istek "2018 için gün ışığından yararlanma" yazması gerektiği zaman, sorun değil. Aslında bu olduğunu başlangıçta uygulanan yöntem kesinlikle. " Cari yıl için gün ışığından yararlanma" yazdıracaksa , o zaman elbette arayacaksınız dayLightSavings(computeCurrentYear());. ...
Marco13

0

Temel bir kural şudur: yönteminiz yeniden kullanılabilir olmalı… tekrar kullanılabilir olmalıdır.

Yönteminizi yalnızca tek bir yerde arayacağınızı düşünüyorsanız, yalnızca arama sitesi tarafından bilinen ve bu yöntem için geçerli olmayan parametreleri içermelidir.

Daha fazla arayanınız varsa, diğer arayanlar bu parametreleri geçebildiği sürece yeni parametreler ekleyebilirsiniz; Aksi takdirde yeni bir metoda ihtiyacınız vardır.

Arayanların sayısı zamanla artabileceğinden, yeniden düzenleme veya aşırı yükleme için hazırlıklı olmanız gerekir. Çoğu durumda, ifade seçmek ve IDE'nizin "özüt parametresi" eylemini çalıştırmak için kendinizi güvende hissetmeniz gerektiği anlamına gelir.


0

Ultra kısa cevap: Diğer koda daha az eşleşme veya bağımlılık Jenerik modülünüz ne ne kadar fazla olursa o kadar çok tekrarlanabilir.

Senin örnek sadece bağlıdır

import java.time.*;
import java.util.Set;

Bu yüzden teoride oldukça tekrar kullanılabilir.

Uygulamada, bu kodu gerektiren ikinci bir usecase'iniz olacağını düşünüyorum. ilkesini , bu koda ihtiyaç duyan 3 farklı yoksa, tekrar kullanılamaz hale getirmem.

Yeniden kullanılabilirliğin diğer yönleri, Test Odaklı Gelişim ile özdeşleştirilen kullanım kolaylığı ve odaklanmadır : Genel modülünüzü lib kullanıcılarınız için kodlama örneği olarak kolay bir şekilde kullandığını gösteren / belgeleyen basit bir birim testiniz varsa, bu yardımcı olacaktır.


0

Bu, yakın zamanda oluşturduğum bir kuralı belirtmek için iyi bir fırsat:

İyi bir programcı olmak geleceği tahmin edebilmek anlamına gelir.

Tabii ki, bu kesinlikle imkansız! Sonuçta, asla emin olamayacaksın kullanıcılarınızın isteyeceksiniz yeni özellikleri, yapmak isteyeceğinizi ilgili hangi görevlerin, daha sonra yararlı ne bulacaksınız genellemeler, & c. Ancak deneyim bazen size neyin kullanışlı olabileceği konusunda kabaca bir fikir verir.

Buna karşı dengelemeniz gereken diğer faktörler, ne kadar ekstra zaman ve çaba harcayacağı ve kodunuzu ne kadar karmaşık hale getireceğidir. Bazen şanslısın ve daha genel bir problemi çözmek aslında daha kolay! (En azından kavramsal olarak, kod miktarında değilse.) Ama daha sık olarak, zaman ve çabadan birinin yanı sıra karmaşıklık maliyeti de vardır.

Bir genelleme ihtiyaç duyulacak çok muhtemel olduğunu düşünüyorum eğer bir eklenene kadar Yani, (yaptığını genellikle değer çok fazla iş ya da karmaşıklık sağlamadıkça); fakat çok daha az muhtemel görünüyorsa, o zaman muhtemelen değildir (çok kolay ve / veya kodu basitleştirmediği sürece).

(Son bir örnek için: geçen hafta bana bir sistemin süresi dolduktan 2 gün sonra yapması gereken eylemler için bir spesifikasyon verildi. Tabii ki 2 günlük süreyi bir parametre haline getirdim. Bu hafta iş milleti memnun oldular. Bu geliştirme için sormak üzereydim! Şanslıydım: kolay bir değişim oldu ve tahmin edilmesinin oldukça muhtemel olduğunu tahmin ediyorum.Genellikle yargılaması zor, ama yine de tahmin etmeye çalışmaya değer ve deneyim genellikle iyi bir rehberdir .)


0

Öncelikle, 'Yöntemlerimin ne kadar tekrar kullanılabilir olduğunu nasıl bilebilirim?' İçin en iyi cevap "deneyim" dir. Bunu birkaç bin kez yapın ve genellikle doğru cevabı alırsınız. Ama bir teaser olarak, size sonuncuyu verebilirim. Bu cevabın satırı: Müşteriniz size ne kadar esneklik ve kaç genelleme katmanı aramanız gerektiğini söyleyecektir.

Bu cevapların çoğunun özel tavsiyeleri var. Daha genel bir şeyler vermek istedim ... çünkü ironi geçmek çok eğlenceli!

Bazı cevapların da belirttiği gibi, genellik pahalıdır. Ancak, gerçekten değil. Her zaman değil. Masrafı anlamak yeniden kullanılabilirlik oyunu oynamak için esastır.

Bazı şeyleri "geri döndürülemez" den "geri döndürülebilir" e kadar ölçeklendirmeye odaklanıyorum. Düzgün bir ölçek. Gerçekten geri dönüşü olmayan tek şey "projeye harcanan zaman" dır. Bu kaynakları asla geri alamayacaksın. Biraz daha az geri dönüşümlü, Windows API gibi "altın kelepçe" durumlar olabilir. Kaldırılan özellikler on yıllarca bu API'da kalıyor, çünkü Microsoft'un iş modeli bunu gerektiriyor. Bazı API özelliğini geri alarak ilişkileri kalıcı olarak zarar görecek müşterileriniz varsa, bu geri dönüşü olmayan olarak değerlendirilmelidir. Ölçeğin diğer ucuna baktığınızda, prototip kodu gibi şeylere sahipsiniz. Nereye gittiğini sevmiyorsan, basitçe fırlatabilirsin. Biraz daha az geri dönüşümlü olan dahili kullanım API'leri olabilir. Bir müşteriyi rahatsız etmeden refaktor edilebilirler,zaman (hepsinin en geri dönüşü olmayan kaynağı!)

Öyleyse bunları bir ölçüye koy. Şimdi bir sezgisel başvuru uygulayabilirsiniz: tersinir bir şey ne kadar fazlaysa, onu gelecekteki görünüş etkinlikleri için o kadar fazla kullanabilirsiniz. Bir şey geri döndürülemezse, yalnızca somut müşteri odaklı görevler için kullanın. Bu nedenle, sadece müşterinin ne istediğini ve daha fazlasını yapmalarını öneren aşırı programlama gibi ilkeler görüyorsunuz. Bu ilkeler, pişman olduğunuz bir şeyi yapmadığınızdan emin olmanız açısından iyidir.

DRY ilkesi gibi şeyler bu dengeyi hareket ettirmenin bir yolunu gösterir. Kendinizi yinelenen bulursanız, temelde dahili bir API olanı oluşturma fırsatı budur. Hiçbir müşteri görmez, böylece her zaman değiştirebilirsiniz. Bu dahili API'ye sahip olduğunuzda, şimdi ileriye dönük şeylerle oynamaya başlayabilirsiniz. Eşinizin size vereceği kaç tane farklı zaman dilimine dayanan görev olduğunu düşünüyorsunuz? Saat dilimi temelli görevler isteyebilecek başka müşterileriniz var mı? Buradaki esnekliğiniz mevcut müşterilerinizin somut talepleri tarafından satın alınır ve gelecekteki müşterilerin gelecekteki potansiyel taleplerini destekler.

Doğal olarak DRY'den gelen bu katmanlı düşünme yaklaşımı, doğal olarak israf etmeden istediğiniz genellemeyi sağlar. Ancak bir sınır var mı? Elbette var. Ama onu görmek için, ağaçlar için ormanı görmek zorundasınız.

Çok sayıda esneklik katmanınız varsa, bunlar genellikle müşterilerinizle karşılaşan katmanların doğrudan kontrol edilmemesine neden olur. Asla görmemesi gereken 10 kattan aşağı inen esneklik nedeniyle müşteriye neden istediklerini elde edemediklerini acımasız bir şekilde görevlendirdiğim bir yazılım kullandım. Kendimizi bir köşeye yazdık. İhtiyacımız olduğunu düşündüğümüz tüm esnekliğe sahip bir düğüme kendimizi bağladık.

Dolayısıyla, bu genelleme / NEM ALMA püf noktasını yaptığınız zaman , her zaman müşterinize bir darbe uygulayın . Sizce eşiniz bir sonraki için ne isteyecek? Kendini bu ihtiyaçları karşılayacak bir pozisyona mı sokuyorsun? Eğer ustalığa sahipseniz, müşteri gelecekteki ihtiyaçlarını etkili bir şekilde size söyleyecektir. Eğer bu el becerisine sahip değilseniz, çoğumuz sadece tahminde bulunun! (özellikle eşlerle!) Bazı müşteriler büyük esneklik isteyecek ve bu katmanların esnekliğinden doğrudan faydalandıkları için tüm bu katmanlarla geliştirdiğiniz ekstra maliyeti kabul etmeye istekli olacaktır. Diğer müşteriler daha çok sabit olmayan gereksinimlere sahipler ve gelişimin daha doğrudan olmasını tercih ediyorlar. Müşteriniz size ne kadar esneklik ve kaç genelleme katmanı aramanız gerektiğini söyleyecektir.


Peki, bunu 10000 kez yapan başka insanlar da olmalı, peki neden 10000 kez yapmalı ve başkalarından öğrenebileceğimde deneyim kazanmalıyım? Cevap her birey için farklı olacağından, tecrübeli cevaplar benim için geçerli değil mi? Ayrıca bu Your customer will tell you how much flexibility and how many layers of generalization you should seek.hangi dünya?
Koray Tugay

@KorayTugay İş dünyası. Müşterileriniz size ne yapacağınızı söylemiyorsa, yeterince dinlemiyorsunuz demektir. Tabii ki, size her zaman kelimelerle söylemeyecekler, ama size başka yollarla söyleyecekler. Tecrübe daha ince mesajlarını dinlemenize yardımcı olur. Henüz bir yeteneğiniz yoksa, şirketinizde bu ince müşteri ipuçlarını dinleme becerisine sahip birini bulun ve yönlendirme için onları katlayın. CEO ya da pazarlamada olsa bile birileri bu yeteneğe sahip olacak.
Cort Ammon

Sizin durumunuzda, çöpü dışarı çıkarmamış olsaydınız, çünkü belirli bir çözümü kırmak yerine bu zaman dilimi sorununun genel bir versiyonunu kodlamakla çok meşguldünüz, müşteriniz ne hissederdi?
Cort Ammon

Yani, ilk yaklaşımımın doğru olanı kabul ettiniz, 2018 kodlaması ilk yıldaki yılı parametreleştirmek yerine? (btw, Bu gerçekten benim müşterimi dinlemiyor bence, çöp örneği. Bu müşterinizi tanıyor. Oracle'dan destek alsa bile, gündüz listesine bakmak istediğimde dinleyeceğiniz ince mesajlar yok. 2018 için değişir.) Zaman ayırdığınız için teşekkürler ve cevap btw.
Koray Tugay

@KorayTugay Herhangi bir ek ayrıntı bilmeden, kodlamanın doğru bir yaklaşım olduğunu söyleyebilirim. Gelecekteki DLS koduna ihtiyaç duyup duymayacağınızı ya da daha sonra ne tür bir istek verebileceğini hiçbir fikriniz yoktu. Müşteriniz sizi test etmeye çalışıyorsa, elde ettikleri şeyi alırlar = D
Cort Ammon

0

Etik olarak eğitilmiş hiçbir yazılım mühendisi, bir DestroyBaghdad prosedürü yazmayı asla onaylamaz. Temel mesleki etik onun yerine Bağdat'ın parametre olarak verilebileceği bir DestroyCity prosedürü yazmasını gerektirir.

Bu, gelişmiş yazılım mühendisliği çevrelerinde "şaka" olarak bilinen bir şeydir. Şakalar bizim "doğru" dediğimiz şey olmak zorunda değildir, ancak komik olmak için genellikle doğru bir şeyi ima etmeleri gerekir.

Bu özel durumda, "şaka" "doğru" değildir. Herhangi bir şehri yok etmek için genel bir prosedür yazarken yer alan iş , birini yok etmek için gerekli olanın ötesinde bir büyüklük emri verebileceğimizi, güvenle kabul edebiliriz. belirli birKent. Aksi takdirde, bir ya da birkaç şehri yıkmış olan herhangi biri (İncil'deki Yeşu, diyoruz ya da Başkan Truman), yaptıklarını önemsizce genelleştirebilir ve istedikleri herhangi bir şehri imha edebilirler. Aslında bu durum böyle değil. Bu iki kişinin ünlü olarak az sayıda belirli şehri yok etmek için kullandığı yöntemler, hiçbir zaman yalnızca herhangi bir şehirde işe yaramayacaktı. Duvarları farklı rezonans frekansına sahip ya da yüksek irtifa hava savunmaları daha iyi olan başka bir şehir, küçük ya da temel yaklaşım değişikliklerine (farklı bir eğimli trompet ya da roket) ihtiyaç duyacaktır.

Bu, zaman içindeki değişikliklere karşı kodun korunmasına da yol açar: modern inşaat yöntemleri ve her yerde bulunan radar sayesinde, artık bu yaklaşımların hiçbirine düşmeyecek birçok şehir var.

Tamamen genel bir araç geliştirmek ve test etmek, herhangi bir şehri yıkacak , yalnızca bir şehri yıkmayı kabul etmeden önce , umutsuzca verimsiz bir yaklaşımdır. Etik olarak eğitilmiş hiçbir yazılım mühendisi, bir problemi, işvereninin / müşterisinin gerçekte gösterilmesi gerekmeksizin ödemek zorunda olduğu miktardan daha fazla iş gerektiren bir ölçüde genelleştirmeye çalışmaz.

Öyleyse doğru olan ne? Bazen genellik eklemek önemsizdir. Öyleyse, her zaman önemsiz olduğunda genelliği eklemeli miyiz? Uzun vadeli bakım meselesi nedeniyle hala "hayır, her zaman değil" diyebilirim. Yazarken, tüm şehirlerin temelde aynı olduğunu varsayalım, bu yüzden DestroyCity ile devam ediyorum. Bunu bir kez yazdım, (girdilerin sayısız numaralandırılabilir alanından dolayı) bilinen tüm şehirleri yineleyen ve işlevin her birinin üzerinde çalıştığından emin olun (bunun nasıl çalıştığından emin değilsin. Muhtemelen City.clone () yöntemini çağırır.) klonu yok eder mi?

Uygulamada, işlev yalnızca Bağdat'ı yok etmek için kullanılır, birinin tekniklerime dirençli yeni bir şehir inşa ettiğini varsayalım (derin yeraltında falan). Şimdi gerçekten var olmayan bir kullanım durumu için bir entegrasyon testi başarısızlığım var ve Irak’ın masum sivillerine karşı terör kampanyama devam etmeden önce, Subterrania’yı nasıl tahrip edeceğimi bulmak zorundayım. Etik olsun ya da olmasın boşver, aptal ve acayip zamanımı boşa harcıyor .

Peki, herhangi bir yıl için gün ışığından yararlanma çıkaran bir işlev mi istiyorsunuz , yalnızca 2018 için veri çıktı mı? Belki, ama kesinlikle test senaryolarını bir araya getirmek için küçük bir miktar ekstra çaba gerektirecek. Gerçekten sahip olduğunuzdan daha iyi bir zaman dilimi veritabanı elde etmek için büyük miktarda çaba gerektirebilir. Mesela 1908'de Ontario Limanı kasabası Ontario, 1 Temmuz'da başlayarak DST dönemine girdi. İşletim sisteminizin saat dilimi veritabanında mı? Düşünmedim, bu yüzden genelleştirilmiş işleviniz yanlış . Tutamayacağı sözleri veren kod yazarken özellikle etik olan hiçbir şey yoktur.

Tamam, öyleyse, uygun uyarılarla, 1970'lerden günümüze, yıllarca zaman dilimi ayarlayan bir işlev yazmak kolaydır. Ancak yazdığınız işlevi almak ve yılı parametreleştirmek için genellemek kadar kolaydır. Bu yüzden, şimdi genelleştirmek, yaptığınız şeyi yapmak ve ihtiyaç duyduğunuzda ve ne zaman ihtiyacınız olduğunu genelleştirmek için artık etik / mantıklı değildir.

Bununla birlikte, karınızın neden bu DST listesini kontrol etmek istediğini bilseydiniz , o zaman aynı soruyu 2019'da tekrar sorup sormadığını ve eğer öyleyse, bu döngüyü vererek kendi başınıza bırakıp bırakamayacağınız konusunda bilgilendirilmiş bir fikre sahip olacaksınız. onu yeniden derlemeye gerek kalmadan arayabileceği bir işlev. Bu analizi yaptıktan sonra, "son yıllarda genelleşmeli" sorusunun cevabı "evet" olabilir. Ancak , kendiniz için başka bir sorun daha yaratıyorsunuz ; bu, gelecekteki saat dilimi verilerinin yalnızca geçici olduğu ve bu nedenle 2019 için çalıştırdığı takdirde bugün, onu en iyi tahminde bulunduğunun farkında olabilir veya olmayabilir. Bu yüzden hala daha az genel işlev için gerekli olmayacak bir sürü belge yazmanız gerekiyor ("veriler zaman dilimi veri tabanının veri tabanına aittir. Özel davayı reddederseniz, o zaman bunu her zaman yapıyorsanız, 2018 verisine ihtiyaç duyduğu görevi üstlenemiyor, 2019 ile ilgili saçmalıklardan dolayı henüz umursamıyor bile.

Onları düzgün düşünmeden zor şeyler yapmayın, çünkü şaka size söylemişti. Yararlı mı Bu derece yararlılık için yeterince ucuz mu?


0

Bu, çizilmesi kolay bir çizgi çünkü mimari astronotların tanımladığı şekilde yeniden kullanılabilirlik bollock'lar.

Uygulama geliştiricileri tarafından oluşturulan hemen hemen tüm kodlar son derece etki alanına özgüdür. Bu 1980 değil. Zahmete değer her şey zaten bir çerçevede.

Soyutlamalar ve sözleşmeler dokümantasyon ve öğrenme çabası gerektirir. Lütfen sadece onun uğruna yenilerini yaratmayı bırak. (Ben bakıyorum senin JavaScript insanlar!)

Seçtiğiniz çerçevede gerçekten olması gereken bir şey bulmuş olmanızın imkansız fantezisini şımartalım. Sadece genelde yaptığınız gibi, kodu açamazsınız. Oh hayır, yalnızca amaçlanan kullanım için değil, aynı zamanda amaçlanan kullanımdan ayrılmalar için, tüm bilinen son durumlar için, akla gelebilecek tüm arıza modları, tanılama için test durumları, test verileri, teknik belgeler, kullanıcı belgeleri, sürüm yönetimi, destek için test kapsamına ihtiyacınız var. senaryolar, regresyon testleri, değişim yönetimi ...

İşvereniniz bunun için para ödemekten mutlu mu? Hayır diyeceğim.

Soyutlama esneklik için ödediğimiz bedeldir. Kodumuzu daha karmaşık ve anlaşılması zorlaştırır. Esneklik gerçek ve mevcut bir ihtiyacı karşılamadıkça, sadece yapmayın çünkü YAGNI.

HTMLRenderer: Sadece ele almam gereken gerçek bir dünya örneğine bakalım. Bir yazıcının aygıt içeriğine dönüştürmeye çalıştığımda düzgün ölçekleme değildi. Varsayılan olarak, GDI + yerine (ki, antialyalar değil) GDI (ölçekleme yapmıyor) kullandığını keşfetmem bütün günümü aldı, çünkü iki mecliste bulmadan önce altı düzeye inmek zorunda kaldım. bir şey yapan kod .

Bu durumda yazarı affedeceğim. Soyutlama aslında gerekli bunun nedeni ise WinForms, WPF, dotnet Çekirdek, Mono ve PDFsharp: Beş farklı render hedefleri hedefleyen çerçeve kodu.

Ama bu sadece benim noktanın altını neredeyse kesinlikle edilir değil tüm platformlarda yüksek performans vurgulamak amacıyla çok sayıda platformu hedefleme son derece karmaşık bir şey (HTML stil ile render) yapıyor.

Kişisel kod neredeyse kesinlikle sadece tek satılık değildir bir uygulamada, eyaletinizde uygulamak işveren ve vergi kurallarını uygulamak iş kuralları ile henüz başka bir veritabanı ızgara olduğunu.

Bütün bu dolaysızlık sizin sahip olmadığınız bir sorunu çözüyor ve kodunuzu okumayı daha da zorlaştırıyor, bu da bakım maliyetini büyük ölçüde artırıyor ve işvereninize büyük bir kötülük. Neyse ki, bu konuda şikayet etmesi gereken insanlar, onlara ne yaptığınızı anlayamıyorlar.

Buna karşı çıkan bir argüman, bu tür bir soyutlamanın teste dayalı gelişimi desteklediğini, ancak TDD'nin de çok yönlü olduğunu düşünüyorum, çünkü işin gereksinimleri hakkında net, eksiksiz ve doğru bir anlayışa sahip olduğunu varsayıyor. TDD, NASA ve tıbbi ekipman ve kendi kendine sürüş arabaları için kontrol yazılımı için mükemmel, ancak herkes için çok pahalı.


Bu arada, dünyadaki tüm gün ışığı tasarrufunu tahmin etmek mümkün değildir . Özellikle İsrail'in her yıl her yere sıçrayan 40 geçişi var çünkü yanlış zamanda dua eden insanlar olamaz ve tanrı gün ışığından yararlanma yapmıyor.


Soyutlamalar ve öğrenme çabası hakkında söylediklerinizle hemfikir olmama rağmen, özellikle de "JavaScript" adlı suistimali hedeflediğinde, ilk cümleye kesinlikle katılmam gerekiyor. Yeniden kullanılabilirlik birçok düzeyde gerçekleşebilir, çok fazla azalmayabilir ve atma kodu atma programcıları tarafından yazılabilir. Ama olan en az yeterli idealist insanlar amacı yeniden kullanılabilir kodu. Bunun sahip olabileceği yararları görmüyorsanız, sizin için üzücü.
Marco13

@ Marco13 - İtirazın makul olduğundan, noktayı genişleteceğim.
Peter 23: 22'de

-3

En azından java 8 kullanıyorsanız, esasen bir zaman dilimi koleksiyonu gibi görünmesini sağlamak için WorldTimeZones sınıfını yazarsınız.

Ardından, WorldTimeZones sınıfına bir filtre (Tahmini filtre) yöntemi ekleyin. Bu, arayan kişinin parametre olarak bir lambda ifadesi geçirerek istedikleri her şeyi filtrelemesini sağlar.

Temelde, tek filtre yöntemi, yüklemeye iletilen değerde yer alan herhangi bir şeyi filtrelemeyi destekler.

Alternatif olarak, çağrıldığında zaman dilimi akışı üreten WorldTimeZones sınıfınıza bir stream () yöntemi ekleyin. Daha sonra arayan kişi, herhangi bir uzmanlık alanı yazmadan istediğiniz gibi filtre uygulayabilir, haritalandırabilir ve küçültebilir.


3
Bunlar iyi genelleme fikirleridir ancak bu cevap soruda sorulanın işaretini tamamen kaçırmaktadır. Sorun, çözümü nasıl en iyi şekilde genelleyeceğimizle ilgili değil, genellemelerde çizgiyi nerede çizdiğimiz ve bu düşünceleri etik olarak nasıl tartıştığımızla ilgilidir.
maple_shaft

Bu yüzden onları yaratılışın karmaşıklığı tarafından değiştirilen destek vakaları sayısına göre tartmanız gerektiğini söylüyorum. Bir kullanım vakasını destekleyen bir yöntem, 20 kullanım vakasını destekleyen bir yöntem kadar değerli değildir. Diğer taraftan, bildiğiniz tek şey bir kullanım durumuysa ve kodlaması 5 dakika sürüyorsa, bunun için gidin. Genelde, belirli kullanımları destekleyen kodlama yöntemleri, genelleme yöntemi hakkında sizi bilgilendirir.
Rodney P. Barbati
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.