2008-09-04 14 views
8

तो, मैं Google परीक्षण ब्लॉग पढ़ रहा था, और यह कहता है कि वैश्विक स्थिति खराब है और परीक्षण लिखना मुश्किल बनाता है। मुझे विश्वास है - मेरा कोड अभी परीक्षण करना मुश्किल है। तो मैं वैश्विक स्थिति से कैसे बचूं?मैं वैश्विक स्थिति से कैसे बच सकता हूं?

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

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

क्या राज्य की जानकारी का प्रबंधन करने का कोई अच्छा तरीका है? (या क्या मैं वैश्विक स्थिति को गलत तरीके से समझ रहा हूं?)

उत्तर

10

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

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

दो मुख्य लाभ: एक, परीक्षण बहुत आसान है, और दो, आपका आवेदन बहुत कम है। आप इसके कार्यान्वयन के बजाय कक्षा के इंटरफ़ेस के खिलाफ प्रोग्राम करने में सक्षम होने पर भरोसा करते हैं।

1

ग्रेट पहला सवाल।

संक्षिप्त उत्तर: सुनिश्चित करें कि आपका आवेदन अपने आउटपुट में सभी इनपुट (अंतर्निहित सहित) से एक फ़ंक्शन है।

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

2

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

आप इस तरह के महल विंडसर के रूप में लेकिन साधारण मामलों के लिए आप इस तरह के रूप में सड़क दृष्टिकोण के एक मध्यम लेने के लिए सक्षम हो सकता है एक निर्भरता इंजेक्शन ढांचे के उपयोग पर विचार कर सकता है:

public interface ISettingsProvider 
{ 
    string ConnectionString { get; } 
} 

public class TestSettings : ISettingsProvider 
{   
    public string ConnectionString { get { return "testdatabase"; } }; 
} 

public class DataStuff 
{ 
    private ISettingsProvider settings; 

    public DataStuff(ISettingsProvider settings) 
    { 
     this.settings = settings; 
    } 

    public void DoSomething() 
    { 
     // use settings.ConnectionString 
    } 
} 

वास्तविकता आप सबसे अधिक होगा में संभवतः आपके कार्यान्वयन में कॉन्फ़िगरेशन फ़ाइलों से पढ़ा जाता है।यदि आप इसके लिए तैयार हैं, तो स्वीकार्य कॉन्फ़िगरेशन के साथ एक पूर्ण उड़ा हुआ डी फ्रेमवर्क जाने का तरीका है, लेकिन मुझे लगता है कि यह Globals.ConnectionString का उपयोग करने से कम से कम बेहतर है।

0

एक MVC सेटिंग में निर्भरता इंजेक्शन का एक उदाहरण यहाँ जाता है:

index.php

$container = new Container(); 
include_file('container.php'); 

container.php

container.add("database.driver", "mysql"); 
container.add("database.name","app"); 

...

$container.add(new Database($container->get('database.driver', "database.name")), 'database'); 
$container.add(new Dao($container->get('database')), 'dao'); 
$container.add(new Service($container->get('dao'))); 
$container.add(new Controller($container->get('service')), 'controller'); 

$container.add(new FrontController(),'frontController'); 

index.php यहां जारी है:

$frontController = $container->get('frontController'); 
$controllerClass = $frontController->getController($_SERVER['request_uri']); 
$controllerAction = $frontController->getAction($_SERVER['request_uri']); 
$controller = $container->get('controller'); 
$controller->$action(); 

और वहाँ तुम्हारे पास है, नियंत्रक एक सेवा स्तर आइटम जो पर निर्भर करता है पर निर्भर करता है एक डीएओ (डेटा का उपयोग ऑब्जेक्ट) वस्तु है जो एक डेटाबेस वस्तु पर निर्भर करता है के साथ डेटाबेस ड्राइवर पर निर्भर करता है, नाम आदि

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^