आम तौर पर मैं डेमेटर के कानून का पालन करता हूं क्योंकि यह कम दायरे में परिवर्तनों को रखने में मदद करता है, ताकि एक नई आवश्यकता या बग फिक्स आपके सिस्टम पर फैल न सके। ऐसे अन्य डिज़ाइन दिशानिर्देश हैं जो इस दिशा में सहायता करते हैं, उदा। this article में सूचीबद्ध हैं। ऐसा कहकर, मैं डेमेटर (साथ ही डिजाइन पैटर्न और अन्य समान सामान) के रूप में उपयोगी डिजाइन दिशानिर्देशों के रूप में विचार करता हूं जिनके व्यापार-बंद होते हैं और यदि आप इसका न्याय करते हैं तो आप उन्हें तोड़ सकते हैं। उदाहरण के लिए मैं आम तौर पर test private methods नहीं करता, मुख्य रूप से क्योंकि यह fragile tests बनाता है। हालांकि, कुछ विशेष मामलों में मैंने एक ऑब्जेक्ट निजी विधि का परीक्षण किया क्योंकि मैंने इसे अपने ऐप में बहुत महत्वपूर्ण माना था, यह जानकर कि ऑब्जेक्ट के कार्यान्वयन में बदलाव होने पर यह विशेष परीक्षण परिवर्तनों के अधीन होगा। बेशक उन मामलों में आपको अतिरिक्त सावधान रहना होगा और अन्य डेवलपर्स के लिए और अधिक दस्तावेज छोड़ना होगा कि आप यह क्यों कर रहे हैं। लेकिन, अंत में, आपको अपने अच्छे फैसले का उपयोग करना होगा :)।
अब, मूल प्रश्न पर वापस जाएं। जहां तक मैं आपकी समस्या को समझता हूं, वहां एक ऑब्जेक्ट के लिए (वेब?) जीयूआई लिख रहा है जो ऑब्जेक्ट्स के ग्राफ की जड़ है जिसे संदेश श्रृंखलाओं के माध्यम से एक्सेस किया जा सकता है। उस मामले के लिए मैं आपके मॉडल के प्रत्येक ऑब्जेक्ट के लिए व्यू घटक निर्दिष्ट करके, जीयूआई को उसी तरीके से मॉड्यूलर करता हूं जैसा आपने अपना मॉडल बनाया है। नतीजतन आपके पास OrderView
, AddressView
आदि जैसे वर्ग होंगे, जो जानते हैं कि उनके संबंधित मॉडल के लिए HTML कैसे बनाएं। फिर आप उन अंतिम विचारों को लिखने के लिए उन विचारों को लिख सकते हैं, या तो उन्हें जिम्मेदारी सौंपकर (उदा। OrderView
AddressView
बनाता है) या Mediator जो उन्हें लिखने और उन्हें अपने मॉडल से जोड़ने का ख्याल रखता है।पहले दृष्टिकोण का एक उदाहरण के रूप में आप कुछ इस तरह हो सकता है (मैं उदाहरण के लिए PHP का उपयोग करेंगे, मैं कौन-सी भाषा का उपयोग कर रहे पता नहीं):
class ShoppingBasket
{
protected $orders;
protected $id;
public function getOrders(){...}
public function getId(){...}
}
class Order
{
protected $user;
public function getUser(){...}
}
class User
{
protected $address;
public function getAddress(){...}
}
और फिर विचार:
class ShoppingBasketView
{
protected $basket;
protected $orderViews;
public function __construct($basket)
{
$this->basket = $basket;
$this->orederViews = array();
foreach ($basket->getOrders() as $order)
{
$this->orederViews[] = new OrderView($order);
}
}
public function render()
{
$contents = $this->renderBasketDetails();
$contents .= $this->renderOrders();
return $contents;
}
protected function renderBasketDetails()
{
//Return the HTML representing the basket details
return '<H1>Shopping basket (id=' . $this->basket->getId() .')</H1>';
}
protected function renderOrders()
{
$contents = '<div id="orders">';
foreach ($this->orderViews as $orderView)
{
$contents .= orderViews->render();
}
$contents .= '</div>';
return $contents;
}
}
class OrderView
{
//The same basic pattern; store your domain model object
//and create the related sub-views
public function render()
{
$contents = $this->renderOrderDetails();
$contents .= $this->renderSubViews();
return $contents;
}
protected function renderOrderDetails()
{
//Return the HTML representing the order details
}
protected function renderOrders()
{
//Return the HTML representing the subviews by
//forwarding the render() message
}
}
और अपने view.php में आप की तरह कुछ करना होगा:
$basket = //Get the basket based on the session credentials
$view = new ShoppingBasketView($basket);
echo $view->render();
यह दृष्टिकोण एक घटक मॉडल है, जहां विचारों composable घटक के रूप में इलाज कर रहे हैं पर आधारित है। इस स्कीमा में आप ऑब्जेक्ट की सीमाओं का सम्मान करते हैं और प्रत्येक दृश्य की एक ज़िम्मेदारी होती है।
संपादित करें (जोड़ा ओपी टिप्पणी के आधार पर)
मैं तुम्हें टोकरी आईडी, आदेश की तारीख और उपयोगकर्ता नाम में प्रस्तुत करने की जरूरत है subviews में और है कि विचारों के आयोजन का कोई रास्ता नहीं है कि वहाँ मान लेंगे एक लाइन जैसा कि मैंने टिप्पणी में कहा था, उस मामले के लिए मैं यह सुनिश्चित कर दूंगा कि "खराब" पहुंच एक एकल, अच्छी तरह से प्रलेखित स्थान पर की जाती है, जिससे दृश्य इस बात से अनजान हो जाता है।
class MixedView
{
protected $basketId;
protected $orderDate;
protected $userName;
public function __construct($basketId, $orderDate, $userName)
{
//Set internal state
}
public function render()
{
return '<H2>' . $this->userName . "'s basket (" . $this->basketId . ")<H2> " .
'<p>Last order placed on: ' . $this->orderDate. '</p>';
}
}
class ViewBuilder
{
protected $basket;
public function __construct($basket)
{
$this->basket = $basket;
}
public function getView()
{
$basketId = $this->basket->getID();
$orderDate = $this->basket->getLastOrder()->getDate();
$userName = $this->basket->getUser()->getName();
return new MixedView($basketId, $orderDate, $userName);
}
}
अगर बाद में आप अपने डोमेन के मॉडल को पुनर्व्यवस्थित करने और अपने ShoppingBasket
वर्ग अब getUser()
संदेश लागू नहीं कर सकते तो आप अपने आवेदन में एक बिंदु को बदलने कि परिवर्तन सब आपके सिस्टम में फैले होने से बचने करना होगा।
HTH
आपका प्रश्न क्या है? – hakre
मुझे पता है कि यहां कोई विशिष्ट प्रश्न नहीं है ... मैंने बक्षीस रखा क्योंकि वहां * हो सकता है और विषय वस्तु पर चर्चा करने लायक है। शायद ओपी सवाल को थोड़ा सा स्पष्ट कर सकता है? – rdlowrey
@ आपकी समस्या यह है कि आप क्लास ऑर्डर में क्लास उपयोगकर्ता, क्लास इन्फो, और उत्पाद कक्षाओं की एक सरणी इंजेक्शन पसंद नहीं करते हैं? वे अपेक्षाकृत स्वतंत्र हैं हालांकि –