जैक्सन संरचित प्रोग्रामिंग

From Vigyanwiki
Revision as of 16:54, 24 May 2023 by Manidh (talk | contribs)
जेएसपी आरेख का उदाहरण।

जैक्सन संरचित प्रोग्रामिंग (जेएसपी) ब्रिटिश सॉफ्टवेयर सलाहकार माइकल ए जैक्सन द्वारा विकसित संरचित प्रोग्रामिंग के लिए एक विधि है और उनकी 1975 की पुस्तक प्रिंसिपल्स ऑफ प्रोग्राम डिजाइन में वर्णित है।[1] जेएसपी (JSP) की तकनीक उन फ़ाइलों की डेटा संरचनाओं का विश्लेषण करना है जिन्हें प्रोग्राम को इनपुट के रूप में पढ़ना चाहिए और आउटपुट के रूप में प्रस्तुत करना चाहिए, और फिर उन डेटा संरचनाओं के आधार पर एक प्रोग्राम डिज़ाइन तैयार करें, ताकि प्रोग्राम नियंत्रण संरचना उन डेटा संरचनाओं को प्राकृतिक और सहज तरीके से संभाल सके।

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

परिचय

माइकल ए जैक्सन ने मूल रूप से 1970 के दशक में जेएसपी विकसित किया था। उन्होंने अपनी 1975 की पुस्तक प्रिंसिपल्स ऑफ प्रोग्राम डिजाइन में इस प्रणाली का दस्तावेजीकरण किया।[1] 2001 के एक सम्मेलन वार्ता में,[2] उन्होंने विधि के पीछे मूल प्रेरक शक्तियों का पूर्वव्यापी विश्लेषण प्रदान किया, और इसे बाद के सॉफ्टवेयर इंजीनियरिंग विकासों से संबंधित किया। जैक्सन का उद्देश्य सीओबीओएल (COBOL) बैच फाइल प्रोसेसिंग प्रोग्राम को संशोधित करना और बनाए रखना आसान बनाना था, लेकिन विधि का उपयोग किसी भी प्रोग्रामिंग भाषा के लिए प्रोग्राम डिजाइन करने के लिए किया जा सकता है जिसमें संरचित नियंत्रण निर्माण होते हैं - अनुक्रम, पुनरावृत्ति और चयन ("यदि / फिर / अन्य")।

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

विधि के लिए प्रेरणा

जिस समय जेएसपी विकसित किया गया था, उस समय अधिकांश प्रोग्राम बैच सीओबीओएल प्रोग्राम थे जो टेप पर संग्रहीत अनुक्रमिक फ़ाइलों को प्रोसेस करते थे। विशिष्ट प्रोग्राम अपनी इनपुट फ़ाइल के माध्यम से रिकॉर्ड के अनुक्रम के रूप में पढ़ता है, ताकि सभी प्रोग्रामों में एक ही संरचना हो - एकल मुख्य लूप जो फ़ाइल में सभी रिकॉर्ड को एक बार में प्रोसेस करता है।[1] जैक्सन ने जोर देकर कहा कि यह प्रोग्राम संरचना लगभग हमेशा गलत थी, और प्रोग्रामरों को अधिक जटिल डेटा संरचनाओं की खोज करने के लिए प्रोत्साहित किया। प्रोग्राम डिज़ाइन के सिद्धांतों के अध्याय 3 में जैक्सन प्रोग्राम के दो संस्करण प्रस्तुत करता है, एक को जेएसपी का उपयोग करके डिज़ाइन किया गया है, दूसरा पारंपरिक एकल-लूप संरचना का उपयोग करके। यहाँ उनका उदाहरण है, सीओबीओएल से जावा में अनुवादित। इन दो प्रोग्रामों का उद्देश्य क्रमबद्ध फ़ाइल में दोहराए गए रिकॉर्ड (पंक्तियों) के समूहों को पहचानना है, और प्रत्येक रिकॉर्ड को सूचीबद्ध करने वाली आउटपुट फ़ाइल और फ़ाइल में होने वाली संख्या को सूचीबद्ध करना है।

यहां प्रोग्राम का पारंपरिक, एकल-लूप संस्करण है।

String line;
int count = 0;
String firstLineOfGroup = null;

// begin single main loop
while ((line = in.readLine()) != null) {
    if (firstLineOfGroup == null || !line.equals(firstLineOfGroup)) {
        if (firstLineOfGroup != null) {
            System.out.println(firstLineOfGroup + " " + count);
        }
        count = 0;
        firstLineOfGroup = line;
    }
    count++;
}
if (firstLineOfGroup != null) {
    System.out.println(firstLineOfGroup + " " + count);
}

यहाँ उसी प्रोग्राम का जेएसपी-शैली संस्करण है। ध्यान दें कि (पारंपरिक प्रोग्राम के विपरीत) इसमें दो लूप होते हैं, एक दूसरे के अंदर स्थिर होता है। बाहरी लूप दोहराए जाने वाले रिकॉर्ड के समूह को प्रोसेस करता है, जबकि आंतरिक लूप एक समूह में अलग-अलग रिकॉर्ड को प्रोसेस करता है।

String line;
int numberOfLinesInGroup;

line = in.readLine();
// begin outer loop: process 1 group
while (line != null) {  
    numberOfLinesInGroup = 0;
    String firstLineOfGroup = line;

    // begin inner loop: process 1 record in the group
    while (line != null && line.equals(firstLineOfGroup)) {
        numberOfLinesInGroup++;
        line = in.readLine();
    }
    System.out.println(firstLineOfGroup + " " + numberOfLinesInGroup);
}

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

मूल विधि

जेएसपी प्रोग्राम के इनपुट और आउटपुट की उपस्थित संरचना को प्रोग्राम की संरचना में ही अधिकृत करने के लिए अर्ध-औपचारिक चरणों का उपयोग करता है।

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

जेएसपी संरचना प्रोग्राम चार घटक प्रकारों के संदर्भ में-

  • मौलिक संचालन
  • अनुक्रम
  • पुनरावृत्तियाँ
  • चयन

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

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

पीएसडी, जो कि भाषा उदासीन है, को फिर प्रोग्रामिंग भाषा में कार्यान्वित किया जाता है। जेएसपी नियंत्रण संरचनाओं के स्तर पर प्रोग्रामिंग की ओर अग्रसर है, इसलिए कार्यान्वित डिज़ाइन केवल मौलिक संचालन, अनुक्रम, पुनरावृत्तियों और चयनों का उपयोग करते हैं। जेएसपी का उपयोग वर्गों और वस्तुओं के स्तर पर प्रोग्रामों की संरचना के लिए नहीं किया जाता है, हालांकि यह वर्ग के तरीकों के भीतर प्रवाह को नियंत्रित करने में सहायता कर सकता है।

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

साधारण संचालन को बॉक्स के रूप में तैयार किया गया है।

A box labeled 'A'
An operation

संचालन का एक क्रम रेखाओं से जुड़े बॉक्सों द्वारा दर्शाया जाता है। नीचे दिए गए उदाहरण में, A अनुक्रम है जिसमें संचालन B, C और D सम्मिलित हैं।

A box labeled 'A' connected to three boxes below it labeled 'B', 'C' and 'D'
A sequence

पुनरावृति को फिर से जुड़े हुए बॉक्सों के साथ दर्शाया गया है। इसके अलावा पुनरावृत्त ऑपरेशन में इसके बॉक्स के ऊपरी दाएं कोने में एक तारा होता है। नीचे दिए गए उदाहरण में, A ऑपरेशन B के शून्य या अधिक आह्वानों की पुनरावृत्ति, पुनरावृत्ति है।

A box labeled 'A' connected to a box labeled 'B' below it with a star in the top right corner
An iteration

चयन अनुक्रम के समान है, लेकिन प्रत्येक वैकल्पिक संचालन के ऊपरी दाएं कोने में वृत्त खींचा गया है। उदाहरण में, A ऑपरेशन B, C या D में से एक और केवल एक का चयन है।

A box labeled 'A' connected to three boxes below it labeled 'B', 'C' and 'D' each with a circle in the top right hand corner
A selection

ध्यान दें कि यह उपरोक्त आरेखों में, यह तत्व A है जो अनुक्रम या पुनरावृत्ति है, न कि तत्व B, C या D (जो उपरोक्त आरेखों में सभी प्राथमिक हैं)। तत्व क्या है, यह निर्धारित करने के लिए जैक्सन 'लुक-डाउन नियम' देता है, अर्थात तत्व क्या है, यह जानने के लिए नीचे दिए गए तत्वों को देखें।

काम किया उदाहरण

उदाहरण के रूप में, यहाँ बताया गया है कि कैसे एक जेएसपी प्रोग्रामर रन लेंथ एनकोडर को डिज़ाइन और कोड करेगा। रन लेंथ एनकोडर एक प्रोग्राम है जिसका इनपुट बाइट्स का स्ट्रीम है जिसे रन में घटित होने के रूप में देखा जा सकता है, जहां रन में समान मान के बाइट्स की एक या एक से अधिक घटनाएं होती हैं। प्रोग्राम का आउटपुट बाइट जोड़े का स्ट्रीम है, जहां प्रत्येक बाइट जोड़ी रन का संकुचित विवरण है। प्रत्येक जोड़ी में, प्रथम बाइट एक रन में दोहराई गई बाइट का मान है और दूसरी बाइट एक संख्या है जो यह दर्शाती है कि रन में उस मान को कितनी बार दोहराया गया था। उदाहरण के लिए, इनपुट स्ट्रीम ("AAAAAAAA") में "A" अक्षर की आठ घटनाओं का एक रन आउटपुट स्ट्रीम में बाइट जोड़ी के रूप में "A8" उत्पन्न करेगा। रन लेंथ एनकोडर का उपयोग प्रायः बिटमैप्स को गंभीर रूप से संकुचित करने के लिए किया जाता है।

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

JSP RLE input.png

दूसरा चरण आउटपुट डेटा संरचना का वर्णन करना है, जिसमें इस स्थिति में बाइट जोड़े के शून्य या अधिक पुनरावृत्तियों का समावेश होता है।

JSP RLE output1.png

अगला चरण इनपुट और आउटपुट संरचनाओं के घटकों के बीच समानता का वर्णन करना है।

JSP RLE correspondence.png

अगला चरण प्रोग्राम संरचना बनाने के लिए दो डेटा संरचनाओं के बीच समानता का उपयोग करना है जो इनपुट डेटा संरचना को प्रोसेस करने और आउटपुट डेटा संरचना का उत्पादन करने में सक्षम है। (कभी-कभी यह संभव नहीं होता है। संरचना संघर्ष की चर्चा नीचे देखें।)

JSP RLE program.png

एक बार प्रोग्राम संरचना समाप्त हो जाने के बाद, प्रोग्रामर कम्प्यूटेशनल संचालनों की एक सूची बनाता है जिसे प्रोग्राम को निष्पादित करना चाहिए, और प्रोग्राम संरचना आरेख को उचित संरचनात्मक घटकों से उन परिचालनों को लटकाकर बाहर निकाल दिया जाता है।

  1. बाइट पढ़ें
  2. बाइट याद रखें
  3. गणित्र को शून्य पर सेट करें
  4. वृद्धि गणित्र
  5. आउटपुट याद किया गया बाइट
  6. आउटपुट गणित्र

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

  1. जबकि अधिक बाइट हैं
  2. जबकि अधिक बाइट्स हैं और यह बाइट रन की पहली बाइट के समान है और गिनती अभी भी बाइट में फिट होगी

एक बार आरेख समाप्त हो जाने के बाद, किसी भी प्रोग्रामिंग भाषा में इसका अनुवाद किया जा सकता है जिसका उपयोग किया जा रहा है। यहाँ C में अनुवाद है।

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int c;
    int first_byte;
    int count;

    c = getchar();   /* get first byte */
    while (c != EOF) {
        /* process the first byte in the run */
        first_byte = c;
        count = 1;
        c = getchar();   /* get next byte */

        /* process the succeeding bytes in the run */
        while (c != EOF && c == first_byte && count < 255) {
            /* process one byte of the same value */
            count++;
            c = getchar();   /* get next byte */
        }

        putchar(first_byte);
        putchar(count);
    }
    return EXIT_SUCCESS;
}

कठिन डिजाइन समस्याओं से निपटने के लिए तकनीकें

प्रोग्राम डिज़ाइन के सिद्धांतों में जैक्सन ने उन स्थितियों को पहचाना जो विशिष्ट प्रकार की डिज़ाइन समस्याओं को उत्पन्न करती हैं, और उनसे निपटने के लिए तकनीक प्रदान करती हैं।

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

एक अन्य प्रकार की समस्या सम्मिलित थी जिसे जैक्सन ने "पहचानने में कठिनाइयाँ" कहा था और आज हम पार्सिंग समस्याएँ कहेंगे। मूल जेएसपी डिजाइन तकनीक को पीओएसआईटी (POSIT) और क्यूयूआईटी (QUIT) संचालन द्वारा पूरक किया गया था ताकि डिजाइन की अनुमति दी जा सके जिसे अब हम बैकट्रैकिंग पार्सर कहेंगे।

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

जेएसपी और ऑब्जेक्ट-ओरिएंटेड डिज़ाइन

वस्तु-उन्मुख तकनीकों के उपलब्ध होने से बहुत पहले जेएसपी का विकास किया गया था। यह और इसकी उत्तराधिकारी विधि जेएसडी अब जो "ऑब्जेक्ट्स" कहलाती है उसे अधिक या कम स्वतंत्र तरीकों के संग्रह के रूप में नहीं मानते हैं। इसके स्थान पर, C A R होरे के काम का अनुसरण करते हुए, जेएसपी और जेएसडी सॉफ्टवेयर ऑब्जेक्ट्स को को-रूटीन के रूप में वर्णित करते हैं।[5][6]

यह भी देखें

  • जैक्सन प्रणाली का विकास
  • वार्नियर/ओआरआर आरेख

संदर्भ

  1. 1.0 1.1 1.2 Jackson, MA (1975), Principles of Program Design, Academic.
  2. Jackson, MA (2001), JSP in Perspective (PDF), sd&m Pioneers’ Conference, Bonn, June 2001, retrieved 2017-01-26{{citation}}: CS1 maint: location (link) CS1 maint: location missing publisher (link)
  3. Warnier, JD (1974), Logical Construction of Programs, NY: Van Nostrand Reinhold
  4. Orr, KT (1980), "Structured programming in the 1980s", Proceedings of the ACM 1980 Annual Conference, New York, NY: ACM Press, pp. 323–26, doi:10.1145/800176.809987, ISBN 978-0897910286, S2CID 26834496
  5. Wieringa, R (Dec 1998), "A survey of structured and object-oriented software specification methods and techniques", Comput Surv, 30 (4): 459–527, CiteSeerX 10.1.1.107.5410, doi:10.1145/299917.299919, S2CID 14967319.
  6. Henderson-Sellers, Brian; Edwards, JM (Sep 1990), "The object-oriented systems life cycle", Communications of the ACM, 33 (9): 142–59, doi:10.1145/83880.84529, S2CID 14680399.

बाहरी संबंध