आप अत्यधिक अनुकूलित सॉफ़्टवेयर को कैसे व्यवस्थित करते हैं?


28

मैं एक बड़े सॉफ्टवेयर प्रोजेक्ट पर काम कर रहा हूं, जो दुनिया भर के विभिन्न ग्राहकों के लिए अत्यधिक अनुकूलित है। इसका मतलब है कि हमारे पास शायद 80% कोड है जो विभिन्न ग्राहकों के बीच आम है, लेकिन बहुत सारे कोड भी हैं जिन्हें एक ग्राहक से दूसरे में बदलना होगा। अतीत में हमने अलग-अलग रिपॉजिटरी (एसवीएन) में अपना विकास किया और जब एक नई परियोजना शुरू हुई (हमारे पास कुछ, लेकिन बड़े ग्राहक हैं) ने हमारी पिछली जरूरतों के लिए सबसे अच्छा कोड आधार जो भी था, उसके आधार पर एक और रिपॉजिटरी बनाई। यह अतीत में काम किया है, लेकिन हम कई समस्याओं में भाग गए:

  • कीड़े जो एक रिपॉजिटरी में तय किए गए हैं, अन्य रिपॉजिटरी में पैच नहीं किए गए हैं। यह संगठन की समस्या हो सकती है, लेकिन मुझे 5 विभिन्न रिपॉजिटरी में बग को ठीक करना और पैच करना मुश्किल लगता है, यह ध्यान में रखते हुए कि इस रिपॉजिटरी को बनाए रखने वाली टीम दुनिया के किसी अन्य हिस्से में हो सकती है और हमारे पास उनके परीक्षण का वातावरण नहीं है , न तो उनके कार्यक्रम को जानते हैं या उनकी क्या आवश्यकताएं हैं (एक देश में "बग" दूसरे में "सुविधा" हो सकती है)।
  • एक परियोजना के लिए किए गए सुविधाएँ और सुधार, जो किसी अन्य परियोजना के लिए भी उपयोगी हो सकते हैं, खो गए हैं या यदि वे किसी अन्य परियोजना में उपयोग किए जाते हैं, तो अक्सर बड़े सिरदर्द होते हैं, जो उन्हें एक कोड आधार से दूसरे में विलय कर देते हैं (क्योंकि दोनों शाखाएं एक वर्ष के लिए स्वतंत्र रूप से विकसित हो सकती हैं। )।
  • एक विकास शाखा में किए गए रिफलेक्टरिंग और कोड सुधार या तो खो जाते हैं या अच्छे से अधिक नुकसान का कारण बनते हैं यदि आपको इन सभी परिवर्तनों को शाखाओं के बीच विलय करना है।

अब हम चर्चा कर रहे हैं कि इन समस्याओं को कैसे हल किया जाए और अब तक निम्नलिखित विचारों के साथ इसे कैसे हल किया जाए:

  1. अलग-अलग शाखाओं में विकास करते रहें, लेकिन केंद्रीय भंडार होने से बेहतर आयोजन होता है जहां सामान्य बग फिक्स को मर्ज कर दिया जाता है और सभी परियोजनाओं को इस केंद्रीय भंडार से एक नियमित (जैसे दैनिक) आधार पर विलय कर दिया जाता है। इसके लिए विशाल अनुशासन और शाखाओं के बीच विलय के लिए बहुत प्रयास की आवश्यकता होती है। इसलिए मुझे यकीन नहीं है कि यह काम करेगा और हम इस अनुशासन को बनाए रख सकते हैं, खासकर जब समय दबाव डालता है।

  2. अलग-अलग विकास शाखाओं का त्याग करें और एक केंद्रीय कोड रिपॉजिटरी है जहां हमारे सभी कोड रहते हैं और प्लगेबल मॉड्यूल और कॉन्फ़िगरेशन विकल्प होने से हमारा अनुकूलन करते हैं। हम अपने कोड में निर्भरता को हल करने के लिए पहले से ही डिपेंडेंसी इंजेक्शन कंटेनरों का उपयोग कर रहे हैं और हम अपने यूआई से व्यापार तर्क को अलग करने के लिए अपने अधिकांश कोड में MVVM पैटर्न का पालन कर रहे हैं।

दूसरा दृष्टिकोण अधिक सुरुचिपूर्ण प्रतीत होता है, लेकिन हमें इस दृष्टिकोण में कई अनसुलझी समस्याएं हैं। उदाहरण के लिए: अपने मॉडल / डेटाबेस में परिवर्तन / परिवर्धन कैसे करें। हम एंटिटी फ्रेमवर्क के साथ .NET का उपयोग कर रहे हैं। मैं यह नहीं देखता कि हम उन संपत्तियों को कैसे संभाल सकते हैं जो एक ग्राहक के लिए आवश्यक हैं, लेकिन हमारे डेटा मॉडल को अव्यवस्थित किए बिना किसी अन्य ग्राहक के लिए बेकार हैं। हम उपग्रह सारणी का उपयोग करके डेटाबेस में इसे हल करने के बारे में सोच रहे हैं (एक अलग तालिका होने पर जहां एक विशेष इकाई के लिए हमारे अतिरिक्त कॉलम मूल इकाई के लिए 1: 1 मैपिंग के साथ रहते हैं), लेकिन यह केवल डेटाबेस है। आप इसे कोड में कैसे संभालेंगे? हमारा डेटा मॉडल एक केंद्रीय पुस्तकालय में रहता है जिसे हम इस दृष्टिकोण का उपयोग करके प्रत्येक ग्राहक के लिए विस्तारित नहीं कर पाएंगे।

मुझे यकीन है कि हम इस समस्या से जूझने वाली एकमात्र टीम नहीं हैं और मैं इस विषय पर इतनी कम सामग्री पाकर हैरान हूं।

तो मेरे सवाल निम्नलिखित हैं:

  1. आपके पास अत्यधिक अनुकूलित सॉफ़्टवेयर के साथ क्या अनुभव है, आपने क्या दृष्टिकोण चुना और यह आपके लिए कैसे काम किया?
  2. आप किस दृष्टिकोण की सलाह देते हैं और क्यों? क्या एक बेहतर दृष्टिकोण है?
  3. क्या इस विषय पर कोई अच्छी किताबें या लेख हैं जिन्हें आप सुझा सकते हैं?
  4. क्या आपके पास हमारे तकनीकी वातावरण (.NET, Entity Framework, WPF, DI) के लिए विशिष्ट सिफारिशें हैं?

संपादित करें:

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

मुझे अभी भी यकीन नहीं है कि हम किस रास्ते पर जाएंगे और मैं (अकेले) निर्णय नहीं कर रहा हूं, लेकिन मैं इसे अपनी टीम में पास करूंगा और मुझे यकीन है कि यह मददगार होगा।

फिलहाल टेनर विभिन्न ग्राहक विशिष्ट मॉड्यूल का उपयोग करके एकल रिपॉजिटरी लगता है। मुझे यकीन नहीं है कि हमारी वास्तुकला इस पर निर्भर है या हमें इसे फिट बनाने के लिए कितना निवेश करना है, इसलिए कुछ चीजें कुछ समय के लिए अलग रिपॉजिटरी में रह सकती हैं, लेकिन मुझे लगता है कि यह एकमात्र दीर्घकालिक समाधान है जो काम करेगा।

तो, सभी प्रतिक्रियाओं के लिए फिर से धन्यवाद!


डेटाबेस तालिकाओं को कोड के रूप में मानने पर विचार करें।

हम पहले से ही इस अर्थ में कर रहे हैं कि हमारे पास हमारे डेटाबेस स्क्रिप्ट्स हैं जो हमारे तोड़फोड़ भंडार में हैं, लेकिन यह वास्तव में ऊपर वर्णित समस्याओं को हल नहीं करता है। हम अपने डेटाबेस मॉडल में की-वैल्यू स्टाइल टेबल नहीं रखना चाहते हैं क्योंकि वे बहुत सारी समस्याएं लेकर आते हैं। तो कैसे आप व्यक्तिगत ग्राहकों के लिए अपने मॉडल में परिवर्धन की अनुमति देते हैं जबकि अभी भी उन सभी के लिए एक साझा कोड भंडार बनाए रखते हैं?
aKzenT

जवाबों:


10

ऐसा लगता है कि मौलिक समस्या सिर्फ कोड रिपॉजिटरी रखरखाव नहीं है, बल्कि उपयुक्त वास्तुकला की कमी है

  1. प्रणाली का मूल / सार क्या है, जो हमेशा सभी प्रणालियों द्वारा साझा किया जाएगा?
  2. प्रत्येक ग्राहक को क्या वृद्धि / विचलन की आवश्यकता होती है?

एक ढांचा या मानक पुस्तकालय पूर्व को शामिल करता है, जबकि बाद को ऐड-ऑन (प्लगइन्स, उपवर्ग, DI, जो भी कोड संरचना के लिए समझ में आता है) के रूप में लागू किया जाएगा।

एक स्रोत नियंत्रण प्रणाली जो शाखाओं का प्रबंधन करती है और वितरित विकास संभवत: मदद भी करती है; मैं मर्क्यूरियल का प्रशंसक हूं, अन्य लोग Git को पसंद करते हैं। रूपरेखा मुख्य शाखा होगी, प्रत्येक अनुकूलित प्रणाली उप-शाखा होगी, उदाहरण के लिए।

सिस्टम को लागू करने के लिए उपयोग की जाने वाली विशिष्ट प्रौद्योगिकियां (.NET, WPF, जो भी हो) काफी हद तक महत्वहीन हैं।

यह अधिकार प्राप्त करना आसान नहीं है , लेकिन दीर्घकालिक व्यवहार्यता के लिए यह महत्वपूर्ण है । और निश्चित रूप से आप जितनी देर प्रतीक्षा करेंगे, आपको उतने अधिक तकनीकी ऋण से जूझना पड़ेगा।

आप सॉफ्टवेयर आर्किटेक्चर: संगठनात्मक सिद्धांत और पैटर्न उपयोगी पुस्तक पा सकते हैं ।

सौभाग्य!


3
हाँ। आर्किटेक्चर अक्सर एक तकनीकी चीज की तुलना में मनोवैज्ञानिक चीज का अधिक होता है। यदि आप उत्पाद पर पूरी तरह से ध्यान केंद्रित करते हैं, तो आप एक काम-विराम के साथ समाप्त हो जाएंगे जहां घटक केवल उस उत्पाद के लिए उपयोगी हैं। यदि, दूसरी ओर, आप पुस्तकालयों के एक सेट के निर्माण पर ध्यान केंद्रित करते हैं जो आमतौर पर अधिक उपयोगी होने जा रहे हैं, तो आप क्षमताओं का एक सेट बनाते हैं जिन्हें व्यापक परिस्थितियों में तैनात किया जा सकता है। ज़ाहिर है, आपकी विशेष स्थिति के लिए इन दो चरम सीमाओं के बीच सही संतुलन का पता लगाना है।
विलियम पेने

मुझे लगता है कि हमारी कई शाखाओं (> 90%) के बीच एक बड़ा साझा हिस्सा है, लेकिन अंतिम 10% हमेशा अलग-अलग स्थानों में होते हैं, इसलिए बहुत कम घटक हैं जहां मैं कुछ उपयोगिता पुस्तकालयों को छोड़कर कुछ ग्राहक विशिष्ट परिवर्तनों की कल्पना नहीं कर सकता हूं किसी भी व्यावसायिक तर्क को शामिल न करें।
aKzenT

@aKzenT: हम्म ... कल्पना मत करो, इसके बजाय मापें। कोड का सर्वेक्षण करें और उन सभी स्थानों को देखें जहां अनुकूलन हुआ है, संशोधित घटकों की एक सूची बनाएं, ध्यान दें कि प्रत्येक घटक को कितनी बार संशोधित किया गया है, और संशोधनों के प्रकार और पैटर्न के बारे में सोचें जो वास्तव में किए गए हैं। क्या वे कॉस्मेटिक या एल्गोरिथम हैं? क्या वे आधार कार्यक्षमता जोड़ रहे हैं या बदल रहे हैं? प्रत्येक प्रकार के परिवर्तन का कारण क्या है? फिर, यह कड़ी मेहनत है , और आप जो खोजते हैं उसके निहितार्थ को पसंद नहीं कर सकते हैं।
स्टीवन ए। लोव

1
मैंने इसे उत्तर के रूप में स्वीकार कर लिया है, क्योंकि हम अपनी वास्तुकला के बारे में अधिक सोचने से पहले यह निर्णय नहीं ले सकते हैं, उन हिस्सों की पहचान करें जो सामान्य हैं या जो सामान्य हैं और फिर देखें कि क्या हम एक एकल भंडार के साथ रह सकते हैं या यदि forking आवश्यक है (के लिए) कम से कम)। यह उत्तर इस सर्वोत्तम IMO को दर्शाता है। अन्य सभी पदों के लिए धन्यवाद, हालांकि!
aKzenT

11

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

उस ढांचे के आधार पर, अलग-अलग रिपॉजिटरी में ग्राहक-विशिष्ट कोड बनाए रखा गया था। जब उपयोगी या आवश्यक होता है, तो बग फिक्स और सुधार परियोजनाओं के बीच कॉपी-पेस्ट किए जाते हैं (प्रश्न में वर्णित सभी विवरणों के साथ)। वैश्विक रूप से उपयोगी सुधार आम ढांचे में जाते हैं, हालांकि।

सभी ग्राहकों के लिए एक सामान्य कोडबेस में सब कुछ होने के कुछ फायदे हैं, लेकिन दूसरी ओर, कोड को पढ़ना तब मुश्किल हो जाता है जब ifप्रत्येक ग्राहक के लिए प्रोग्राम को अलग-अलग व्यवहार करने के लिए अनगिनत s होते हैं।

संपादित करें: इसे और अधिक समझने के लिए एक किस्सा:

उस कंपनी का डोमेन गोदाम प्रबंधन है, और गोदाम प्रबंधन प्रणाली का एक कार्य आने वाले सामानों के लिए एक मुफ्त भंडारण स्थान खोजना है। आसान लगता है, लेकिन व्यवहार में, बहुत सारी बाधाओं और रणनीतियों का अवलोकन करना पड़ता है।

एक समय में, प्रबंधन ने एक प्रोग्रामर को स्टोरेज स्थानों को खोजने के लिए एक लचीला, पैरामीटर मॉड्यूल बनाने के लिए कहा, जिसने कई अलग-अलग रणनीतियों को लागू किया और बाद की सभी परियोजनाओं में इसका उपयोग किया जाना चाहिए। नेक प्रयास से एक जटिल मॉड्यूल तैयार हुआ, जिसे समझना और बनाए रखना बहुत मुश्किल था। अगले प्रोजेक्ट में, प्रोजेक्ट लीड यह पता नहीं लगा सका कि उस गोदाम में यह कैसे काम करता है, और उक्त मॉड्यूल का डेवलपर चला गया था, इसलिए उसने अंततः इसे अनदेखा कर दिया और उस कार्य के लिए एक कस्टम एल्गोरिदम लिखा।

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

मुझे पता है कि LOC एक अच्छा माप नहीं है, लेकिन फिर भी: "लचीले" मॉड्यूल का आकार ~ 3000 LOC (PL / SQL) था, जबकि समान कार्य के लिए एक कस्टम मॉड्यूल ~ 100..250 LOC लेता है। इसलिए, लचीले होने की कोशिश करने से कोड बेस के आकार में वृद्धि हुई, पुन: प्रयोज्यता प्राप्त किए बिना हमने उम्मीद की थी।


आपकी प्रतिक्रिया के लिए धन्यवाद। यह वर्णित पहले समाधान का विस्तार है और हमने इस बारे में भी सोचा। हालाँकि, चूंकि हमारे अधिकांश पुस्तकालय कुछ मुख्य संस्थाओं का उपयोग करते हैं और ये कोर इकाइयाँ आमतौर पर एक ग्राहक या किसी अन्य के लिए विस्तारित होती हैं, मुझे लगता है कि हम केवल इस कोर भंडार में बहुत कम पुस्तकालय रख सकते हैं। उदाहरण के लिए, हमारे पास एक "ग्राहक" इकाई है और ORM एक लाइब्रेरी में मैप की गई है, जिसका उपयोग हमारे लगभग सभी अन्य पुस्तकालयों और कार्यक्रमों द्वारा किया जाता है। लेकिन हर ग्राहक के पास कुछ अतिरिक्त क्षेत्र होते हैं जिन्हें उन्हें "ग्राहक" में जोड़ने की आवश्यकता होती है, इसलिए हमें इस लाइब्रेरी को कांटा करना होगा और इसलिए इसके आधार पर सभी लाइब्रेरी।
अंजानेट

3
हमारे विचार "अनगिनत" से बचने के लिए निर्भरता इंजेक्शन का व्यापक उपयोग करना और विभिन्न ग्राहकों के लिए पूर्ण मॉड्यूल का आदान-प्रदान करना है। यह सुनिश्चित नहीं है कि यह कैसे काम करेगा। यह दृष्टिकोण आपके लिए कैसे काम करता है?
aKzenT

+1, यह मूल रूप से उन परियोजनाओं के मेरे अनुभव से मेल खाता है जिन्होंने इसे अच्छी तरह से संभाला है। यदि आप 'ifs के लिए अलग-अलग ग्राहकों के दृष्टिकोण' का उपयोग करने जा रहे हैं, तो 2 अंक: 1. यदि (customer1) नहीं करते हैं ..., इसके बजाय if (configurationOption1) ... और प्रति-ग्राहक कॉन्फ़िगरेशन विकल्प हैं। 2. इसे न करने की कोशिश करें! शायद उस समय का 1% जो कॉन्फ़िगरेशन-विशिष्ट मॉड्यूल की तुलना में बेहतर (अधिक समझने योग्य / आसानी से बनाए रखने योग्य) विकल्प होगा।
विघ्नहर्ता

@ बक्वेटा: केवल स्पष्ट करने के लिए: आप कॉन्फ़िगरेशन विकल्पों (ifs) के बजाय प्रति-ग्राहक मॉड्यूल का उपयोग करने की सलाह देते हैं, है ना? मुझे ग्राहकों के बजाय सुविधाओं के बीच अंतर करने के लिए आपका विचार पसंद है। तो दोनों के संयोजन में विभिन्न "फीचर मॉड्यूल" होंगे जो विन्यास विकल्पों द्वारा नियंत्रित होते हैं। एक ग्राहक को तब केवल स्वतंत्र फीचर मॉड्यूल के एक सेट के रूप में दर्शाया जाता है। मुझे यह बहुत पसंद है, लेकिन मुझे यकीन नहीं है कि यह कैसे आर्किटेक्ट होगा। DI मॉड्यूल लोडिंग और एक्सचेंजिंग की समस्या को हल करता है, लेकिन आप ग्राहकों के बीच विभिन्न डेटा मॉडल का प्रबंधन कैसे करते हैं?
13:10 बजे केकेजेएनटी

हाँ, प्रति-सुविधा मॉड्यूल और फिर प्रति-ग्राहक कॉन्फ़िगरेशन / सुविधाओं का चयन। DI आदर्श होगा। दुर्भाग्य से मुझे कभी भी एक डेटा लाइब्रेरी के साथ पर्याप्त प्रति ग्राहक अनुकूलन की आपकी आवश्यकताओं को संयोजित नहीं करना पड़ा है, इसलिए मुझे यकीन नहीं है कि मैं वहाँ बहुत मदद कर सकता हूं ...
vaughandroid

5

उन परियोजनाओं में से एक जो मैंने बड़ी संख्या में उत्पाद रिलीज़ पर समर्थित कई प्लेटफार्मों (5 से अधिक) पर काम किया है। आपके द्वारा बताई जा रही बहुत सी चुनौतियाँ ऐसी थीं, जिनका सामना हमें कुछ अलग तरीके से करना पड़ा। हमारे पास एक मालिकाना डीबी था, इसलिए हमें उस क्षेत्र में एक ही प्रकार की समस्याएं नहीं थीं।

हमारी संरचना आपके समान थी, लेकिन हमारे पास हमारे कोड के लिए एक एकल भंडार था। प्लेटफ़ॉर्म विशिष्ट कोड कोड ट्री के भीतर अपने स्वयं के प्रोजेक्ट फ़ोल्डर में चला गया। आम कोड उस परत के आधार पर पेड़ के भीतर रहता था।

प्लेटफॉर्म के निर्माण के आधार पर, हमारे पास सशर्त संकलन था। यह बनाए रखना एक तरह का दर्द था, लेकिन इसे केवल तब करना पड़ता था जब प्लेटफॉर्म की विशिष्ट परत पर नए मॉड्यूल जोड़े जाते थे।

एक ही रिपॉजिटरी में सभी कोड होने से हमारे लिए एक ही समय में कई प्लेटफॉर्म और रिलीज़ पर बग फिक्स करना आसान हो गया। सभी प्लेटफार्मों के लिए एक बैकस्टॉप के रूप में सेवा करने के लिए हमारे पास एक स्वचालित निर्माण का माहौल था, अगर नए कोड ने एक असंबंधित प्लेटफॉर्म को तोड़ दिया।

हमने इसे हतोत्साहित करने की कोशिश की, लेकिन ऐसे मामले होंगे जहां एक मंच को एक विशिष्ट प्लेटफ़ॉर्म बग के आधार पर ठीक करने की आवश्यकता होती थी जो अन्यथा सामान्य कोड में थी। अगर हम मॉड्यूल को बिना दिखावट के संकलित किए बिना संकलित कर सकते हैं, तो हम पहले ऐसा करेंगे। यदि नहीं, तो हम मॉड्यूल को सामान्य क्षेत्र से बाहर ले जाएंगे और इसे विशिष्ट प्लेटफ़ॉर्म में धकेलेंगे।

डेटाबेस के लिए, हमारे पास कुछ टेबल थे जिनमें प्लेटफ़ॉर्म विशिष्ट कॉलम / संशोधन थे। हम यह सुनिश्चित करेंगे कि तालिका के प्रत्येक प्लेटफ़ॉर्म संस्करण को कार्यक्षमता के आधारभूत स्तर से मिला, इसलिए सामान्य कोड प्लेटफ़ॉर्म निर्भरताओं के बारे में चिंता किए बिना इसे संदर्भित कर सकता है। प्लेटफ़ॉर्म विशिष्ट क्वेरी / जोड़तोड़ को प्लेटफ़ॉर्म प्रोजेक्ट परतों में धकेल दिया गया।

तो, आपके सवालों का जवाब देने के लिए:

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

अपने अनुभव साझा करने के लिए धन्यवाद। बस बेहतर समझने के लिए: आपके मामले में एक मंच कैसे परिभाषित किया जाता है। विंडोज, लिनक्स, X86 / x64? या कुछ और विभिन्न ग्राहकों / परिवेशों से संबंधित है? आप 4 में अच्छी बात कर रहे हैं) मुझे लगता है कि यह हमारी समस्याओं में से एक है। हमारे पास बहुत सारे स्मार्ट और योग्य लोगों की एक टीम है, लेकिन हर किसी के पास चीजों को करने के तरीके पर थोड़ा अलग विचार है। स्पष्ट रूप से वास्तुकला के प्रभारी किसी के बिना एक आम रणनीति पर सहमत होना मुश्किल है और आप कुछ भी बदले बिना खुद को चर्चाओं में खोने का जोखिम उठाते हैं।
aKzenT

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

4

मैंने पेंशन प्रशासन आवेदन पर कई वर्षों तक काम किया जिसमें समान मुद्दे थे। पेंशन योजना कंपनियों के बीच बहुत भिन्न हैं, और गणना तर्क और रिपोर्टों को लागू करने के लिए अत्यधिक विशिष्ट ज्ञान की आवश्यकता है और बहुत अलग डेटा डिज़ाइन भी। मैं केवल वास्तुकला के हिस्से का एक संक्षिप्त विवरण दे सकता हूं, लेकिन शायद यह पर्याप्त विचार देगा।

हमारे पास 2 अलग-अलग टीमें थीं: एक कोर डेवलपमेंट टीम, जो कोर सिस्टम कोड के लिए ज़िम्मेदार थी (जो आपके ऊपर 80% साझा कोड होगा), और एक कार्यान्वयन टीम, जिसमें पेंशन सिस्टम में डोमेन विशेषज्ञता थी, और क्लाइंट सीखने के लिए जिम्मेदार था आवश्यकताओं और कोडिंग स्क्रिप्ट और ग्राहक के लिए रिपोर्ट।

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

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

यह डेटा मॉडल उस इकाई / डोमेन ऑब्जेक्ट को कम चालाक है, लेकिन यह अत्यधिक लचीला, सार्वभौमिक है, और इसे कोर कोड के एक सेट द्वारा संसाधित किया जा सकता है। शायद आपके मामले में, आप अपनी आधार इकाई वस्तुओं को केवल सामान्य क्षेत्रों के साथ परिभाषित कर सकते हैं, और कस्टम फ़ील्ड के लिए एक अतिरिक्त शब्दकोश हो सकते हैं (अपनी इकाई ऑब्जेक्ट में डेटा डिस्क्रिप्टर के कुछ प्रकार जोड़ें ताकि यह कस्टम फ़ील्ड के लिए मेटा डेटा हो। )

हमारे पास कोर सिस्टम कोड और कार्यान्वयन कोड के लिए अलग-अलग स्रोत रिपॉजिटरी थे।

हमारे कोर सिस्टम में वास्तव में बहुत कम व्यावसायिक तर्क थे, कुछ बहुत मानक सामान्य गणना मॉड्यूलों के अलावा। मुख्य प्रणाली इस प्रकार काम करती है: स्क्रीन जनरेटर, स्क्रिप्ट रनर, रिपोर्ट जनरेटर, डेटा एक्सेस और ट्रांसपोर्ट लेयर।

मुख्य तर्क और अनुकूलित तर्क को खंडित करना एक कठिन चुनौती है। हालांकि, हमने हमेशा महसूस किया कि प्रत्येक क्लाइंट के लिए चल रहे सिस्टम की कई प्रतियों के बजाय, एक से अधिक क्लाइंट को चलाने वाला एक कोर सिस्टम होना बेहतर था।


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

2

मैंने एक छोटे सिस्टम (20 kloc) पर काम किया है, और पाया कि DI और कॉन्फ़िगरेशन दोनों क्लाइंट के बीच अंतर को प्रबंधित करने के लिए शानदार तरीके हैं, लेकिन सिस्टम को फोर्क करने से बचने के लिए पर्याप्त नहीं है। डेटाबेस एक एप्लिकेशन विशिष्ट भाग के बीच विभाजित होता है, जिसमें एक निश्चित स्कीमा होता है, और क्लाइंट आश्रित हिस्सा होता है, जिसे कस्टम XML कॉन्फ़िगरेशन दस्तावेज़ के माध्यम से परिभाषित किया जाता है।

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


क्या आपने मुख्य पुस्तकालयों में अंतर किया है जो ग्राहकों के बीच समान हैं या क्या आप पूरा पेड़ कांटे हैं? क्या आप मेनलाइन से अलग-अलग फोर्क्स में रेगुलेटरी मर्ज करते हैं? और यदि हाँ, दैनिक मर्ज की दिनचर्या में कितना समय था और आप कैसे इससे बचते थे कि समय शुरू होने पर यह प्रक्रिया अलग हो जाती है (जैसे कि यह परियोजना में हमेशा एक बिंदु पर होता है)? इतने सारे सवालों के लिए क्षमा करें: p
aKzenT

हमने पूरे पेड़ को कांटा, मुख्य रूप से क्योंकि ग्राहक अनुरोध सिस्टम अखंडता का निर्माण करने से पहले आते हैं। मुख्य प्रणाली से विलय मैन्युअल और अन्य उपकरणों के उपयोग से होता है, और आमतौर पर महत्वपूर्ण बग या बड़े फीचर अपडेट तक सीमित होता है। मर्ज की लागत के कारण, हम बड़े-बड़े अनूठे विखंडू में अपडेट रखने की कोशिश करते हैं, और क्योंकि कई क्लाइंट अपने स्वयं के सिस्टम को होस्ट करते हैं और हम मूल्य प्रदान किए बिना उन पर स्थापना लागत नहीं डालना चाहते हैं।
बजे डैन मोनेगो

मैं उत्सुक हूं: IIRC मर्क्यूरियल एक डीवीसीएस है जो गिट के समान है। क्या आपने तोड़फोड़ या अन्य पारंपरिक वीसीएस की तुलना में शाखाओं के बीच इन मर्जों को करने से कोई लाभ देखा है? मैं बस तोड़फोड़ का उपयोग कर 2 पूरी तरह से अलग विकसित शाखाओं के बीच एक बहुत ही दर्दनाक मर्ज प्रक्रिया को समाप्त कर रहा था और सोच रहा था कि अगर हम प्रिट का उपयोग करते तो यह आसान होता।
aKzenT

मर्क्यूरियल के साथ विलय करना हमारे पूर्व टूल के साथ विलय करने की तुलना में बहुत आसान है, जो कि वॉल्ट था। मुख्य लाभों में से एक यह है कि आवेदन में परिवर्तन इतिहास को सामने और केंद्र में रखने के बारे में बहुत अच्छा है, जो कि जहां किया गया था, उसे ट्रैक करना आसान बनाता है। हमारे लिए सबसे कठिन हिस्सा मौजूदा शाखाओं को खत्म कर रहा था - यदि आप दो शाखाओं को मिला रहे हैं, तो मर्क्यूरियल के लिए आवश्यक है कि वे दोनों एक ही मूल हों, इसलिए यह स्थापित करना एक अंतिम पूरी तरह से मैनुअल मर्ज की आवश्यकता है।
दान मोनेगो

2

मुझे डर है कि मुझे आपके द्वारा वर्णित समस्या का प्रत्यक्ष अनुभव नहीं है, लेकिन मेरे पास कुछ टिप्पणियां हैं।

दूसरा विकल्प, कोड को एक केंद्रीय रिपॉजिटरी (जितना कि प्रैक्टिकेबल) में एक साथ लाना, और कस्टमाइज़ेशन के लिए आर्किटेक्चर करना (फिर से, जितना प्रैक्टिकेबल) लगभग निश्चित रूप से लॉन्ग टर्म में जाने का तरीका है।

समस्या यह है कि आप वहां पहुंचने की योजना कैसे बना रहे हैं, और आपको कितना समय लगेगा।

इस स्थिति में, यह शायद ठीक है (अस्थायी रूप से) एक बार में रिपॉजिटरी में आवेदन की एक से अधिक प्रति है।

यह आपको धीरे-धीरे एक ऐसे आर्किटेक्चर में ले जाने में सक्षम करेगा जो सीधे कस्टमाइज़ेशन का समर्थन करता है, उसे एक झपट्टे में पड़े बिना।


2

दूसरा दृष्टिकोण अधिक सुरुचिपूर्ण प्रतीत होता है, लेकिन हमें इस दृष्टिकोण में कई अनसुलझी समस्याएं हैं।

मुझे यकीन है कि उन समस्याओं को हल किया जा सकता है, एक के बाद एक। यदि आप अटक जाते हैं, तो विशेष समस्या के बारे में एसओ पर या यहां पूछें।

जैसा कि अन्य लोगों ने बताया है, एक केंद्रीय कोडबेस / एक रिपॉजिटरी होना वह विकल्प है जिसे आपको पसंद करना चाहिए। मैं आपके उदाहरण प्रश्न का उत्तर देने का प्रयास करता हूं।

उदाहरण के लिए: अपने मॉडल / डेटाबेस में परिवर्तन / परिवर्धन कैसे करें। हम एंटिटी फ्रेमवर्क के साथ .NET का उपयोग कर रहे हैं। मैं यह नहीं देखता कि हम उन संपत्तियों को कैसे संभाल सकते हैं जो एक ग्राहक के लिए आवश्यक हैं, लेकिन हमारे डेटा मॉडल को अव्यवस्थित किए बिना किसी अन्य ग्राहक के लिए बेकार हैं।

कुछ संभावनाएं हैं, उन सभी को मैंने वास्तविक-विश्व प्रणालियों में देखा है। कौन सा चुनना है यह आपकी स्थिति पर निर्भर करता है:

  • कुछ हद तक अव्यवस्था के साथ रहते हैं
  • एक तालिका "CustomAttributes" (नाम और प्रकार का वर्णन करते हुए) और "CustomAttributeValues" (मानों के लिए, उदाहरण के लिए एक स्ट्रिंग प्रतिनिधित्व के रूप में संग्रहीत किया जाता है, भले ही वे संख्याएँ हों) परिचय। यह प्रत्येक ग्राहक के लिए अलग-अलग मान रखते हुए, इंस्टाल टाइम या रन टाइम में ऐसी विशेषताओं को जोड़ने की अनुमति देगा। प्रत्येक कस्टम विशेषता को अपने डेटा मॉडल में "दृश्यमान" मॉडल करने पर जोर न दें।

  • अब यह स्पष्ट होना चाहिए कि उस कोड का उपयोग कैसे करें: उन तालिकाओं तक पहुँचने के लिए सिर्फ सामान्य कोड है, और व्यक्तिगत कोड (शायद एक अलग प्लग-इन DLL में, जो आप पर निर्भर है) उस विशेषताओं की सही व्याख्या करने के लिए

  • एक अन्य विकल्प यह है कि प्रत्येक इकाई तालिका को एक बड़ा स्ट्रिंग फ़ील्ड दिया जाए जहाँ आप एक व्यक्ति XML-स्ट्रिंग जोड़ सकते हैं।
  • कुछ अवधारणाओं को सामान्य करने की कोशिश करें, ताकि वे विभिन्न ग्राहकों में आसानी से पुन: उपयोग किए जा सकें। मैं मार्टिन फाउलर की पुस्तक " विश्लेषण पैटर्न " की सिफारिश करता हूं । हालाँकि यह पुस्तक सॉफ्टवेयर प्री से कस्टमाइज़ करने के बारे में नहीं है, लेकिन यह आपके लिए मददगार भी हो सकती है।

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


कस्टम गुण संग्रहीत करने के लिए CustomAttributes या XML कॉलम जोड़ने के साथ मुझे जो समस्याएँ दिखाई देती हैं, वह यह है कि वे अपनी क्षमताओं में बहुत सीमित हैं। उदाहरण के लिए, इन विशेषताओं के आधार पर छंटनी, समूह बनाना या फ़िल्टर करना बहुत चुनौतीपूर्ण है। मैंने एक बार एक सिस्टम पर काम किया था जिसमें एक अतिरिक्त विशेषता तालिका का उपयोग किया गया था और इन कस्टम विशेषताओं को बनाए रखने और संभालने के लिए यह तेजी से जटिल हो गया। इस कारण से मैं इन विशेषताओं को कॉलम के रूप में एक अतिरिक्त तालिका में डालने के बजाय सोच रहा था जो मूल में 1: 1 मैप किया गया है। इन्हें परिभाषित, क्वेरी और प्रबंधित करने की समस्या अभी भी एक समान है।
aKzenT

@ काजेनट: कस्टमिज़ेबिलिटी मुफ्त में नहीं आती है, आपको आसानी से उपयोग बनाम कस्टमाइज़ेबिलिटी का व्यापार करना होगा। मेरा सामान्य सुझाव यह है कि आप निर्भरता का परिचय नहीं देते हैं जहाँ सिस्टम का मुख्य भाग किसी भी कस्टम भाग से किसी भी तरह से निर्भर करता है, केवल दूसरे तरीके से। उदाहरण के लिए, जब ग्राहक 1 के लिए इन "अतिरिक्त तालिकाओं" को शुरू करते हैं, तो क्या आप ग्राहक के लिए उस तालिकाओं और संबंधित कोड को तैनात करने से बच सकते हैं? यदि उत्तर हां है, तो समाधान ठीक है।
डॉक्टर ब्राउन

0

मैंने केवल एक ही ऐसा एप्लिकेशन बनाया है। मैं कहता हूँ कि बेची गई ९ ०% इकाइयाँ इस प्रकार हैं, कोई संशोधन नहीं। प्रत्येक ग्राहक की अपनी स्वनिर्धारित त्वचा थी और हमने उस त्वचा के भीतर इस प्रणाली की सेवा की। जब एक मॉड आया था, तो हमने IF ब्रांचिंग का उपयोग करने की कोशिश की थी । जब mod # 2 उसी सेक्शन के लिए आया था तो हम CASE लॉजिक पर स्विच कर गए थे जिसमें भविष्य के विस्तार की अनुमति थी। यह अधिकांश छोटे अनुरोधों को संभालने के लिए लग रहा था।

मामले के तर्क को लागू करके किसी भी अन्य छोटे कस्टम अनुरोधों को संभाला गया।

यदि मॉड दो कट्टरपंथी थे, तो हमने अलग-अलग मॉड्यूल को शामिल करने के लिए एक क्लोन (अलग-अलग शामिल) का निर्माण किया और इसके चारों ओर एक मामले को लपेट दिया।

बग फिक्स और कोर पर संशोधनों ने सभी उपयोगकर्ताओं को प्रभावित किया। हमने उत्पादन में जाने से पहले विकास का पूरा परीक्षण किया। हमने हमेशा ईमेल सूचनाएँ भेजीं जो किसी भी परिवर्तन के साथ थीं और कभी भी, कभी भी, शुक्रवार को उत्पादन में बदलाव नहीं किए गए ... कभी नहीं।

हमारा वातावरण क्लासिक एएसपी और एसक्यूएल सर्वर था। हम एक स्पेगेटी कोड की दुकान नहीं थे ... सब कुछ शामिल था, सबरूटीन्स और फ़ंक्शंस का उपयोग करके मॉड्यूलर था।


-1

जब मुझे B के विकास को शुरू करने के लिए कहा जाता है जो A के साथ 80% कार्यक्षमता साझा कर रहा है, तो मैं या तो:

  1. क्लोन ए और इसे संशोधित करें।
  2. कार्यक्षमता को निकालें जो A और B दोनों C में साझा करते हैं जो वे उपयोग करेंगे।
  3. A को B और खुद की जरूरतों को पूरा करने के लिए एक विन्यास योग्य बनाएं (इसलिए B A में एम्बेडेड है)।

आपने 1 को चुना, और यह आपकी स्थिति को अच्छी तरह से फिट नहीं करता है। आपका मिशन यह अनुमान लगाना है कि 2 और 3 में से कौन सा बेहतर है।


1
आसान लगता है, लेकिन व्यवहार में यह कैसे करना है? आप अपने सॉफ़्टवेयर को "यदि (ग्राहक 1)" के साथ अव्यवस्थित किए बिना इतना विन्यास योग्य बनाते हैं, जो कुछ समय बाद अप्राप्य हो जाता है।
बजे एक

@aKzenT यही कारण है कि मैंने आपको चुनने के लिए 2 और 3 को छोड़ दिया। अगर ग्राहक के प्रोजेक्ट को कस्टमर 2 की ज़रूरतों के लिए विन्यास के माध्यम से समर्थन करने के लिए आवश्यक परिवर्तन करना है, तो कोड को
अचूक

मैं "if (customer1)" के बजाय "if (विकल्प 1)" करना पसंद करता हूं। एन विकल्पों के साथ इस तरह से मैं बहुत सारे संभावित ग्राहकों का प्रबंधन कर सकता हूं। जैसे एन बुलियन विकल्पों के साथ आप 2 ^ N ग्राहकों को प्रबंधित कर सकते हैं, केवल N 'if' होने पर ... "if (customer1)" रणनीति के साथ प्रबंधन करना असंभव है, जिसके लिए 2 ^ N 'की आवश्यकता होगी'।
Fil
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.