Redux - birden fazla mağaza, neden olmasın?


221

Not olarak: Redux (Baobab) için dokümanları okudum ve Google'ın ve testlerinin adil bir bölümünü yaptım.

Neden bu kadar güçlü bir Redux uygulaması sadece bir mağaza var önerilmektedir?

Birden fazla mağaza kurulumuna karşı tek mağaza kurulumunun artılarını / eksilerini anlıyorum ( Bu konuda SO üzerinde birçok soru-cevap var ).

IMO, bu mimari karar projelerinin ihtiyaçlarına göre uygulama geliştiricilerine aittir. Peki neden bu kadar şiddetle Redux için neredeyse zorunlu sondaj noktasına sürülmektedir ( hiçbir şey olsa birden fazla mağaza yapmaktan bizi duruyor )?

EDIT: tek mağazaya dönüştürdükten sonra geri bildirim

Birkaç ay boyunca karmaşık bir SPA'yı neyin düşüneceği konusunda redux ile çalıştıktan sonra, tek mağaza yapısının çalışmak için saf bir zevk olduğunu söyleyebilirim.

Başkalarının tek mağazaya karşı birçok mağazanın neden birçok, birçok kullanım durumunda tartışmalı bir soru olduğunu anlamalarına yardımcı olabilecek birkaç nokta:

  • güvenilirdir : uygulama durumunu incelemek ve içerikle ilgili bilgi edinmek için seçicileri kullanırız. Gerekli tüm verilerin tek bir mağazada olduğunu biliyoruz. Devlet sorunlarının nerede olabileceğine dair tüm sorgulamaları önler.
  • hızlı : mağazamızda şu anda 100'e yakın redüktör var. Bu sayımda bile, sadece bir avuç redüktör herhangi bir dağıtımdaki verileri işler, diğerleri sadece önceki durumu döndürür. Büyük / karmaşık bir mağazanın ( redüktör sayısı ) yavaş olduğu iddiası oldukça tartışmalıdır. En azından oradan herhangi bir performans sorunu görmedik.
  • hata ayıklama dostu : Bu, redux'u bir bütün olarak kullanmak için en ikna edici bir argüman olsa da, tek mağaza için birden fazla mağazaya da gider. Bir uygulama oluştururken süreçte durum hataları ( programcı hataları ) olması gerekir, bu normaldir. PITA, bu hataların hata ayıklanması saatler sürmektedir. Tek mağaza ( ve redux-logger ) sayesinde, herhangi bir devlet sorununa birkaç dakikadan fazla zaman harcamadık.

birkaç işaretçi

Redux mağazanızı oluşturmanın asıl zorluğu, onu nasıl yapılandıracağınıza karar vermektir . Birincisi, yol boyunca yapıyı değiştirmek sadece büyük bir acıdır. İkincisi, çünkü büyük ölçüde uygulamalarınızı nasıl kullanacağınızı ve herhangi bir işlem için uygulama verilerinizi sorgulayacağınızı belirler. Bir mağazanın nasıl yapılandırılacağı konusunda birçok öneri var. Bizim durumumuzda aşağıdakilerin ideal olduğunu gördük:

{
  apis: {     // data from various services
    api1: {},
    api2: {},
    ...
  }, 
  components: {} // UI state data for each widget, component, you name it 
  session: {} // session-specific information
}

Umarım bu geri bildirim başkalarına yardımcı olur.

EDIT 2 - yardımcı mağaza araçları

Hızlı bir şekilde karmaşık hale gelebilecek tek bir mağazayı nasıl "kolayca" yöneteceğinizi merak edenler için. Mağazanızın yapısal bağımlılıklarını / mantığını izole etmeye yardımcı olan bir araç var.

Orada Normalizr bir şemaya göre verilerini normalleştirir. Daha sonra, idbir Sözlük gibi, verilerinizle çalışmak ve verilerinizin diğer bölümlerini almak için bir arayüz sağlar .

O zaman Normalizr'i bilmeden, aynı hatlar boyunca bir şeyler inşa ettim. relational-json bir şema alır ve Tablo tabanlı bir arabirim döndürür ( biraz veritabanı gibi ). Relational-json'un avantajı, veri yapınızın verilerinizin diğer kısımlarına dinamik olarak başvurmasıdır ( esas olarak, verilerinizi normal JS nesneleri gibi herhangi bir yönde hareket ettirebilirsiniz ). Normalizr kadar olgun değil, ama birkaç aydır üretimde başarıyla kullanıyorum.


4
Kullandığınız mağaza yapısı için yaklaşımınızı seviyorum; ancak, bileşen durumu değişikliklerinizle API durumu değişiklikleri eşlemesini nasıl yönetiyorsunuz? Diyelim ki API'mdan alana özgü veriler alıyorum, bu bileşenlerimde bulunan genel bir veri yapısına nasıl dönüşür?
Diniden

Bileşenlerinizin mağaza verilerini nasıl haritaladığı / kullanacağı size bağlıdır. Sorunuzu tam olarak anlamadığımı düşünmeme rağmen, bir sohbet oturumu hazırlayabilir veya başlatabilir misiniz?
Sebastien Daniel

2
Sanırım soru şu olurdu: bileşenleriniz apis durumundan herhangi birini oluşturuyor mu, yoksa yalnızca bileşenler durumuna konulan her şeyi yapıyor mu? SADECE bileşenin durumundan oluşturmayı başardıysanız, bileşenlerinizi ve Kaplarınızı etki alanına özgü verilerin varlığında bile yüksek oranda yeniden kullanılabilir hale getirmenin mükemmel bir yolunu buldunuz. Bileşenleriniz kısmen API durumundan ve bileşen durumundan oluşturuluyorsa, API'deki verileri bileşenlerinizin anladığı genel listelere ve ilkellere eşlemek için Etki Alanına özgü Kapsayıcılar kullandığınızı tahmin ediyorum.
Diniden

2
Redux'u temel olarak işlevsel olarak saf veri eşleştiricileri olan seçicilerle birlikte kullanıyorum. Her bileşen güncellemeleri depolamak için "tepki verir" ve bir değişiklik onunla ilgili ise verileri "seçer" ve buna göre oluşturur. Yani evet, bileşenler SADECE kendileri için önemli olan şeylere dayanarak oluşturulur. Ama bu sadece Redux veya mağaza yapısı yüzünden değil. Bu, bir Immutable veri deposu, veri değişiklikleri için bir referans karşılaştırma testi ve bileşenin ihtiyacı olan verileri, ihtiyaç duyduğu formatta getiren saf bir seçicinin kombinasyonu nedeniyle.
Sebastien Daniel

Hey @SebastienDaniel, mağaza güncellemesindeki değişikliğin onunla alakalı olup olmadığını bilmek için her bir bileşenin yaptığı denetimi nasıl uyguladığınıza bir örnek gösterebilir misiniz? Yani bir tür genel kalıp kullanıyorsanız ... ya da her özel durumda bileşenle ilgili belirli verilerin değişip değişmediğini kontrol ediyorsanız.
John Bernardsson

Yanıtlar:


232

Birden fazla mağaza kullanabileceğiniz uç durumlar vardır (örneğin, aynı anda saniyede birçok kez ekranda bulunan binlerce öğe listesinin güncellenmesiyle ilgili performans sorunlarınız varsa). Bunun bir istisna olduğunu ve çoğu uygulamada asla tek bir mağazadan daha fazlasına ihtiyacınız olmadığını söyledi.

Bunu neden dokümanlarda vurguluyoruz? Flux geçmişinden gelen çoğu kişi , güncelleme kodunu modüler hale getirmenin çözümü olarak birden fazla mağazanın olduğunu varsayacaktır. Bununla birlikte, Redux'un bunun için farklı bir çözümü vardır: redüktör bileşimi.

Bir redüktör ağacına daha fazla bölünmüş birden fazla redüktöre sahip olmak, güncellemeleri Redux'da nasıl modüler tuttuğunuzdur. Bunu tanımıyorsanız ve önce redüktör kompozisyonunu tam olarak anlamadan birden fazla mağazaya gidiyorsanız, Redux tek mağaza mimarisinin birçok avantajını kaçırırsınız:

  • Redüktör bileşiminin kullanılması, waitFordiğer redüktörleri manuel olarak ek bilgilerle ve belirli bir sırayla çağıran bir redüktör yazarak Flux'ta "bağımlı güncellemeler" la uygulanmasını kolaylaştırır .

  • Tek bir mağazada, durumu devam ettirmek, nemlendirmek ve okumak çok kolaydır. Sunucu oluşturma ve veri önyükleme önemsizdir, çünkü istemcide doldurulması ve rehidre edilmesi gereken tek bir veri depolama alanı vardır ve JSON içeriğini mağazanın kimliği veya adı hakkında endişelenmeden tanımlayabilir.

  • Tek bir mağaza Redux DevTools zaman yolculuğu özelliklerini mümkün kılar. Ayrıca redux-undo veya redux-optimist gibi topluluk uzantılarını indirgeyici düzeyinde çalıştıkları için kolaylaştırır. Bu tür "redüktör arttırıcılar" mağazalar için yazılamaz.

  • Tek bir mağaza, aboneliklerin yalnızca sevk işleminden sonra çağrılmasını garanti eder. Yani, dinleyicilere haber verildiğinde, durum tamamen güncellenmiştir. Birçok mağazada böyle bir garanti yoktur. Bu, waitForFlux'un koltuk değerine ihtiyaç duymasının nedenlerinden biridir . Tek bir mağazada, bu ilk etapta gördüğünüz bir sorun değil.

  • Her şeyden önce, Redux'da birden fazla mağaza gereksizdir (zaten profil oluşturmanız gereken performans avantajı durumları hariç). Belgeleri önemli bir nokta haline getiriyoruz, bu nedenle Redux'u Flux gibi kullanmak ve faydalarını kaybetmek yerine redüktör kompozisyonunu ve diğer Redux modellerini öğrenmeye teşvik ediliyoruz.


11
Redüktör bileşiminin tam avantajını / gerekliliğini anlamadığımı itiraf edeceğim. Cevabınız için biraz daha okuma ve bir örnek yaptım (yine TodoMVC). Böyle küçük bir örnekle, indirgeyici bileşimin sağladığı gerçek gelişmeyi anlamak zordu. Bununla birlikte, biraz düşünce ile, büyük ölçekte kazanç (şimdi) açıktır. Tekrar teşekkürler, harika cevap!
Sebastien Daniel

4
@Sebastien "Alışveriş sepeti" örneği bence bunun için daha iyi.
Dan Abramov

3
Redux'u geleneksel (SPA olmayan) bir uygulamaya yavaş yavaş uyguluyorum. Tüm uygulama aynı mağaza kullanmak için değiştirilinceye kadar ben bir tepki / redux uygulama dönüştürmek her "bütün" için multilpe depoları kullanıyorum.
Paul Knopf

5
@DanAbramov Sizin kendi Redux mağazasını çalıştıran ve kendi ayrı Redux mağazasını çalıştıran bağımsız bir "uygulama" npm üzerinden içe aktardığınız ana "uygulamanızın" olduğu bir durumda ne alacağınızı merak edin. Örneğin, şirketinizdeki diğer ekiplerden biri, mağazanızı bu verilerle kirletmeden çekmek istediğiniz bir kullanıcı arayüzüne sahip bir tür mesajlaşma hizmetine sahipse.
natlee75

6
@ natlee75 "Redux'da birden fazla mağaza kullanmanın geçerli bazı nedenleri arasında şunlar olabilir: [...] Bir Redux uygulamasını daha büyük bir uygulamada bileşen olarak yalıtmak, bu durumda her kök bileşen örneği için bir mağaza oluşturmak isteyebilirsiniz." Gönderen redux.js.org/docs/FAQ.html#store-setup-multiple-stores
Kevin

24

Yüzlerce veya binlerce redüktörlü bazı çok büyük kurumsal uygulamalarda, uygulamanın farklı alanlarını tamamen ayrı uygulamalar olarak düşünmek genellikle yararlıdır. Bu durumlarda (gerçekten bir alan adını paylaşan birden fazla uygulama olduğu yerlerde), birden fazla mağaza kullanıyorum.

Örneğin, aşağıdaki ortak işlevsellik alanlarına ayrı uygulamalar olarak davranma eğilimindeyim:

  • yönetim
  • Analytics / veri vis gösterge tabloları
  • Faturalandırma yönetimi ve satın alma akışları
  • Kurumsal hesap ekibi / izin yönetimi

Bunlardan herhangi biri küçükse, bunları ana uygulamanın bir parçası olarak saklayın. Çok büyürlerse (bazı kurumsal hesap yönetimi ve analiz araçlarının yaptığı gibi) bunları ayırın.

Çok büyük uygulamaları yönetmenin en iyi yolu, onları daha küçük uygulamaların bir bileşimi gibi ele almaktır.

Uygulamanız ~ 50k LOC'den daha azsa, muhtemelen bu tavsiyeyi görmezden gelmeli ve bunun yerine Dan'ın tavsiyelerine uymalısınız.

Uygulamanız 1 Milyondan fazla LOC ise, mono uygulamaları depolansanız bile mini uygulamaları ayırmanız gerekir.


5

Bu mimari karar, projelerinin ihtiyaçlarına göre uygulama geliştiricilerine aittir.

Kendi dünyanda yaşıyorsun. Redux kullanan insanlarla tanışıyorum, çünkü her gün popüler. Herhangi bir karar vermeden ne kadar projenin yeniden başlatılmaya başladığını hayal bile edemezdiniz. Redux yaklaşımlarından nefret ediyorum ama kullanmak zorundaydım, çünkü diğer geliştiriciler başka hiçbir şey bilmiyorlar. Bu sadece facebook tarafından şişirilmiş destansı bir kabarcık.

  • Mağazanın parçaları izole edilmediğinden güvenilir değildir.
  • Verimsizdir, çünkü hash trie'yi klonluyorsunuz ve çapraz ediyorsunuz. Mutasyonlar aritmetik olarak büyüdüğünde - karmaşıklık geometrik olarak büyür. Herhangi bir redüktör, seçici vb. Yeniden düzenleyerek sorunu çözemezsiniz. Üçgeninizi ayırmanız gerekir.
  • Yavaşlandığında kimse onu ayrı mağazalarla ayrı uygulamalara bölmek istemez. Kimse yeniden düzenleme için para harcamak istemiyor. İnsanlar genellikle bazı akıllı bileşenleri döküme dönüştürüyor ve hepsi bu. Redux geliştiricilerini geleceğin ne beklediğini biliyor musunuz? Bu cehennemleri koruyacaklar.
  • Hata ayıklama dostu değil . Mağazanın neredeyse yalıtılmış parçaları arasındaki bağlantılarda hata ayıklamak zordur. Bu bağlantıların miktarını analiz etmek bile çok zordur.

Birkaç redux mağazanız olduğunu hayal edelim. Tek yönlü veri akışını keseceksiniz. Mağazalar arasında ne kadar bağlantınız olduğunu hemen anlayacaksınız. Bu bağlantılardan muzdarip olabilir, dairesel deps ile savaşabilirsiniz, vb.

Tek yönlü akışlı tek değişmez depo, her hastalık için bir iksir değildir. Proje mimarisini korumak istemiyorsanız yine de acı çekeceksiniz.


Söylediklerini beğendim ve burada bununla ilgili soru sordum. Biraz zaman ayırıp düşüncelerinizi paylaşırken buna bakmak ister misiniz? Reddit'te sorduğum soru, çünkü SO bu tür soruları burada teşvik etmiyor.
Arup Rakshit

3

Aşağıdaki kullanım durumlarında birden çok mağaza yardımcı olabilir 1. Veri yapısı, davranış, uygulama bağlamı bakımından birbirinden bağımsız büyük bileşenleriniz varsa. Bu bileşenleri izole etmek verilerinizi ve uygulama akışınızı yönetmenizi kolaylaştırır. Ayrıca bileşenlerinizin bağımsız olarak geliştirilmesine ve bakımına yardımcı olur. 2. Performans sorunları: tipik bir kullanım durumu değildir, ancak bileşenlerinizin bazıları çok sık güncelleniyorsa ve diğer bileşenler üzerinde herhangi bir etkisi yoksa, muhtemelen farklı mağazalara gidebilirsiniz.

Diğer tüm durumlarda, birden fazla mağazanız olması gerekmeyebilir. Dan'ın dediği gibi, düşünceli redüktör kompozisyonları oluşturmak daha iyi bir çözüm olabilir.


İletiniz "birkaç vaka dışında her zaman redux kullan" == "birkaç vaka dışında proje mimarisine ihtiyacınız yok" şeklinde görünüyor. Gerçekliğe çok yakın, mutluyum.
puchu

2

neden redux kullanarak birden fazla mağaza kullanamıyoruz ????

Redux'da bu gerekli değildir, çünkü veri alanları arasındaki ayrım zaten tek bir redüktörün daha küçük redüktörlere bölünmesiyle elde edilir.


Birden fazla mağaza oluşturabilir miyim veya oluşturmalıyım? Mağazamı doğrudan içe aktarabilir ve bileşenlerde kendim kullanabilir miyim?

Orijinal Flux kalıbı, bir uygulamada, her biri farklı bir alan adı verisi alanına sahip birden çok "depo" bulunmasını tanımlar. Bu, bir mağazanın güncellenmesi için başka bir mağazanın “waitFor” olması gerektiği gibi sorunları ortaya çıkarabilir.

Redux'da bu gerekli değildir, çünkü veri alanları arasındaki ayrım zaten tek bir redüktörün daha küçük redüktörlere bölünmesiyle elde edilir.

Diğer birkaç soruda olduğu gibi, bir sayfada birden fazla farklı Redux mağazası oluşturmak mümkündür, ancak amaçlanan desende sadece tek bir mağaza olması gerekir. Tek bir mağazaya sahip olmak, Redux DevTools'un kullanılmasını sağlar, kalıcı ve rehidrasyon verisini kolaylaştırır ve abonelik mantığını basitleştirir.

Redux'da birden fazla mağaza kullanmanın geçerli bazı nedenleri şunlar olabilir:

Uygulamanın profillenmesiyle onaylandığında, devletin bir kısmının çok sık güncellenmesinden kaynaklanan bir performans sorununu çözme. Bir Redux uygulamasını daha büyük bir uygulamada bileşen olarak yalıtmak, bu durumda her kök bileşen örneği için bir mağaza oluşturmak isteyebilirsiniz. Ancak, yeni mağazalar oluşturmak, özellikle de Flux geçmişinden geliyorsanız, ilk içgüdünüz olmamalıdır. Önce redüktör kompozisyonunu deneyin ve sadece probleminizi çözmezse birden fazla mağaza kullanın.

Benzer şekilde, mağaza örneğinize doğrudan içe aktararak başvurabilirsiniz, ancak bu Redux'da önerilen bir model değildir. Bir mağaza örneği oluşturur ve bunu bir modülden dışa aktarırsanız, tekil olur. Bu, gerekirse bir Redux uygulamasını daha büyük bir uygulamanın bileşeni olarak izole etmenin veya sunucu oluşturmayı etkinleştirmenin daha zor olacağı anlamına gelir, çünkü sunucuda her istek için ayrı mağaza örnekleri oluşturmak istersiniz.

redux tarafından resmi doktor


1

Redux'da bir mağazaya sahip olmak birçok durumda gerçekten ihtiyacımız olan şey, hem Redux hem de Flux'u kullandım ve Redux'un işi daha iyi yaptığına inanıyorum!

Mağazanın bir JavaScript Nesnesinde olduğunu unutmayın, bu yüzden sadece bir mağazanız olsa da, bir mağazanın Redux dev araçlarını kullanarak geçiş yapmayı çok daha kolay hale getirmesi ve karıştırılmaması için kolayca genişletilebilir ve tekrar kullanılabilir büyük uygulamalar ...

Ayrıca bir mağaza konsepti bizim için veritabanını taklit ediyor, onu değiştirebileceğiniz ve tarayıcı belleğinde erişebileceğiniz bir hakikat kaynağı ...

Tüm uygulama iyi yönetiliyorsa, tüm uygulama durumunu yönetmek için bir mağaza yeterli olabilir ...


3
Bu yüzden herkes tek mağazanın bir işi daha iyi yapacağına inanmalı ve kimse nedenini açıklayamaz. Bana bir şey hatırlatıyor ...
puchu
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.