क्या कक्षाओं पर फ़ील्ड घोषित करना वास्तव में PHP में हानिकारक है?


13

निम्नलिखित कोड पर विचार करें, जिसमें एक जानबूझकर प्रोग्रामिंग त्रुटि के कारण सेटर को जानबूझकर तोड़ दिया गया है जो मैंने पिछले कुछ समय में वास्तविक के लिए बनाया है:

<?php

    class TestClass {

        private $testField;

        function setField($newVal) {
            $testField = $newVal;
            // deliberately broken; should be `$this->testField = $newVal`
        }

        function getField() {
            return $this->testField;
        }

    }

    $testInstance = new TestClass();
    $testInstance->setField("Hello world!");

    // Actually prints nothing; getField() returns null
    echo $testInstance->getField(); 

?>

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

PHP सूचना: अपरिभाषित संपत्ति: TestClass :: $ 13 पर लाइन में /var/www/test.php

घोषणा के साथ, कोई चेतावनी नहीं है।

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

आगे के विचार पर, हालांकि, इसे रोकने के लिए समझ में नहीं आता है। चूँकि मेरे अनुभव में एक असिंचित क्षेत्र को पढ़ने की कोशिश करना एक बहुत ही सामान्य त्रुटि का कारण है, जो किसी निजी या संरक्षित क्षेत्र को अनुचित रूप से पढ़ने या संशोधित करने की कोशिश करने से अधिक है (मैंने पूर्व में कई बार अपने छोटे प्रोग्रामिंग करियर में किया है, लेकिन बाद वाला कभी नहीं। ), यह मुझे लगता है कि सभी क्षेत्र की घोषणाओं पर टिप्पणी करना - न केवल सार्वजनिक लोगों के लिए - सबसे अच्छा अभ्यास होगा।

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


1
यकीनन उपयोगी है ? आपके द्वारा बताए गए लाभ अत्यंत महत्वपूर्ण हैं। मैं शायद कोड पर काम करने से इनकार कर दूंगा जिसमें कोई स्पष्ट संपत्ति की घोषणा नहीं थी।
माइकल

2
वास्तव में, इन त्रुटियों से खुद को बचाने का तरीका सावधानीपूर्वक त्रुटि की जांच और बेहतर है, इकाई परीक्षण के माध्यम से।
माइकल

1
वहाँ php त्रुटि रिपोर्टिंग (एक सूचना स्तर) में बनाया गया है जो आपको बताएगा कि क्या आप पहले घोषित किए बिना एक चर का उपयोग करते हैं।
क्रेयॉन वायलेंट

3
@MarkAmery मुझे लगता है कि सख्त इकाई परीक्षण को अपनाने के लिए सबसे महत्वपूर्ण जगह है एक फ्रेंचली-स्टार्टअप स्टार्टअप - चूंकि आप हमेशा कोड बदलते रहते हैं, आप संभवतः इसे हमेशा तोड़ रहे हैं । यह वास्तव में सख्त परीक्षण और फ्लैट-आउट टीडीडी का सटीक उद्देश्य है। हाँ, मुझे लगता है कि अंडरस्कोर का उपयोग करने से आपको यह याद रखने में मदद मिल सकती है कि आप निजी सामान का उपयोग कर रहे हैं, लेकिन मेरे लिए विशिष्ट कोडिंग मानकों को अपनाने का विचार है जो मुझे गलतियाँ करने से बचाने के लिए नहीं करना चाहिए। TRUE === $variableतुलना करने के बजाय गलती से खुद को रोकने के लिए ऐसा करना।
माइकल

1
@MarkAmery ध्यान दें कि दृश्यता कीवर्ड स्वचालित प्रलेखन टूल द्वारा पार्स किए जाते हैं , इसलिए वे केवल एक टिप्पणी की तुलना में अधिक "प्रलेखन मूल्य" देते हैं जो आप मैन्युअल रूप से डालते हैं।
माइकल

जवाबों:


15

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

  • संकलक घोषित गुणों का अनुकूलन कर सकता है। जब आप गतिशील रूप से एक संपत्ति की घोषणा करते हैं तो यह एक प्रदर्शन हिट होता है क्योंकि कंपाइलर को आपके गतिशील गुणों को संग्रहीत करने के लिए एक गतिशील हैश तालिका बनाना होता है।
  • मैं इस पर 100% नहीं हूं, लेकिन मेरा मानना ​​है कि एपीसी जैसे बायटेकोड ऑप्टिमाइज़र आपके लिए उपयोगी नहीं होंगे क्योंकि उनके पास आपकी कक्षा की पूरी तस्वीर नहीं होगी। (और एपीसी जैसे आशावादी एक चाहिए )
  • अपने कोड को पढ़ने के लिए कठिन 1000x बनाता है। लोग आपसे नफरत करेंगे।
  • यह 1000 गुना अधिक संभावना है कि आप एक गलती करेंगे। (क्या यह getId या getID था? रुको, आपने दोनों का उपयोग किया। विफल।)
  • कोई आईडीई स्वत: पूर्ण या टाइपिंग नहीं।
  • प्रलेखन जनरेटर आपकी संपत्ति नहीं देखेंगे।

आपके द्वारा वर्णित समस्या वास्तव में एक छोटी सी है जब आपकी कक्षा परिभाषा में आपके गुणों की घोषणा नहीं करने की समस्या की तुलना में। यहाँ एक अच्छा समाधान है।

अपने गुणों के लिए डिफॉल्ट घोषित करने की आदत डालें।

private $testField = null;
private $testField = '';
private $testField = 0;
private $testField = []; //array()
private $testField = false;

वस्तुओं को संग्रहीत करने वाले गुणों को छोड़कर, यह अधिकांश आधार प्रकारों को कवर करेगा जिन्हें आप संग्रहीत करेंगे। वे गुण जो वस्तुओं का भंडारण करेंगे, उन्हें आपके निर्माता में सेट किया जा सकता है।

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


आपके 5 डाउनसाइड्स के जवाब में: 1 (प्रदर्शन): क्या आपके पास इसके लिए कोई स्रोत है? 2 (पठनीयता): निश्चित नहीं कि मैं समझता हूं; प्रस्ताव घोषणाओं को टिप्पणी करने के लिए था, न केवल उन्हें हटाने के लिए, इसलिए क्या पठनीयता खो गई है? थोड़ा कम अनुकूल सिंटैक्स हाइलाइटिंग और संभावित कठिनाई पड़ोसी टिप्पणियों से अलग है, मुझे लगता है? 3: यह एक जिसे मैं बिल्कुल नहीं समझता; क्या आप स्पष्ट कर सकते हो? 4 (आईडीई): पर्याप्त रूप से - मुझे आईडीई के साथ PHP कोडिंग का अनुभव नहीं है और ग्रहण के प्रकार के बारे में पता नहीं था। 5 (डॉक्टर जनरेटर): पर्याप्त रूप से उचित - इनमें से किसी का भी उपयोग नहीं किया जाता है।
मार्क एमी

मैंने उन्हें टिप्पणी करने के बारे में आपकी लाइन नहीं देखी। भले ही, उपरोक्त बिंदु अभी भी लागू होते हैं - आप कैसे जानते हैं कि कौन से सक्रिय हैं या कानूनी रूप से टिप्पणी की गई है ??
जारोड नेटल्स

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

2
@MarkAmery आपकी प्रोग्रामिंग गलती, हालांकि, अनिवार्य रूप से एक टाइपो के लिए है। हम सब उनके पास हैं - लेकिन आप यहाँ एक मक्खी को मारने के लिए बम विस्फोट करने की कोशिश कर रहे हैं।
जारोड नेटल्स

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

2

मैंने कुछ कोड पर काम किया है जो गतिशील रूप से निर्मित ऑब्जेक्ट गुण का उपयोग करता है। मैंने सोचा था कि गतिशील रूप से बनाई गई वस्तु गुणों का उपयोग करना बहुत अच्छा था (सच, मेरी राय में)। हालाँकि, मेरे कार्यक्रम को चलने में 7 सेकंड का समय लगा। मैंने डायनामिक ऑब्जेक्ट प्रॉपर्टीज़ को हटा दिया और उन्हें प्रत्येक क्लास के हिस्से के रूप में घोषित ऑब्जेक्ट प्रॉपर्टीज़ (इस मामले में सार्वजनिक) के रूप में बदल दिया। CPU समय 7 सेकंड से 0.177 सेकंड से अधिक चला गया। यह काफी पर्याप्त है।

यह संभव है कि मैं जिस तरह से गतिशील वस्तु गुणों का उपयोग कर रहा था उसमें मैं कुछ गलत कर रहा था। यह भी संभव है कि मेरा कॉन्फ़िगरेशन किसी तरह से टूट गया हो। बेशक, मुझे कहना चाहिए कि मेरी मशीन पर एक बहुत ही सादे वेनिला PHP कॉन्फ़िगरेशन है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.