Scala için sistem tasarımını yeniden icat


35

Çok, çok, bir ay önce, ustalarımı Nesne Yönelimli Yazılım Mühendisliğinde yaptım. Her şeyi ele aldım: proje başlatma, gereksinimler, analiz, tasarım, mimari, geliştirme, vb. Tüm zamanların en sevdiğim BT kitabı, Tecrübeye Dayalı Bir Yaklaşım (IBM-1996) olan Nesneye Yönelik Yazılım Geliştirme idi. Zamanlarının gerçek uzmanlarından oluşan bir grup tarafından yaratılmış bir kitap. Nesneye yönelik analiz, tasarım ve geliştirme yöntemlerine iş ürünü merkezli yaklaşımı açıklar.

Oyun tasarladım, geliştirdim, mutlu oldum ve oyunumun başındaydı ama biraz tarihli hissetmeye başladım: Çevik hareketler günün modası haline geldi ve bazı iyi bilinen yinelemeli ve artımlı yaklaşımları yeni kalça sözcükleriyle yeniden markalaştırdı. Aniden deneyimsiz geliştiriciler, sanki sihir tarafından değiştirilmiş gibi "gereksinimler" veya "mimarlık" dediğimde kaşlarını çatmaya başladı.

Tasarım ve geliştirme eğlenceli geçti ve BT endüstrisini geride bırakmak üzereydim.

Sonra Scala'yı keşfettim. Oh, tozlu bir yoldaki yumuşak yağmur gibi. Her şey netleşti, hava tekrar tatlı oldu ve sabit diskimin küçük ışığı gecenin derinliklerinde titreyerek beni keşif dünyamda koruyacaktı.

Sistem tasarımını severim. Ben bir programcıdan çok, kalbindeki mimarım. Analiz etmeyi, tasarlamayı, düşünmeyi, tartışmayı, gelişmeyi seviyorum. Sadece basit, temiz ve net tasarımları severim.

Saf Scala çözümlerini nasıl tasarlarız?

Elbette konvansiyonel dizi diyagramları, etkileşim diyagramları, nesne diyagramları, vs., zorunlu ve işlevsel nesne yönelimli sistemleri harmanlamanın iyiliği için değiştirilebilir veya geliştirilebilir. Elbette bambaşka bir şeyin açılışı var!

Ben şişkinlik karmaşıklığı aramıyorum - Esnek basitlik arıyorum. Scala'ya benzeyen aslında basit ve kolaydır (farklı olsa da), ancak bir çift Yoga pantolonu gibi gereksinimlerinize uyacak şekilde genişletilebilir. Bu sevimli dil için basit başlayacak ve gereksinimlerinize ve etki alanınıza uyacak şekilde genişletilebilecek bir tasarım sistemi olmalıdır. Elbette UML olamaz!

Peki saf Scala sistemlerini nasıl tasarlarız? Bir an için, sıfırdan komple bir sistem tasarlama lüksüne sahip olduğunuzu ve yalnızca Scala kullanacağınızı biliyorsunuz - Modelleriniz nasıl görünecek? Yapı ve davranışı tanımlamak için ne tür diyagramlar gerekir? Yeni, hafif, yenilikçi bir araç seti yerine mevcut modelleme tekniklerini genişletmenin karmaşıklığına dahil olmadan Seçenekler, eşleşmeler, karışımlar, tekil Nesneler, vb. Nasıl modellenir?

Böyle bir tasarım / süreç / çözüm var mı , yoksa bunu icat etme zamanı mı?


+1 "bir çift Yoga pantolonu gibi ihtiyacınıza uyacak şekilde genişletilebilir."
Russell

FWIW, UML ve Scala hakkında, ilginizi çekebilecek bir soru gördüm. Ayrıca, işlev tarafına giderseniz, kategori teorisi notasyonlarını incelemeye değer olabilir. Gregory Meredith genellikle bu konuda bazı ilginç sunumlara bağlantı verir, ancak blogunda ne olduğuna emin değilim - yine de göz atmaya değer.
Daniel C. Sobral

Çok değer ;-) Kazmam için bana yön veriyor. Teşekkürler Daniel
Jack

Kontrol etmeye değer, Scala için "değiştirilmiş" UML, github.com/mnn/Dia2Scala/blob/master/other/Notation.md
WeiChing Lin

Yanıtlar:


12

Bu soruya gerçekten bir cevap veremem, ancak bazı düşünceler sunmama izin verin.

Üniversitede bilgisayar mühendisliği öğrencisiyim ve geçen dönem ben ve bir grup, ana dilimizin Scala olduğu büyük bir yazılım projesi yaptı. Tasarımımızı geleneksel yöntemle yaptık: kullanım alanları, etki alanı modeli, sıra diyagramları, UML sınıf diyagramları; olağan yük. Ve zaten farkında olduğun gibi, onlar zavallı bir durum. İşte bazı nedenler.

İlk önce dizi diyagramlarını düşünün. His bir sekans diyagramının birbirleriyle konuşmaya, yarı-bağımsız aktörler uzun ömürlü, bir kaç kararlı taşımaktadır. Scala'da nesneler kısa bir süre için yaratılma eğilimindedir. Ayrıca, vaka sınıfları "aptal" nesneleri, yalnızca veri içeren ve kodsuz olarak teşvik eder, bu nedenle iletilerin iletilmesi konsepti yerinde değildir. Ancak dizi diyagramları için en zor olanı, birinci sınıf işlevleri dahil etmenin iyi bir yolunun bulunmamasıdır; Burada veya orada sadece bir geri arama kullanan bir OO tasarımında çalışmak için yapılabilir, ancak bu, kontrolün aktarılmasının birincil yoluysa, sıralama diyagramının gerçek kodunuzu çok az yansıttığını göreceksiniz.

UML sınıf diyagramları Scala'ya daha uygundur; evet, karışımlar iyi gelmiyor, ama bu elden geçirilmek yerine "çimdiklenebilecek" bir şey. Ancak bunun eksik olabileceğini düşünüyorum.

Scala'nın neden "aptal nesneler" olduğunu tekrar düşünün. Yöntemsiz bir vaka sınıfı yazarsanız:

case class NewInvite(user: User, league: League)

Herhangi bir yönteme ihtiyacınız yok , çünkü üyelerin türleri onlarla yapabilecekleriniz hakkında bir şey vaat ediyor. Aslında, her şeyi vaat ediyorlar . Ve programın içindeki her kapsamda, kapsam içindeki değişkenler ve türleri, kodun o noktada nereye gidebileceği konusunda bir şey vaat ediyor.

Bu yüzden, belki biraz geri çekilirsek ve kendi başıma türler hakkında çok az düşünmek yerine, programımızı kodumuzun hangi bağlamda yaşayacağı ve programcıya (ve sonunda kullanıcıya ne vaat edeceği) göre tasarlayın. ) bu bağlamların her birinde, Scala'ya daha uygun bir tanım bulacağız. Ancak ben sadece burada tahmin ediyorum ve bence bu alanda daha fazla araştırılması gereken haklısınız.


"Programcıya ne vaat edildi" - buna güzel bir yüzüğü var ;-)
Jack

12

UML, 80'li yılların sonları ve 90'lı yılların başlarında "Kabarcık Savaşları" ndan ortaya çıktı. Her zaman gösterim için bir uzlaşma olmuştur , bir tasarım yöntemi değil. UML'ye atfedilen sütunların çoğu gizlice “Adım 1: bir sınıf modeli çizin” yazan bir tasarım yönteminin sonucudur.

Eskileri canlandırmamız gerektiği kadar yeni tasarım yöntemlerine de ihtiyacımız olmadığını öneriyorum . Sorumlulukları tanımlamak ve tahsis etmekle başlayın, sonra onların uygulamalarını anlamaya gidin ve bu fikirleri iletmek için iyi notlar ve temsillerle devam edin.

Sorumluluklar

CRC, Scala için de çalışıyor, başka bir OO dili için de çalışıyor; Antropomorfize edici aktörlerle sorumluluk dağılımının modellenmesi ve işbirliklerinin anlaşılması hala iyi sonuç vermektedir.

Büyük ölçekte, hala nesnelerle tasarım yapıyor olmalısınız. Nesne sınırları, kapsülleme sınırlarıdır. Değişken durum ve uygulama ayrıntılarını bu nesne sınırları içinde tutun. Vaka sınıfları iyi arayüz nesneleri oluşturur, böylece vanilya koleksiyonları ve veri yapıları da yapılır.

Uygulamaları anlama

Bu veri yapılarını diğer nesnelerden ziyade nesne sınırları boyunca geçirin ve şunu bulacaksınız: a) bir nesnenin içini gizli tutmak kolaylaşır ve b) nesne davranışlarının işlevsel uygulamaları çok anlamlı olur.

Programınızın büyük ölçekli yapısını "büyük küçük işlevler havuzu" olarak değerlendirmek istemeyeceksiniz. Bunun yerine, doğal olarak sistemin yalıtılmış kısımları arasındaki dar arayüzlere doğru çekim yaparsınız. Bunlar yine de nesnelere çok benziyor ve hissediyor, bu yüzden devam et ve onları nesne olarak uygula!

Temsil ve Gösterim

Bu nedenle, bu tasarım yapısı içerisinde düşüncelerinizi kafanızdan çıkarmanız ve başkalarıyla paylaşmanız gerekir.

UML'nin sisteminizin büyük ölçekli yapısını tanımlamak için hala yararlı olabileceğini düşünüyorum. Yine de, daha düşük detay seviyelerinde yardımcı olmayacak.

Ayrıntılı ayrıntıda, okuryazar programlama tekniklerini deneyin.

Ayrıca minidocs kullanmayı seviyorum. Bir minidoc, sistem davranışının belirli bir yönünü tanımlayan bir veya iki sayfalık bir belgedir. Güncellenmesi için kodun yanına oturmalı ve tam zamanında öğrenmeyi sağlayacak kadar kısa olmalıdır. Doğru bir soyutlama seviyesine ulaşmak biraz pratik gerektirir: yararlı olacak kadar spesifik olması gerekir, ancak bir sonraki kod değişikliğiyle geçersiz kılınacak kadar spesifik olmamalıdır.


9

Saf Scala çözümlerini nasıl tasarlarız?

Bence bu soruyla yanlış bir açı yapıyorsun. Çözümler için genel tasarımınız belirli bir dile bağlı olmamalıdır; bunun yerine eldeki soruna karşılık gelmelidir. Scala'nın en güzel yanı, tasarımınızı uygulama zamanı geldiğinde yolunuza çıkmayacak kadar esnek olmasıdır. Java, diğer taraftan, bazı tasarım kararları (öncelikle, her şey-is-a sınıfı zihniyet) uygular olacak biraz aksak hissettirecek.

Tasarlarken, durumu açıkça modellemeye çalışın . Akılda kalıcı veriler ve açık durum, üzerinde düşünülmesi daha kolay olan tasarımlara yol açar. Çoğu zaman bu, işlevsel bir programlama çözümüne güzel bir şekilde dönüşecektir, ancak zaman zaman mutasyon ve zorunluluk tarzı kullanmanın daha verimli veya daha basit olduğunu keşfedebilirsiniz; Scala, her ikisini de oldukça iyi bir şekilde barındırıyor.

Scala'nın yolunuzdan çıkmakta bu kadar iyi olmasının bir diğer nedeni de ihtiyaçlarınıza uyan DSL'ler üretebilmesi . Belli bir problemi çözen kendi dilinizi "normal" bir şekilde çözebilir ve ardından Scala'da uygulayabilirsiniz.

Özetle, asıl amacım, "saf Scala çözümleri tasarlamaya" çalışmamanız gerektiğidir. Çözümleri mümkün olan en doğal ve anlaşılır şekilde tasarlamalısınız ve Scala'nın bu çözümleri çeşitli şekillerde uygulamanıza yardım edebilecek inanılmaz derecede esnek bir araçtır. Bildiğiniz tek şey bir çekiç olduğunda, her sorun bir çivi gibi görünmeye başlar, bu yüzden size sunulan çeşitli yaklaşımları araştırdığınızdan emin olun. Tasarım sürecini X, Y ve Z adımlarına kapatmaya çalışmayın, A'dan W'ye kadar olan olanakları kaçırmanız gerekebilir.


4

Haklısın OOD sınırlı ve modası geçmiş. Başlıca avantajı, her önemsiz desen ve tasarım numarası için süslü isimlerle, çok iyi tanımlanmış ve ritüelleştirilmiş olmasıdır. Sistem tasarımına daha modern ve rasyonel yaklaşımlar için benzer bir sistem bulamazsınız.

Yalnızca birkaç şeyi listeleyebilirim: tasarıma, bir alt kümesi Dil Odaklı Programlama (ve Scala topluluğu tarafından yoğun olarak kullanılır) ve Etki Alanına Dayalı Tasarım olarak adlandırılan anlamsal bir yaklaşım. Sonuncusu, daha genel bir semantik tasarım yaklaşımına ilişkin basitleştirilmiş ve OOP'lu bir görünümdür, yalnızca OOD'dan hoşlanıyorsanız keyfini çıkarabilirsiniz.

Ayrıca, diğer işlevsel programlama topluluklarından bir ya da iki numara öğrenmenizi tavsiye ederim - örneğin Haskell ve Scheme, tasarım teknik bilgilerinin tamamı Scala'ya transfer edilmemiş.


3

Soru şuydu: Saf Scala çözümlerini nasıl tasarlarız?

Gibi cevaplar

  1. XYZ kullanıyoruz çünkü ....
  2. ABC kullanıyoruz ama öyle ....
  3. XYZ kullanmaya başladık, fakat daha sonra ABC'yi daha iyi bulduk çünkü ...

böyle bir araç seti veya çözümün bir miktar olgunluk veya genel olarak kabul edilmiş bir varlık olduğunu belirtmiş olabilir.

Scala'ya özgü bir tasarım araç seti düşünmenin uygun olup olmadığıyla ilgili yorumlar farklı bir konudur. Bu konuda benim görüşüm, Scala'nın zorunlu ve işlevsel programlamayı birleştirme biçiminde devrimci olduğu yönünde. Scala, geliştirme uygulamalarına, kavramlara ve ilkelere inanılmaz bir soluk yakalıyor ve Scala'ya en uygun çözümü bulmak için, muhtemelen bir alt kümenin diğer birçok dile de çok iyi hizmet edeceği bir çözüm keşfedeceğiz.

O zaman şunu söylemek güvenli midir, geri dönüş sorusunun cevabını biliyoruz:

“... birini icat etme zamanı geldi mi?”

O olabilir evet ? (' Evet ', çözümün yolunu belirlemediğinde. Mevcut bir çözümü genişleterek veya sıfırdan bir tane yaratarak başarılabilir. Mevcut tasarım seçeneklerinde önemli eksiklikler olmasına rağmen itiraf eder)

Kabul etmemeniz durumunda cevabımı aşağı oylayabilirsiniz. Bir erkek gibi alacağım.


Devrimci? Neden? Lisp, onlarca yıldır zorunlu ve işlevsel yaklaşımların mükemmel bir birleşimi olmuştur. Scala, tür sistemi nedeniyle ilginçtir.
SK-mantık

3
'Devrimci' güçlü ve güçlü bir kelime ise özür dilerim. Scala'nın tekerleği yeniden icat ettiğini ima etmiyorum - ama kesinlikle lastiği yeniden şekillendirdiği kesin. Aslında, Scala birçok programlama dilinin tüm iyiliğinin güzel bir karışımıdır. Eminim ki Lisp'ten de ağır şekilde ödünç alır. Bana göre ve başkaları için hiçbir iddiada bulunmuyorum, Scala dili, kod hakkında doğal olarak oldukça berbat bir şekilde düşündüğüm için devrimci hissediyor. Aynı olan bir tasarım / modelleme dili kesinlikle ücretsiz olacaktır. Tek noktam buydu - Lisp'e ve diğer tüm harika dillere alınma.
Jack,

2

Diller arasında ayrım yapmazdım, java'da da aynı şekilde yapardım. Ancak, işlevselliği yerine OO okulundan geliyorum (cebirsel Haskell veya lisp). Haskell uygulama tasarımı Scala veya Clojure'den gerçekten farklı. Ayrıca bir Scala.js uygulaması tasarımı, durum bilgisi olan DOM nedeniyle farklıdır - uygulamanızın zorunlu olan durum bilgisi olan bir bölümü ile mücadele etmek zordur. Zamanla, durumu ve değişkenliği mümkün olduğunca ortadan kaldırmaya çalışırken OO yöntemini yapmaya alışmıştım. Bir typelevel veya scalaz hayranı olsaydım, uygulamalarım muhtemelen oldukça farklı görünürdü.

  1. Teknoloji yığınına ve müşteri / sunucu sorumluluğu, dağıtık doğa gibi ana tasarım kararlarına karar vermek - veri kalıcılığına gerçekten ihtiyacımız var mı? Uygulamamız için en uygun olan nedir? (kesinlikle henüz kütüphaneler veya çerçeveler değil)

  2. App.scalaTemel türleri (özellikler ve vaka sınıfları) ve rolleri tanımladığım tek bir dosyadan başlayarak - AFK olurken çok fazla düşünürken ve düşünürken. Tek bir dosyadayken oynamak çok kolaydır. Prototip bile basit bir uygulamasa ortaya çıkabilir. Bu aşamaya çok zaman ayırdım, çünkü hiçbir şey mümkün olan en doğru ve esas olarak şeffaf ve mantıklı prototipin yapılmasından daha önemli değildir. Her şey daha fazla tefekkür etmemize yardımcı olur ve başarı olasılığını arttırır.

  3. Şimdi çözümümüzün doğruluğunu kanıtladığımızda, net bir vizyonumuz var ve tüm potansiyel problemler ortaya çıkıyor, ne tür üçüncü taraf kütüphaneleri veya metodolojileri getireceğimizi düşünmenin zamanı geldi. Bu devletli oyuncuları yapacak mıyız, Akka'nın esnekliğine gerçekten ihtiyacımız var mı, .., .. ya da belki değil mi? Bu akışlar için Rx kullanıyor muyuz? 10 etkileşimli özelliğe sahip olduktan sonra çıldırmayacağımız için UI için ne kullanıyoruz?

  4. App.scalayeni özellikler ve sınıflar ortaya çıkıp büyüdüğü için dosyayı çoklu dosyalara bölün. Arayüzleri rollerini anlatmalıdır. Şimdi, mümkünse tip sınıfları ve geçici polimorfizmi kullanmayı düşünmenin vakti geldi. Arayüzünüzü kim çağırırsa, onlar için esnek olmalıdır. Mesele, sadece arayanın ayrıntılarını bırakarak sadece genel işlevleri yerine getirmektir. Bazen uygulamaya çalıştığınız şey Turing-complete benzeri olabilir, bu nedenle GitHub'a özellik istekleri göndermek yerine, arayanların özelliklerini kendi başlarına uygulaması için bir yol sağlamalısınız. Bu şey daha sonra eklemek zor. En başından beri düşünülmeli. DSL tasarlamanın yanı sıra.

  5. tasarımı düşünmek, çünkü uygulama büyüyecek ve yeni özelliklere, optimizasyonlara, sebat etme, kullanıcı arayüzü, uzaktan kumandalama, vb. Unutmayın, hepsi tek bir dosyadayken, bir şeyleri değiştirmek oldukça kolaydır. İnsan beyni, 10+ dosyaya yayıldıktan sonra kaybetmeye başlar. Büyüyen bir tümör gibi, aşırı mühendislik başlar. Uygulamalarımın, bir tür bel kemiği oluşturan birkaç uzun kısmi işlevle sonuçlandığını fark ettim. Çalışmayı kolay buluyorum. Sanırım Akka oyuncuları tarafından bulaştırıldım.

  6. Şimdi ilk gerçek özellikler var, sadece temel işlev değil, test yazmaya başlama zamanı. Neden bu kadar geç? Çünkü bu süre zarfında büyük olasılıkla büyük yeniden yazmalardan geçtiniz ve bu testleri sürdürmekle zaman kaybetmiş olacaksınız. Herhangi bir büyük yeniden tasarım olamayacağından emin olmadıkça testler yazılmamalıdır. Sürekli refactoring'e kolayca dayanabilen entegrasyon testlerini tercih ediyorum ve aslında bir şeyler geliştirmek için daha fazla zaman harcamak istemiyorum. Birkaç kez bana testleri sürdürmek için çok fazla zaman harcadım. Potansiyel hataları düzeltmek kesinlikle kötü testlerden çok işe yarayacaktır. Kötü testler veya ilk andan itibaren yapılan testler büyük ağrıya neden olabilir. Kesinlikle TDD hayranı olmadığımı fark et - IMHO bu saçmalık.

  7. Uygulama tasarımının okunaklı hale getirilmesi, yapılması ve okunabilir tutulması, bileşen rollerinin açık olması. Uygulama büyüdükçe, dahice bir programcı olmadıkça bu şekilde kalmaz ve bu cevabı okursanız büyük olasılıkla siz :-) olmazsınız. Ben de öyle değilim. Bu - bu sorunlara neden olabilir, onları ortadan kaldırmaya çalışın. Ayrıca sizi bir süre rahatsız eden kod kokularını da giderdiğinizden emin olun. Bu noktada proje yöneticiniz (varsa) muhtemelen başını sallamaya başlar. Ona ödediğini söyle.

  8. Tamam, uygulama iyi tasarlanmış mı? Şunlara bağlıdır: Gerçekten kafanızın dışında bile mantıklı olan iyi tanımlanmış rollere sahip misiniz? Bunlardan bazılarını alıp çok fazla çaba göstermeden açabilir misiniz? Aralarındaki endişenin açık bir şekilde ayrılması var mı? Başka bir yere çarpacağından endişe etmeden yeni bir özellik ekleyebilir misiniz (tam olarak ne yaptığınızı tam olarak bildiğinizin işareti)? Genel olarak konuşursak, sorunlara basit pragmatik çözümler içeren bir kitap olarak okunabilir olmalıdır. Hangi IMHO iyi tasarımın ana işaretidir.

Sonuçta, bu sadece zor bir iş ve zaman muhtemelen yöneticilerinizden alamayacaksınız. Burada tarif ettiğim tek şey çok zaman, emek, kahve, çay ve özellikle de AFK'yı düşünmek. Ne kadar çok verirseniz, tasarım o kadar iyi olur. Uygulamaları tasarlamak için genel bir tarif yoktur, sağduyu, pragmatizm, KISS, sıkı çalışma, deneyim iyi tasarım demektir.

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.