पदावनत कोड - थर्ड-पार्टी कोड

छवि

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

यह छिपा हुआ अर्थ यह है कि आपको हमारे आवेदन और हमारे द्वारा उपयोग किए जाने वाले तीसरे पक्ष के कोड के बीच इंटरफेस, क्लाइंट, ब्रिज, एडेप्टर बनाने चाहिए। हम अपने परीक्षणों में इन इंटरफेस की नकली वस्तुओं का निर्माण करेंगे या नहीं यह भी इतना महत्वपूर्ण नहीं है। महत्वपूर्ण बात यह है कि हम ऐसे इंटरफेस बनाते हैं और उनका उपयोग करते हैं जो हमारे कोड को थर्ड-पार्टी कोड से बेहतर बनाते हैं। PHP दुनिया में इसका एक उत्कृष्ट उदाहरण हमारे आवेदन में एक HTTP क्लाइंट का निर्माण और उपयोग करना है जो कि सीधे Guzzle का उपयोग करने के बजाय, Guzzle HTTP क्लाइंट का उपयोग करता है।

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

मुझे नहीं लगता कि इसे हासिल करना मुश्किल है। तृतीय-पक्ष कोड आमतौर पर हमारे आवेदन के एक अलग फ़ोल्डर में निहित होता है, अक्सर यह vendor/ या library/ । यह एक अलग नामस्थान में भी रहता है और हमारे आवेदन में उपयोग किए गए से अलग नामकरण सम्मेलन है। थर्ड-पार्टी कोड की पहचान करना काफी आसान है और, थोड़े अनुशासन के साथ, हम अपने एप्लिकेशन कोड को थर्ड-पार्टी पार्ट्स पर कम निर्भर बना सकते हैं।

यदि हम विरासत कोड के लिए समान नियम लागू करते हैं तो क्या होगा?


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

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

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

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

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

src / Legacy / User.php
 <?php namespace Legacy; class User { public $email; public $password; public $role; public $name; public function promote($newRole) { $this->role = $newRole; } public function save() { db_layer::save($this); } } 

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

आइए अपने आप को सीमित करें और इन सार्वजनिक संपत्तियों तक पहुंच को प्रतिबंधित करें और यह अनुमान लगाने का प्रयास करें कि उपयोगकर्ता अधिकारों को बढ़ाते समय एक पुरानी प्रणाली कैसे काम करती है:

src / LegacyBridge / Promoter.php
 <?php namespace LegacyBridge; interface Promoter { public function promoteTo(Role $role); } 

src / LegacyBridge / LegacyUserPromoter.php
 <?php namespace LegacyBridge; class LegacyUserPromoter implements Promoter { private $legacyUser; public function __construct(Legacy\User $user) { $this->legacyUser = $user; } public function promoteTo(Role $newRole) { $newRole = (string) $newRole; //  ,  $role     ?  ! $legacyRoles = [ Role::MODERATOR => 1, Role::MEMBER => 2, ]; $newLegacyRole = $legacyRoles[$newRole]; $this->legacyUser->promote($newLegacyRole); $this->legacyUser->save(); } } 

अब, जब हम नए कोड में User अधिकार बढ़ाना चाहते हैं, तो हम LegacyBridge\Promoter इंटरफ़ेस का उपयोग करते हैं, जो एक पुरानी प्रणाली में उपयोगकर्ता को बढ़ाने की सभी सूक्ष्मताओं से संबंधित है।

हेरिटेज भाषा बदलें


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

src / LegacyBridge / Promoter.php
 <?php namespace LegacyBridge; interface Promoter { public function promoteTo(Role $role); } 

src / LegacyBridge / LegacyUserPromoter.php
 <?php namespace LegacyBridge; class LegacyUserPromoter implements Promoter { private $legacyUser; public function __construct(Legacy\User $user) { $this->legacyUser = $user; } public function promoteTo(Role $newRole) { if ($newRole->isMember()) { throw new \Exception("Can't promote to a member."); } $legacyMemberRole = 2; $this->legacyUser->promote($legacyMemberRole); $this->legacyUser->save(); } } 

src / LegacyBridge / Demoter.php
 <?php namespace LegacyBridge; interface Demoter { public function demoteTo(Role $role); } 

src / LegacyBridge / LegacyUserDemoter.php
 <?php namespace LegacyBridge; class LegacyUserDemoter implements Demoter { private $legacyUser; public function __construct(Legacy\User $user) { $this->legacyUser = $user; } public function demoteTo(Role $newRole) { if ($newRole->isModerator()) { throw new \Exception("Can't demote to a moderator."); } $legacyModeratorRole = 1; $this->legacyUser->promote($legacyModeratorRole); $this->legacyUser->save(); } } 


इतना बड़ा बदलाव नहीं, लेकिन कोड का उद्देश्य बहुत स्पष्ट हो गया है।

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

Source: https://habr.com/ru/post/hi417683/


All Articles