If को ऊपर, For को नीचे ले जाना
(matklad.github.io)- किसी फ़ंक्शन के अंदर मौजूद if स्टेटमेंट को कॉल साइट पर ऊपर ले जाने से कोड की जटिलता कम करने में मदद मिलती है
- condition check और branch handling को एक जगह केंद्रित करने से duplication और अनावश्यक branch checks को आसानी से पहचाना जा सकता है
- enum dissolving refactor का उपयोग करके उसी condition के कोड में जगह-जगह फैल जाने की समस्या को रोका जा सकता है
- batch operations आधारित for loops performance सुधारने और दोहराए जाने वाले काम को optimize करने में प्रभावी होते हैं
- if को ऊपर, for को नीचे ले जाने वाले pattern को मिलाकर code readability और efficiency दोनों को साथ में बढ़ाया जा सकता है
दो संबंधित नियमों पर एक संक्षिप्त नोट
- अगर किसी फ़ंक्शन के भीतर if condition मौजूद है, तो यह सोचना बेहतर है कि क्या उसे फ़ंक्शन के call site पर ले जाया जा सकता है
- उदाहरण की तरह, फ़ंक्शन के अंदर precondition जाँचने के बजाय, उस condition check की ज़िम्मेदारी call site को देना या type (या assert) के ज़रिए precondition को guarantee करना अधिक उपयुक्त है
- precondition checks को ऊपर ले जाने (Push up) का तरीका पूरे कोडबेस को प्रभावित करता है और कुल मिलाकर अनावश्यक condition checks की संख्या कम करता है
control flow और conditionals का केंद्रीकरण
- control flow और if statements कोड की जटिलता और bugs के मुख्य कारण होते हैं
- conditionals को call site जैसे ऊपरी स्तर पर केंद्रित करके branch handling को एक फ़ंक्शन में समेटना, और वास्तविक काम को सीधी रेखा वाले (straight-line) subroutines को सौंपना उपयोगी pattern है
- जब branches और control flow एक ही जगह इकट्ठा होते हैं, तो duplicate branches और अनावश्यक conditions को पहचानना आसान हो जाता है
उदाहरण:
- जब f फ़ंक्शन के भीतर nested if मौजूद हो, तो dead code (Dead Branch) को पहचानना आसान होता है
- लेकिन अगर branches कई फ़ंक्शनों (g, h) में बिखरी हों, तो इसे समझना कठिन हो जाता है
enum dissolving refactor
- अगर कोड में वही conditional branch enum आदि के रूप में समाई हुई हो, तो condition को ऊपर खींचकर branch और काम को अधिक स्पष्ट रूप से अलग किया जा सकता है
- इस तरीके को लागू करने से वही condition कोड में बार-बार दोहराए जाने की समस्या से बचाती है
उदाहरण:
- f, g फ़ंक्शनों और enum E में एक ही branching condition व्यक्त की गई स्थिति को
- एक ऊपरी conditional branch के ज़रिए पूरे कोड को सरल बनाया जा सकता है
data-oriented thinking और batch operations
- अधिकांश प्रोग्राम कई objects (entities) पर चलते हैं। critical path (Hot Path) में performance अक्सर बहुत सारे objects को प्रोसेस करने से तय होती है
- batch की अवधारणा लाकर objects के set पर operations को default बनाना, और single-object operations को special case की तरह संभालना बेहतर होता है
उदाहरण:
-
frobnicate_batch(walruses)जैसी batch processing function को default रखा जाए, -
और individual objects को for loop के जरिए संभाले जाने वाले special case में बदला जा सकता है
-
performance optimization के दृष्टिकोण से यह तरीका महत्वपूर्ण है; बड़े पैमाने के काम में यह startup cost कम करता है और ordering flexibility बढ़ाता है
-
SIMD operations (struct-of-array आदि) का उपयोग भी संभव है, जिससे किसी विशेष field को bulk में प्रोसेस करने के बाद पूरा काम आगे बढ़ाया जा सकता है
व्यावहारिक उदाहरण और सुझाए गए patterns
- FFT आधारित polynomial multiplication की तरह, कई बिंदुओं पर एक साथ computation संभव बनाकर performance को अधिकतम किया जा सकता है
- conditionals को ऊपर और loops को नीचे ले जाने वाले नियम साथ-साथ लागू किए जा सकते हैं
उदाहरण:
- loop के भीतर एक ही condition expression को बार-बार जाँचने के बजाय, condition को loop के बाहर निकालने से loop के अंदर branching कम होती है और optimization तथा vectorization आसान हो जाती है
- यह approach TigerBeetle design जैसे बड़े सिस्टम data plane में भी उच्च efficiency सुनिश्चित करती है
निष्कर्ष
- if statements (conditionals) को ऊपरी स्तर (call site, control layer) पर और for loops को निचले स्तर (operation layer, data processing layer) पर ले जाने वाले pattern को मिलाकर code readability, efficiency, और performance तीनों को बेहतर बनाया जा सकता है
- abstract vector space के दृष्टिकोण से सोचना (set-level operations) बार-बार branching करने की तुलना में बेहतर problem-solving tool है
- संक्षेप में: if ऊपर, for नीचे!
1 टिप्पणियां
Hacker News राय