ओपनरेस्टी कोडिंग स्टाइल गाइड

API7.ai

December 15, 2022

OpenResty (NGINX + Lua)

कई विकास भाषाओं में उनकी कोडिंग विशिष्टताएं होती हैं जो डेवलपर्स को क्षेत्र में कुछ परंपराएं बताती हैं, लिखे गए कोड की शैली को सुसंगत रखने के लिए, और कुछ सामान्य गलतियों से बचने के लिए। Python का PEP 8 इसका एक उत्कृष्ट उदाहरण है, और लगभग सभी Python डेवलपर्स ने Python के लेखकों द्वारा लिखी गई इस कोडिंग विशिष्टता को पढ़ा है।

OpenResty की अभी तक अपनी कोडिंग विशिष्टता नहीं है, और कुछ डेवलपर्स को PRs जमा करने के बाद बार-बार उनके कोड स्टाइल को बदलने के लिए कहा जाता है, जो बहुत समय और प्रयास खर्च करता है जिससे बचा जा सकता है।

OpenResty में दो Lint टूल हैं जो आपको कोड स्टाइल का स्वचालित रूप से पता लगाने में मदद कर सकते हैं: luacheck और lj-releng। पहला Lua और OpenResty दुनिया में एक सामान्य Lint टूल है, और दूसरा OpenResty द्वारा Perl में लिखा गया एक Lint टूल है।

मेरे लिए, मैं VS Code एडिटर में luacheck प्लगइन इंस्टॉल करता हूं ताकि मेरे पास कोड लिखते समय स्वचालित सुझाव देने के लिए एक टूल हो; और किसी प्रोजेक्ट के CI में, मैं दोनों टूल चलाता हूं, जैसे:

luacheck -q lua ./utils/lj-releng lua/*.lua lua/apisix/*.lua

आखिरकार, परीक्षण के लिए एक और टूल कभी भी बुरी चीज नहीं होती।

हालांकि, ये दोनों टूल वैश्विक चर, प्रति पंक्ति लंबाई, और अन्य सबसे बुनियादी कोड स्टाइल का पता लगाने के बारे में अधिक हैं, जो अभी भी Python PEP 8 के विस्तृत स्तर से दूर हैं, और आपके संदर्भ के लिए कोई दस्तावेज़ नहीं है।

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

इंडेंटेशन

OpenResty में, हम इंडेंटेशन मार्कर के रूप में 4 स्पेस का उपयोग करते हैं, हालांकि Lua को ऐसे सिंटैक्स की आवश्यकता नहीं होती है। यहां गलत और सही कोड के दो उदाहरण दिए गए हैं।

--नहीं if a then ngx.say("hello") end
--हां if a then ngx.say("hello") end

सुविधा के लिए, हम आपके द्वारा उपयोग किए जा रहे एडिटर में टैब को 4 स्पेस में बदल सकते हैं।

स्पेस

ऑपरेटर के दोनों तरफ, उन्हें अलग करने के लिए एक स्पेस की आवश्यकता होती है। निम्नलिखित गलत और सही कोड के दो उदाहरण हैं।

--नहीं local i=1 local s = "apisix"
--हां local i = 1 local s = "apisix"

खाली पंक्ति

कई डेवलपर्स अन्य भाषाओं से विकास परंपराओं को OpenResty में लाते हैं, जैसे कि एक पंक्ति के अंत में सेमीकोलन जोड़ना:

--नहीं if a then ngx.say("hello"); end;

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

--नहीं if a then ngx.say("hello") end
--हां if a then ngx.say("hello") end

इसके अलावा, फ़ंक्शन को दो खाली पंक्तियों से अलग करने की आवश्यकता होती है।

--नहीं local function foo() end local function bar() end
--हां local function foo() end local function bar() end

यदि कई if elseif शाखाएं हैं, तो उन्हें भी एक खाली पंक्ति से अलग करने की आवश्यकता होती है।

--नहीं if a == 1 then foo() elseif a== 2 then bar() elseif a == 3 then run() else error() end
--हां if a == 1 then foo() elseif a== 2 then bar() elseif a == 3 then run() else error() end

प्रति पंक्ति अधिकतम लंबाई

प्रत्येक पंक्ति 80 वर्णों से अधिक नहीं होनी चाहिए; यदि यह उससे अधिक होती है, तो हमें लाइन ब्रेक और संरेखण करने की आवश्यकता होती है। और जब लाइन ब्रेक को संरेखित करते हैं, तो हमें ऊपर और नीचे की पंक्तियों के बीच संबंध को प्रतिबिंबित करने की आवश्यकता होती है। नीचे दिए गए उदाहरण के लिए, दूसरी पंक्ति पर फ़ंक्शन का तर्क पहली पंक्ति पर बाएं ब्रैकेट के दाईं ओर होना चाहिए।

--नहीं return limit_conn_new("plugin-limit-conn", conf.conn, conf.burst, conf.default_conn_delay)
--हां return limit_conn_new("plugin-limit-conn", conf.conn, conf.burst, conf.default_conn_delay)

यदि यह स्ट्रिंग्स को जोड़ने का संरेखण है, तो हमें .. को अगली पंक्ति में रखने की आवश्यकता होती है।

--नहीं return limit_conn_new("plugin-limit-conn" .. "plugin-limit-conn" .. "plugin-limit-conn")
--हां return limit_conn_new("plugin-limit-conn" .. "plugin-limit-conn" .. "plugin-limit-conn")

चर

यह बिंदु पिछले लेखों में भी कई बार जोर दिया गया था: हमें हमेशा वैश्विक चर के बजाय स्थानीय चर का उपयोग करना चाहिए।

--नहीं i = 1 s = "apisix"
--हां local i = 1 local s = "apisix"

चर के नामकरण के लिए, snake_case शैली का उपयोग किया जाना चाहिए।

--नहीं local IndexArr = 1 local str_Name = "apisix"
--हां local index_arr = 1 local str_name = "apisix"

स्थिरांक के लिए, दूसरी ओर, all-caps शैली का उपयोग किया जाना चाहिए।

--नहीं local max_int = 65535 local server_name = "apisix" --हां local MAX_INT = 65535 local SERVER_NAME = "apisix"

टेबल

OpenResty में, हम टेबल को पूर्व-आवंटित करने के लिए table.new का उपयोग करते हैं।

--नहीं local t = {} for i = 1, 100 do t[i] = i end
--हां local new_tab = require "table.new" local t = new_tab(100, 0) for i = 1, 100 do t[i] = i end

इसके अलावा, ध्यान दें कि आपको सरणी में nil का उपयोग नहीं करना चाहिए, और यदि आपको अशक्त का उपयोग करना ही है, तो ngx.null का उपयोग करें।

--नहीं local t = {1, 2, nil, 3} --हां local t = {1, 2, ngx.null, 3}

स्ट्रिंग

हॉट कोड पथ पर स्ट्रिंग्स को कभी भी न जोड़ें।

--नहीं local s = "" for i = 1, 100000 do s = s .. "a" end
--हां local t = {} for i = 1, 100000 do t[i] = "a" end local s = table.concat(t, "")

फ़ंक्शन

फ़ंक्शन का नामकरण भी snake_case का पालन करता है।

--नहीं local function testNginx() end
--हां local function test_nginx() end

और फ़ंक्शन को जल्द से जल्द वापस लौटना चाहिए।

--नहीं local function check(age, name) local ret = true if age < 20 then ret = false end if name == "a" then ret = false end -- कुछ और करें return ret
--हां local function check(age, name) if age < 20 then return false end if name == "a" then return false end -- कुछ और करें return true

मॉड्यूल

सभी require की गई लाइब्रेरी को local किया जाना चाहिए:

--नहीं local function foo() local ok, err = ngx.timer.at(delay, handler) end
--हां local timer_at = ngx.timer.at local function foo() local ok, err = timer_at(delay, handler) end

शैली की सुसंगतता के लिए, require और ngx को भी local किया जाना चाहिए:

--नहीं local core = require("apisix.core") local timer_at = ngx.timer.at local function foo() local ok, err = timer_at(delay, handler) end
--हां local ngx = ngx local require = require local core = require("apisix.core") local timer_at = ngx.timer.at local function foo() local ok, err = timer_at(delay, handler) end

त्रुटि प्रबंधन

त्रुटि जानकारी के साथ वापस लौटने वाले फ़ंक्शन के लिए, त्रुटि जानकारी का न्याय और प्रसंस्करण किया जाना चाहिए:

--नहीं local sock = ngx.socket.tcp() local ok = sock:connect("www.google.com", 80) ngx.say("successfully connected to google!")
--हां local sock = ngx.socket.tcp() local ok, err = sock:connect("www.google.com", 80) if not ok then ngx.say("failed to connect to google: ", err) return end ngx.say("successfully connected to google!")

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

--नहीं local function foo() local ok, err = func() if not ok then return false end return true end
--नहीं local function foo() local ok, err = func() if not ok then return false, {msg = err} end return true end
--हां local function foo() local ok, err = func() if not ok then return false, "failed to call func(): " .. err end return true end

सारांश

यह कोडिंग स्टाइल गाइड का एक प्रारंभिक संस्करण है, और हम इसे GitHub पर उपलब्ध कराएंगे ताकि इसे निरंतर अपडेट और रखरखाव के लिए उपलब्ध कराया जा सके। आप इस विशिष्टता को साझा करने के लिए स्वागत करते हैं ताकि अधिक OpenResty उपयोगकर्ता इसमें शामिल हो सकें।