मैं हाल ही में एक छोटा सा कोड कोड लिख रहा था जो मानव-अनुकूल तरीके से इंगित करेगा कि कोई घटना कितनी पुरानी है। उदाहरण के लिए, यह इंगित कर सकता है कि घटना "तीन सप्ताह पहले" या "एक महीने पहले" या "कल" हुई।
आवश्यकताएँ अपेक्षाकृत स्पष्ट थीं और यह परीक्षण संचालित विकास के लिए एक आदर्श मामला था। मैंने एक-एक करके परीक्षण लिखे, प्रत्येक परीक्षण को पास करने के लिए कोड लागू किया, और सब कुछ पूरी तरह से काम करने लगा। एक बग तक उत्पादन में दिखाई दिया।
यहाँ कोड का प्रासंगिक टुकड़ा है:
now = datetime.datetime.utcnow()
today = now.date()
if event_date.date() == today:
return "Today"
yesterday = today - datetime.timedelta(1)
if event_date.date() == yesterday:
return "Yesterday"
delta = (now - event_date).days
if delta < 7:
return _number_to_text(delta) + " days ago"
if delta < 30:
weeks = math.floor(delta / 7)
if weeks == 1:
return "A week ago"
return _number_to_text(weeks) + " weeks ago"
if delta < 365:
... # Handle months and years in similar manner.
परीक्षण आज, कल, चार दिन पहले, दो सप्ताह पहले, एक सप्ताह पहले, इत्यादि की घटना के मामले की जाँच कर रहे थे और कोड उसी के अनुसार बनाया गया था।
जो मैंने याद किया वह यह है कि एक घटना कल से एक दिन पहले हो सकती है, जबकि एक दिन पहले: उदाहरण के लिए छब्बीस घंटे पहले होने वाली घटना एक दिन पहले होगी, जबकि कल ठीक नहीं है, यदि अब 1 am अधिक है, तो यह एक बिंदु है कुछ है, लेकिन चूंकि delta
एक पूर्णांक है, यह सिर्फ एक होगा। इस मामले में, एप्लिकेशन "एक दिन पहले" प्रदर्शित करता है, जो स्पष्ट रूप से कोड में अप्रत्याशित और अखंडित है। इसे जोड़कर तय किया जा सकता है:
if delta == 1:
return "A day ago"
कंप्यूटिंग के बाद बस delta
।
जबकि बग का एकमात्र नकारात्मक परिणाम यह है कि मैंने आधे घंटे बर्बाद कर दिया, यह सोचकर कि यह मामला कैसे हो सकता है (और यह विश्वास करते हुए कि यह समय क्षेत्रों के साथ करना है, कोड में यूटीसी के समान उपयोग के बावजूद), इसकी उपस्थिति मुझे परेशान कर रही है। यह इंगित करता है कि:
- इस तरह के सरल स्रोत कोड में भी तार्किक गलती करना बहुत आसान है।
- टेस्ट संचालित विकास में मदद नहीं मिली।
यह भी चिंताजनक है कि मैं यह नहीं देख सकता कि ऐसे कीड़े से कैसे बचा जा सकता है। कोड लिखने से पहले अधिक सोचने के अलावा, एक ही तरीका है जिसके बारे में मैं सोच सकता हूं कि उन मामलों के लिए बहुत सारे दावे जोड़े जाएंगे जो मुझे लगता है कि ऐसा कभी नहीं होगा (जैसे कि मुझे विश्वास था कि एक दिन पहले कल जरूरी है), और फिर प्रत्येक सेकंड के लिए लूप के माध्यम से पिछले दस वर्षों में, किसी भी उल्लंघन के लिए जाँच, जो बहुत जटिल लगती है।
मैं पहली बार में इस बग को बनाने से कैसे बच सकता हूं?