क्या डेटाबेस के प्रश्नों को पृष्ठ के बाहर ही समाप्त कर दिया जाना चाहिए?


10

PHP में पेज जनरेशन लिखते समय, मैं अक्सर खुद को डेटाबेस के प्रश्नों से अटे फाइलों का एक सेट लिखता हुआ पाता हूँ। उदाहरण के लिए, मेरे पास एक पृष्ठ पर प्रदर्शित करने के लिए डेटाबेस से सीधे एक पोस्ट के बारे में कुछ डेटा लाने के लिए एक क्वेरी हो सकती है:

$statement = $db->prepare('SELECT * FROM posts WHERE id=:id');
$statement->bindValue(':id', $id, PDO::PARAM_INT);
$statement->execute();
$post = $statement->fetch(PDO::FETCH_ASSOC);
$content = $post['content']
// do something with the content

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

कुछ मामलों में, मैंने अपने पोस्ट से संबंधित db प्रश्नों को संभालने के लिए कार्यों की एक सरल लाइब्रेरी बनाकर इस समस्या को हल किया है, कोड के उस ब्लॉक को एक सरल से छोटा कर दिया है:

$content = post_get_content($id);

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

$recent_posts = post_get_recent(5);
foreach ($recent_posts as $post) { ... }

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

निश्चित रूप से, मैं विशिष्ट इंटरैक्शन के लिए सामान्य उपयोग के मामलों और प्रश्नों के लिए फ़ंक्शंस का उपयोग कर सकता हूं, लेकिन जैसे ही मैं कच्चे प्रश्न लिखना शुरू करता हूं, मैं हर चीज के लिए सीधे पहुंच में वापस खिसकना शुरू कर देता हूं। या तो, या मैं आलसी हो जाऊंगा और PHP लूप में चीजें करना शुरू कर दूंगा जो वास्तव में सीधे MySQL प्रश्नों में किया जाना चाहिए, वैसे भी।

मैं इंटरनेट अनुप्रयोगों को लिखने के साथ अधिक अनुभवी लोगों से पूछना चाहता हूं: क्या कोड की अतिरिक्त लाइनों और संभव अक्षमताओं के लायक बनाए रखने की क्षमता है जो अमूर्तता का परिचय दे सकती है? या सीधे डेटाबेस क्वेरी को संभालने के लिए एक स्वीकार्य विधि का उपयोग कर रहा है?


हो सकता है कि आप संग्रहित प्रक्रियाओं का उपयोग select
गन्दे

जवाबों:


7

जब आपके पास बहुत से विशिष्ट क्वेरी फ़ंक्शंस होते हैं, तो आप उन्हें कंपोज़ेबल बिट्स में तोड़ने की कोशिश कर सकते हैं। उदाहरण के लिए

$posts = posts()->joinWithComments()->orderBy("post.post_date")->first(5);

अमूर्त स्तरों का एक पदानुक्रम भी है जो आपको ध्यान में रखने के लिए उपयोगी हो सकता है। आपके पास

  1. mysql एपीआई
  2. आपके mysql फ़ंक्शंस, जैसे कि सेलेक्ट ("पोस्ट से जहाँ foo = bar" का चयन करें); या शायद अधिक के रूप मेंselect("posts")->where("foo = bar")->first(5)
  3. उदाहरण के लिए, आपके डोमेन के लिए विशिष्ट कार्य posts()->joinWithComments()
  4. फ़ंक्शंस जो किसी विशेष पेज के लिए विशिष्ट हैं, जैसे कि commentsToBeReviewed($currentUser)

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


2
+1 यह सिंटैक्स अनिवार्य रूप से आपका अपना ORM बनाता है। यदि आप वास्तव में डेटाबेस एक्सेस चीजों के बारे में चिंतित हैं, जो जटिल हो रही हैं, और विवरण के साथ बहुत समय बिताना नहीं चाहते हैं, तो मैं सुझाव दूंगा कि एक परिपक्व वेब फ्रेमवर्क (जैसे CodeIgniter ) का उपयोग करें जो पहले से ही इस सामान का पता लगा चुका है। या कम से कम इसका उपयोग करके यह देखने का प्रयास करें कि यह आपको किस प्रकार की शक्करयुक्त चीनी देता है, जैसा कि xpmatteo ने प्रदर्शित किया है।
हार्टले ब्रॉडी

5

चिंता का पृथक्करण एक ऐसा सिद्धांत है जिसके बारे में पढ़ने लायक है, इस पर विकिपीडिया लेख देखें।

http://en.wikipedia.org/wiki/Separation_of_concerns

एक और सिद्धांत के बारे में पढ़ने लायक है युग्मन:

http://en.wikipedia.org/wiki/Coupling_(computer_science )

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

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

बॉस के साथ आता है और आपको बताता है कि उसके पास एक ग्राहक है जो अपनी वेबसाइट पर पोस्ट प्रदर्शित करना चाहता है, उन्हें XML की आवश्यकता है और उन्हें प्रति सेकंड पीक प्रदर्शन के बारे में 5000 अनुरोधों की आवश्यकता है। अब आपको XML / JSON / HTML जेनरेट करना होगा। आप अपने रेंडरिंग को फिर से, पहले की तरह अलग कर सकते हैं। हालाँकि अब आपको 100 सर्वरों को जोड़ने की ज़रूरत है ताकि आपको अपनी ज़रूरत का प्रदर्शन मिल सके। अब आपका डेटाबेस 100 सर्वरों से संभवत: प्रति सर्वर दर्जनों कनेक्शन के साथ हिट हो रहा है, जिनमें से प्रत्येक को तीन अलग-अलग ऐप के लिए अलग-अलग आवश्यकताओं और विभिन्न प्रश्नों आदि के साथ सीधे उजागर किया गया है। प्रत्येक फ्रंटएंड मशीन पर डेटाबेस का उपयोग सुरक्षा जोखिम और बढ़ता है। एक लेकिन मैं वहाँ नहीं जाऊँगा। अब आपको प्रदर्शन के लिए पैमाना चाहिए, प्रत्येक ऐप में अलग-अलग कैशिंग आवश्यकताएं हैं यानी अलग-अलग चिंताएं हैं। आप इसे एक कसकर युग्मित परत यानी अपने डेटाबेस एक्सेस / बिजनेस लॉजिक / रेंडरिंग लेयर में कोशिश और प्रबंधित कर सकते हैं। प्रत्येक परत की चिंताएं अब एक दूसरे के रास्ते में आने लगी हैं अर्थात डेटाबेस से डेटा की कैशिंग आवश्यकताओं को प्रतिपादन परत की तुलना में बहुत अलग किया जा सकता है, आपके पास व्यवसायिक परत में जो तर्क है वह खून में बहने की संभावना है एसक्यूएल यानी पीछे की ओर खिसकना या यह रेंडरिंग लेयर में आगे जा सकता है, यह सबसे बड़ी समस्या है जो मैंने एक परत में सब कुछ होने के साथ देखी है, यह आपके आवेदन में प्रबलित कंक्रीट डालने के समान है न कि अच्छे तरीके से।

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

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


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

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

1

मुझे लगता है कि जब आप कहते हैं "पृष्ठ ही" आप PHP स्रोत फ़ाइल का मतलब है कि गतिशील रूप से HTML उत्पन्न करता है।

डेटाबेस को क्वेरी न करें और उसी स्रोत फ़ाइल में HTML उत्पन्न करें।

वह स्रोत फ़ाइल जहां आप डेटाबेस को क्वेरी करते हैं वह "पेज" नहीं है, भले ही यह एक PHP स्रोत फ़ाइल है।

PHP स्रोत फ़ाइल में जहां आप गतिशील रूप से HTML बनाते हैं, आप बस उन कार्यों को कॉल करते हैं जो PHP स्रोत फ़ाइल में परिभाषित होते हैं जहां डेटाबेस एक्सेस किया जाता है।


0

अधिकांश मध्यम-स्तरीय परियोजनाओं के लिए मैं जिस पैटर्न का उपयोग करता हूं वह निम्नलिखित है:

  • सभी SQL क्वेरी को सर्वर-साइड कोड से अलग स्थान पर रखा गया है।

    C # के साथ कार्य करने का अर्थ है आंशिक वर्गों का उपयोग करना, अर्थात प्रश्नों को एक अलग फ़ाइल में रखना, यह देखते हुए कि वे प्रश्न एक ही वर्ग से सुलभ होंगे (नीचे कोड देखें)।

  • उन SQL क्वेरीज़ में स्थिरांक हैं । यह महत्वपूर्ण है, क्योंकि यह मक्खी पर SQL प्रश्नों के निर्माण के प्रलोभन को रोकता है (इस प्रकार SQL इंजेक्शन के जोखिम को बढ़ाता है और साथ ही बाद में प्रश्नों की समीक्षा करना अधिक कठिन बना देता है)।

C # में वर्तमान दृष्टिकोण

उदाहरण:

// Demo.cs
public partial class Demo : DataRepository
{
    public IEnumerable<Stuff> LoadStuff(int categoryId)
    {
        return this
            .Query(Queries.LoadStuff)
            .With(new { CategoryId = categoryId })
            .ReadRows<Stuff>();
    }

    // Other methods go here.
}

public partial class Demo
{
    private static class Queries
    {
        public const string LoadStuff = @"
select top 100 [StuffId], [SomeText]
    from [Schema].[Table]
    where [CategoryId] = @CategoryId
    order by [CreationUtcTime]";

        // Other queries go here.
    }
}

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

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

क्या PHP में ऐसा करना संभव है?

PHP में आंशिक कक्षाओं और आंतरिक कक्षाओं दोनों का अभाव है, इसलिए जैसा कि यह PHP में लागू नहीं किया जा सकता है।

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

namespace Data {
    public class Demo inherit DataRepository {
        public function LoadStuff($categoryId) {
            $query = \Queries\Demo::$LoadStuff;
            // Do the stuff with the query.
        }

        // Other methods go here.
    }
}

namespace Queries {
    public static class Demo {
        public const $LoadStuff = '...';

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