ऑब्जेक्ट द्वारा सरणी के रूप में स्टेट करें


94

राज्य के आकार को डिजाइन करने के अध्याय में , डॉक्स आपके राज्य को आईडी द्वारा बंद किए गए ऑब्जेक्ट में रखने का सुझाव देते हैं:

प्रत्येक इकाई को एक कुंजी के रूप में एक आईडी के साथ संग्रहीत ऑब्जेक्ट में रखें, और अन्य संस्थाओं या सूचियों से इसे संदर्भित करने के लिए आईडी का उपयोग करें।

वे राज्य करते हैं

डेटाबेस के रूप में ऐप की स्थिति के बारे में सोचें।

मैं फ़िल्टरों की सूची के लिए राज्य के आकार पर काम कर रहा हूं, जिनमें से कुछ खुले होंगे (वे पॉपअप में प्रदर्शित होते हैं), या चयनित विकल्प हैं। जब मैंने "डेटाबेस के रूप में एप्लिकेशन की स्थिति के बारे में सोचा" पढ़ा, तो मैंने उन्हें JSON प्रतिक्रिया के रूप में सोचने के बारे में सोचा क्योंकि यह एक एपीआई (स्वयं एक डेटाबेस द्वारा समर्थित) से वापस आ जाएगा।

इसलिए मैं इसके बारे में सोच रहा था

[{
    id: '1',
    name: 'View',
    open: false,
    options: ['10', '11', '12', '13'],
    selectedOption: ['10'],
    parent: null,
  },
  {
    id: '10',
    name: 'Time & Fees',
    open: false,
    options: ['20', '21', '22', '23', '24'],
    selectedOption: null,
    parent: '1',
  }]

हालाँकि, डॉक्स एक प्रारूप को अधिक पसंद करते हैं

{
   1: { 
    name: 'View',
    open: false,
    options: ['10', '11', '12', '13'],
    selectedOption: ['10'],
    parent: null,
  },
  10: {
    name: 'Time & Fees',
    open: false,
    options: ['20', '21', '22', '23', '24'],
    selectedOption: null,
    parent: '1',
  }
}

सिद्धांत रूप में, यह तब तक मायने नहीं रखता है जब तक कि डेटा क्रमबद्ध हो (शीर्षक "राज्य" के तहत)

इसलिए मैं ऐरे-ऑफ-ऑब्जेक्ट दृष्टिकोण के साथ खुशी से चला गया, जब तक कि मैं अपना रिड्यूसर नहीं लिख रहा था।

ऑब्जेक्ट-की-बाय-आईडी दृष्टिकोण (और फैल सिंटैक्स का उदार उपयोग) के साथ, रिड्यूसर का OPEN_FILTERहिस्सा बन जाता है

switch (action.type) {
  case OPEN_FILTER: {
    return { ...state, { ...state[action.id], open: true } }
  }

जबकि एरेक्ट-ऑफ-ऑब्जेक्ट्स दृष्टिकोण के साथ, यह अधिक क्रिया है (और हेल्पर फ़ंक्शन रिलेन्ट)

switch (action.type) {
   case OPEN_FILTER: {
      // relies on getFilterById helper function
      const filter = getFilterById(state, action.id);
      const index = state.indexOf(filter);
      return state
        .slice(0, index)
        .concat([{ ...filter, open: true }])
        .concat(state.slice(index + 1));
    }
    ...

इसलिए मेरे प्रश्न तीन गुना हैं:

1) क्या रीड्यूसर की सादगी वस्तु-कुंजी-द्वारा-आईडी दृष्टिकोण के साथ जाने की प्रेरणा है? क्या उस राज्य आकार के अन्य फायदे हैं?

तथा

2) ऐसा लगता है जैसे ऑब्जेक्ट-की-बाय-आईडी दृष्टिकोण एक एपीआई के लिए मानक JSON / से निपटने के लिए कठिन बनाता है। (यही कारण है कि मैं पहली जगह में वस्तुओं की सरणी के साथ गया था।) इसलिए यदि आप उस दृष्टिकोण के साथ जाते हैं, तो क्या आप इसे JSON प्रारूप और राज्य आकार प्रारूप के बीच आगे और पीछे बदलने के लिए फ़ंक्शन का उपयोग करते हैं? वह गुदगुदी लगती है। (हालांकि अगर आप उस दृष्टिकोण की वकालत करते हैं, तो यह आपके तर्क का हिस्सा है कि ऊपर दिए गए एरे के ऑब्जेक्ट्स की तुलना में कम क्लंकी है?)

तथा

3) मुझे पता है कि दान अब्रामोव ने सैद्धांतिक रूप से राज्य-डेटा-संरचना अज्ञेयवादी के रूप में डिज़ाइन किया है (जैसा कि "द्वारा सुझाया गया है) , शीर्ष-स्तरीय राज्य एक ऑब्जेक्ट या मानचित्र की तरह कुछ अन्य कुंजी-मूल्य संग्रह है, लेकिन तकनीकी रूप से यह कोई भी हो सकता है प्रकार , " जोर मेरा)। लेकिन ऊपर दिया गया, क्या यह सिर्फ "अनुशंसित" है, इसे किसी वस्तु को आईडी के पास रखने के लिए, या क्या अन्य अप्रत्याशित दर्द बिंदु हैं जो मैं वस्तुओं की एक सरणी का उपयोग करके चलाने जा रहा हूं जो इसे ऐसा बनाता है कि मुझे बस गर्भपात करना चाहिए योजना और आईडी द्वारा बंद एक वस्तु के साथ छड़ी करने की कोशिश?


2
यह एक दिलचस्प सवाल है, और एक मेरे पास भी था, बस कुछ अंतर्दृष्टि प्रदान करने के लिए, हालांकि मैं सरणियों के बजाय redux में सामान्यीकरण करता हूं (विशुद्ध रूप से क्योंकि देखो आसान है), मुझे लगता है कि यदि आप सामान्यीकृत दृष्टिकोण को छांट लेते हैं तो एक मुद्दा क्योंकि आप सरणी के रूप में एक ही संरचना प्राप्त नहीं करते हैं, इसलिए आप अपने आप को छाँटने के लिए मजबूर हैं।
रॉबर्ट सॉन्डर्स

मुझे 'ऑब्जेक्ट-की-बाय-आईडी' दृष्टिकोण में एक समस्या दिखाई देती है, हालांकि यह अक्सर नहीं होता है लेकिन हमें किसी भी यूआई एप्लिकेशन को लिखते समय इस मामले पर विचार करना होगा। तो क्या होगा यदि मैं एक ड्रैग ड्रॉप तत्व का उपयोग करके ऑर्डर की गई सूची के रूप में सूचीबद्ध इकाई के क्रम को बदलना चाहता हूं? आमतौर पर 'ऑब्जेक्ट-की-बाय-आईडी' दृष्टिकोण यहाँ विफल रहता है और मैं निश्चित रूप से ऐसे उदार मुद्दों से बचने के लिए ऑब्जेक्ट एप्रोच के साथ जाऊँगा। इसे साझा करने के बारे में और भी कुछ सोचा जा सकता है
कुणाल नवते

आप वस्तुओं से बनी वस्तु को कैसे छाँट सकते हैं? यह असंभव लगता है।
डेविड विल्हुबेर

@DavidVielhuber का मतलब है कि आप किसी चीज़ का इस्तेमाल कर रहे हैं sort_by? const sorted = _.sortBy(collection, 'attribute');
निकोक्सेडोटेमे

हाँ। वर्तमान में हम उन वस्तुओं को एक संगणित संपत्ति के अंदर सरणियों में परिवर्तित करते हैं
डेविड विल्हुबर

जवाबों:


46

Q1: reducer की सादगी सही प्रविष्टि खोजने के लिए सरणी के माध्यम से खोज नहीं करने का एक परिणाम है। सरणी के माध्यम से खोज नहीं करने का फायदा है। चयनकर्ता और अन्य डेटा एक्सेसर्स अक्सर इन वस्तुओं को एक्सेस कर सकते हैं id। प्रत्येक पहुंच के लिए सरणी के माध्यम से खोज करना एक प्रदर्शन मुद्दा बन जाता है। जब आपकी सरणियाँ बड़ी हो जाती हैं, तो प्रदर्शन समस्या बहुत खराब हो जाती है। साथ ही, जब आपका ऐप अधिक जटिल हो जाता है, तो अधिक स्थानों पर डेटा दिखाना और फ़िल्टर करना, समस्या और भी बिगड़ जाती है। संयोजन हानिकारक हो सकता है। आइटमों idको एक्सेस O(n)करने से O(1), एक्सेस टाइम से बदल जाता है , जो कि बड़े n(यहां एरे आइटम) के लिए बहुत बड़ा अंतर है।

Q2: आप normalizrएपीआई से स्टोर करने के लिए रूपांतरण में मदद कर सकते हैं । नॉर्मिज़र V3.1.0 के रूप में आप दूसरे रास्ते पर जाने के लिए अपभ्रंश का उपयोग कर सकते हैं। उस ने कहा, ऐप्स अक्सर डेटा के उत्पादकों की तुलना में अधिक उपभोक्ता होते हैं और जैसे कि स्टोर करने के लिए रूपांतरण आमतौर पर अधिक बार किया जाता है।

Q3: किसी सरणी का उपयोग करके आप जिन समस्याओं को चलाएंगे, वे स्टोरेज कन्वेंशन और / या असंगतताओं के साथ बहुत अधिक समस्याएं नहीं हैं, लेकिन अधिक प्रदर्शन समस्याएं हैं।


सामान्य बात फिर से वह चीज है जो बैकेंड में दोष को बदलने के बाद निश्चित रूप से दर्द पैदा करेगी। इसलिए इसे हर बार अप-टू-डेट रखना होता है
कुणाल नवहटे

12

डेटाबेस के रूप में ऐप की स्थिति के बारे में सोचें।

यही प्रमुख विचार है।

1) अद्वितीय आईडी वाले ऑब्जेक्ट होने से आप ऑब्जेक्ट को संदर्भित करते समय हमेशा उस आईडी का उपयोग कर सकते हैं, इसलिए आपको कार्रवाई और रीड्यूसर के बीच न्यूनतम मात्रा में डेटा पास करना होगा। यह array.find (...) का उपयोग करने से अधिक कुशल है। यदि आप ऐरे एप्रोच का उपयोग करते हैं तो आपको पूरी वस्तु को पास करना होगा और वह बहुत जल्द गड़बड़ हो सकती है, आप अलग-अलग रिड्यूसर, एक्शन या यहां तक ​​कि कंटेनर में ऑब्जेक्ट को फिर से बना सकते हैं (आप ऐसा नहीं चाहते)। दृश्य हमेशा पूर्ण ऑब्जेक्ट प्राप्त करने में सक्षम होंगे, भले ही उनके संबद्ध रिड्यूसर में केवल आईडी शामिल हो, क्योंकि राज्य को मैप करते समय आपको कहीं संग्रह मिलेगा (यह देखने के लिए पूरे राज्य को गुणों के लिए मैप करने के लिए मिलता है)। क्योंकि मैंने जो कुछ भी कहा है, वह क्रियाएं न्यूनतम मात्रा में मापदंडों को समाप्त करती हैं, और सूचना की न्यूनतम मात्रा को कम करती है, इसे आजमाएं,

2) एपीआई का कनेक्शन आपके भंडारण और पुनर्परिभाषित की वास्तुकला को प्रभावित नहीं करना चाहिए, यही कारण है कि आपके पास कार्य हैं, चिंताओं को अलग करने के लिए। बस एक पुन: प्रयोज्य मॉड्यूल में एपीआई के अंदर और बाहर अपने रूपांतरण तर्क रखें, एपीआई का उपयोग करने वाले कार्यों में उस मॉड्यूल को आयात करें, और यह होना चाहिए।

3) मैंने आईडी के साथ संरचनाओं के लिए सरणियों का उपयोग किया, और ये मेरे द्वारा सामना किए गए अप्रत्याशित परिणाम हैं:

  • कोड में लगातार वस्तुओं को फिर से बनाना
  • अनावश्यक सूचनाओं को रिड्यूसर्स और कार्यों में पास करना
  • इसके परिणामस्वरूप, खराब, साफ नहीं और स्केलेबल कोड नहीं।

मैंने अपनी डेटा संरचना को बदलना और बहुत सारे कोड को फिर से लिखना शुरू कर दिया। आपको चेतावनी दी गई है, कृपया अपने आप को मुसीबत में न डालें।

इसके अलावा:

4) आईडी के साथ अधिकांश संग्रह पूरे ऑब्जेक्ट के संदर्भ के रूप में आईडी का उपयोग करने के लिए हैं, आपको इसका लाभ उठाना चाहिए। एपीआई कॉल को आईडी और फिर बाकी पैरामीटर मिलेंगे, जिससे आपके कार्य और रीड्यूसर हो जाएंगे।


Im एक ऐसे मुद्दे पर आ रहा है, जहाँ हमारे पास एक ऐसा डेटा (1000 से 10,000 तक) है, जो आईडी द्वारा रेडीमेड स्टोर में किसी वस्तु में संग्रहीत है। विचारों में, वे सभी समय श्रृंखला डेटा प्रदर्शित करने के लिए सॉर्ट किए गए सरणियों का उपयोग करते हैं। इसका मतलब यह है कि हर बार एक रेंडर किया जाता है, इसे पूरी वस्तु को लेना पड़ता है, एक सरणी में परिवर्तित होता है, और इसे सॉर्ट करता है। मुझे ऐप के प्रदर्शन में सुधार करने का काम सौंपा गया था। क्या यह उपयोग का मामला है जहां यह आपके डेटा को सॉर्ट किए गए सरणी में संग्रहीत करने और किसी वस्तु के बजाय डिलीट और अपडेट करने के लिए बाइनरी सर्च का उपयोग करने के लिए अधिक समझ में आता है?
विलियम चाउ

मैंने अपडेट पर गणना समय को कम करने के लिए इस डेटा से प्राप्त कुछ अन्य हैश मानचित्र बनाने के लिए समाप्त कर दिया। यह सभी अलग-अलग विचारों को अद्यतन करने के लिए अपने स्वयं के अद्यतन तर्क की आवश्यकता होती है। इससे पहले, सभी घटक स्टोर से ऑब्जेक्ट ले लेंगे, और इसके दृश्य बनाने के लिए आवश्यक डेटा संरचनाओं का पुनर्निर्माण करेंगे। जिस तरह से मैं यूआई में न्यूनतम जानकरी सुनिश्चित करने के बारे में सोच सकता हूं वह वेब कार्यकर्ता का उपयोग ऑब्जेक्ट से एरे में रूपांतरण करने के लिए कर रहा है। इसके लिए व्यापार बंद सरल पुनर्प्राप्ति और अद्यतन तर्क है क्योंकि सभी घटक केवल पढ़ने और लिखने के लिए एक प्रकार के डेटा पर निर्भर करते हैं।
विलियम चाउ

8

1) क्या रीड्यूसर की सादगी वस्तु-कुंजी-द्वारा-आईडी दृष्टिकोण के साथ जाने की प्रेरणा है? क्या उस राज्य आकार के अन्य फायदे हैं?

मुख्य कारण जिसे आप आईडी के साथ संग्रहीत वस्तुओं में चाबियों के रूप में रखना चाहते हैं (जिन्हें सामान्यीकृत भी कहा जाता है ), यह है कि यह वास्तव में गहराई से नेस्टेड वस्तुओं (जो आप आमतौर पर एक अधिक जटिल ऐप में REST API से प्राप्त करते हैं) के साथ काम करने के लिए बोझिल है - आपके घटकों और आपके reducers दोनों के लिए।

अपने वर्तमान उदाहरण के साथ सामान्यीकृत राज्य के लाभों का वर्णन करना थोड़ा कठिन है (जैसा कि आपके पास एक गहरी नेस्टेड संरचना नहीं है )। लेकिन मान लें कि विकल्पों (आपके उदाहरण में) का भी एक शीर्षक था, और आपके सिस्टम में उपयोगकर्ताओं द्वारा बनाए गए थे। इसके बजाय प्रतिक्रिया कुछ इस तरह दिखाई देगी:

[{
  id: 1,
  name: 'View',
  open: false,
  options: [
    {
      id: 10, 
      title: 'Option 10',
      created_by: { 
        id: 1, 
        username: 'thierry' 
      }
    },
    {
      id: 11, 
      title: 'Option 11',
      created_by: { 
        id: 2, 
        username: 'dennis'
      }
    },
    ...
  ],
  selectedOption: ['10'],
  parent: null,
},
...
]

अब मान लें कि आप एक ऐसा घटक बनाना चाहते हैं जो उन सभी उपयोगकर्ताओं की सूची दिखाता है जिन्होंने विकल्प बनाए हैं। ऐसा करने के लिए, आपको पहले सभी वस्तुओं का अनुरोध करना होगा, फिर उनके प्रत्येक विकल्प पर पुनरावृति करना होगा, और अंत में create_by.username प्राप्त करना होगा।

एक बेहतर समाधान में प्रतिक्रिया को सामान्य बनाना होगा:

results: [1],
entities: {
  filterItems: {
    1: {
      id: 1,
      name: 'View',
      open: false,
      options: [10, 11],
      selectedOption: [10],
      parent: null
    }
  },
  options: {
    10: {
      id: 10,
      title: 'Option 10',
      created_by: 1
    },
    11: {
      id: 11,
      title: 'Option 11',
      created_by: 2
    }
  },
  optionCreators: {
    1: {
      id: 1,
      username: 'thierry',
    },
    2: {
      id: 2,
      username: 'dennis'
    }
  }
}

इस संरचना के साथ, यह बहुत आसान है, और अधिक कुशल है, उन सभी उपयोगकर्ताओं को सूचीबद्ध करने के लिए जिन्होंने विकल्प बनाए हैं (हमने उन्हें संस्थाओं में अलग कर दिया है। चयनकर्ता, इसलिए हमें बस उस सूची के माध्यम से लूप करना होगा)।

यह दिखाने के लिए भी काफी सरल है जैसे कि उन लोगों के उपयोगकर्ता नाम जिन्होंने आईडी 1 के साथ फ़िल्टर आइटम के लिए विकल्प बनाए हैं

entities
  .filterItems[1].options
  .map(id => entities.options[id])
  .map(option => entities.optionCreators[option.created_by].username)

2) ऐसा लगता है जैसे ऑब्जेक्ट-की-बाय-आईडी दृष्टिकोण एक एपीआई के लिए मानक JSON / से निपटने के लिए कठिन बनाता है। (यही कारण है कि मैं पहली जगह में वस्तुओं की सरणी के साथ गया था।) इसलिए यदि आप उस दृष्टिकोण के साथ जाते हैं, तो क्या आप इसे JSON प्रारूप और राज्य आकार प्रारूप के बीच आगे और पीछे बदलने के लिए फ़ंक्शन का उपयोग करते हैं? वह गुदगुदी लगती है। (हालांकि अगर आप उस दृष्टिकोण की वकालत करते हैं, तो यह आपके तर्क का हिस्सा है कि ऊपर दिए गए एरे के ऑब्जेक्ट्स की तुलना में कम क्लंकी है?)

एक JSON-प्रतिक्रिया जैसे का उपयोग कर सामान्यीकृत किया जा सकता है normalizr

3) मुझे पता है कि दान अब्रामोव ने सैद्धांतिक रूप से राज्य-डेटा-संरचना अज्ञेय के रूप में डिज़ाइन किया है (जैसा कि "द्वारा सुझाया गया है, सम्मेलन द्वारा, शीर्ष-स्तरीय राज्य एक ऑब्जेक्ट या मानचित्र की तरह कुछ अन्य कुंजी-मूल्य संग्रह है, लेकिन तकनीकी रूप से यह कोई भी हो सकता है) प्रकार, "जोर मेरा)। लेकिन ऊपर दिया गया, क्या यह सिर्फ "अनुशंसित" है, इसे किसी वस्तु को आईडी के पास रखने के लिए, या क्या अन्य अप्रत्याशित दर्द बिंदु हैं जो मैं वस्तुओं की एक सरणी का उपयोग करके चलाने जा रहा हूं जो इसे ऐसा बनाता है कि मुझे बस गर्भपात करना चाहिए योजना और आईडी द्वारा बंद एक वस्तु के साथ छड़ी करने की कोशिश?

यह शायद अधिक जटिल ऐप्स के लिए एक सिफारिश है जिसमें बहुत से नेस्टेड एपीआई प्रतिक्रियाएं हैं। आपके विशेष उदाहरण में, यह वास्तव में बहुत मायने नहीं रखता है।


1
mapयहां अपरिभाषित रिटर्न देता है , अगर संसाधनों को अलग-अलग लाया जाता है, तो filterएस रास्ता बहुत जटिल हो जाता है। क्या कोई उपाय है?
रामचंद्रन

1
@tobiasandersen क्या आपको लगता है कि सर्वर के लिए प्रतिक्रिया / रिड्यूस के लिए सामान्यीकृत डेटा आदर्श को वापस करना ठीक है, क्लाइंट से बचने के लिए नॉर्मिज़्र जैसे लिबास के माध्यम से रूपांतरण करने के लिए? दूसरे शब्दों में, सर्वर को डेटा को सामान्य बनाना है और क्लाइंट को नहीं।
मैथ्यू
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.