PrestaShop-এর গ্লোবাল কনফিগারেশন টেবিল একটি মডিউলের আনইনস্টল রুটিনকে এমনভাবে তৈরি করে যাতে এটি সম্পূর্ণ সম্পর্কহীন অন্যান্য এক্সটেনশনের সেটিংস মুছে ফেলতে পারে। Configuration::deleteByName('width') এর একটি মাত্র কল অন্য কোনো শপের কাস্টম উইডথ (width) ভ্যালু মুছে ফেলতে পারে, যা মার্চেন্টকে বিভ্রান্ত করে ফেলে এবং offending মডিউলটিকে আপাতদৃষ্টিতে ক্ষতিকর নয় বলে মনে হয়।

কেন শেয়ারড কনফিগারেশন টেবিলটি গুরুত্বপূর্ণ

PrestaShop প্রতিটি মডিউলের সেটিংস একটি মাত্র টেবিলে সংরক্ষণ করে যেখানে শুধুমাত্র একটি key এবং একটি value থাকে। এই টেবিলে এমন কোনো কলাম নেই যা রেকর্ড করে যে কোন মডিউলটি একটি row তৈরি করেছে, এবং এটি কোনো naming convention বা নামকরণের নিয়মও মেনে চলে না। ফলে, দুটি মডিউল যদি একই key ব্যবহার করে—যেমন "width" বা "API_DATE_FROM"—তবে তারা একই ডাটাবেস row পড়তে এবং লিখতে থাকবে। সর্বশেষ যে লিখবে সেটিই কার্যকর হবে, এবং পরবর্তীতে যেকোনো delete অপারেশন উভয় পক্ষের জন্যই সেই row-টি মুছে ফেলবে।

যখন আনইনস্টল কোড একটি ডাটা-মুছে ফেলার টুলে পরিণত হয়

একটি সাধারণ আনইনস্টল মেথড দেখতে অনেকটা এরকম:

public function uninstall()
{
    return Configuration::deleteByName('width');
}

এর উদ্দেশ্য হলো মডিউলের নিজস্ব কনফিগারেশন পরিষ্কার করা, কিন্তু key-টি namespaced না হওয়ার কারণে, এই স্টেটমেন্টটি "width" নামক যেকোনো row মুছে ফেলে। কোনো সতর্কতা (warning) লগ করা হয় না, কোনো exception-ও থ্রো করা হয় না; row-টি স্রেফ অদৃশ্য হয়ে যায়। মার্চেন্টের অন্য মডিউলটি নিঃশব্দে তার সেটিংস হারিয়ে ফেলে এবং অদ্ভুত আচরণ করতে শুরু করতে পারে।

ভার্সন আপগ্রেড করার সময় সমস্যাটি আরও প্রকট হয়ে ওঠে। একজন ডেভেলপার যখন ভার্সন 1.0 থেকে 2.0-এ যান, তখন তিনি হয়তো MY_MODULE_WIDTH-এর মতো একটি প্রিফিক্সযুক্ত key-এর অধীনে ভ্যালু সেভ করা শুরু করেন। পুরনো, প্রিফিক্সহীন এন্ট্রিগুলো "পরিষ্কার" করার জন্য, তারা আনইনস্টল রুটিনে একটি delete কল যোগ করেন এই বিশ্বাসে যে তারা কেবল লিগ্যাসি ডাটা (legacy data) মুছছেন। বাস্তবে, তারা সেই একই জেনেরিক key-এর অধীনে থাকা অন্যান্য এক্সটেনশনের ডাটাও মুছে ফেলছেন।

অডিট যা উন্মোচন করেছে

৫৭টি পাবলিক মডিউল রিপোজিটরির একটি অডিটে একটি পুনরাবৃত্তিমূলক প্যাটার্ন দেখা গেছে:

  • অনেক মডিউল মডিউলের নাম থেকে প্রাপ্ত কোনো প্রিফিক্স ছাড়াই "width", "height", বা "API_DATE_FROM"-এর মতো জেনেরিক key ব্যবহার করে।
  • বেশ কিছু আনইনস্টল মেথডে Configuration::deleteByName কল রয়েছে যা এই জেনেরিক key-গুলোকে টার্গেট করে।
  • এই সমস্যাটি কেবল একজন ডেভেলপার বা নির্দিষ্ট কোনো ধরনের মডিউলের মধ্যে সীমাবদ্ধ নয়; শেয়ারড টেবিল ডিজাইনের কারণে এটি একটি সিস্টেমিক ঝুঁকি (systemic risk)।

অডিটে এমন কোনো লগ বা এরর মেসেজ পাওয়া যায়নি যা একজন শপ মালিককে সতর্ক করতে পারে যে অন্য কোনো মডিউলের কনফিগারেশন মুছে ফেলা হয়েছে। এর একমাত্র লক্ষণ হলো সেটিংসের আকস্মিক হারিয়ে যাওয়া, যা মার্চেন্ট ক্যাশ (cache) সমস্যা বা তার নিজস্ব কোডের কোনো বাগ (bug) হিসেবে গণ্য করতে পারেন।

মডিউল ডেভেলপারদের জন্য নিরাপদ পদ্ধতিসমূহ

  1. প্রতিটি key-কে Namespace করুন – প্রতিটি কনফিগারেশন key-এর শুরুতে মডিউলের টেকনিক্যাল নাম যুক্ত করুন (যেমন, my_module_width)। এটি কোনো আলাদা ওনারশিপ কলামের ওপর নির্ভর না করেই একটি ইউনিক আইডেন্টিফায়ার তৈরি করে।
  2. পুরানো, প্রিফিক্সহীন key মুছে ফেলা এড়িয়ে চলুন – টেবিলে কিছু অপ্রচলিত (obsolete) row রেখে দিলে স্টোরেজে প্রায় কোনো খরচ হয় না এবং এটি অনাকাঙ্ক্ষিত ক্ষতির ঝুঁকি দূর করে।
  3. মুছে ফেলার আগে মালিকানা যাচাই করুন – যদি ডিলিট করা সত্যিই প্রয়োজন হয়, তবে প্রথমে নিশ্চিত করুন যে key-টির ভ্যালু আপনার নিজস্ব কোড দ্বারা সেট করা হয়েছে (উদাহরণস্বরূপ, একটি মার্কার ভ্যালু সংরক্ষণ করুন যা কেবল আপনার মডিউলই জানে)।
  4. আনইনস্টল মেথড অডিট করুন – কোডবেসে deleteByName কলগুলো খুঁজুন। প্রতিটি occurrence পরীক্ষা করা উচিত যাতে নিশ্চিত হওয়া যায় যে key-টি ইউনিকভাবে namespaced।
  5. নামকরণের নিয়ম (naming convention) ডকুমেন্ট করুন – মডিউলের README-তে একটি সংক্ষিপ্ত নির্দেশিকা অন্তর্ভুক্ত করুন যাতে ভবিষ্যৎ কন্ট্রিবিউটররা প্রিফিক্সযুক্ত key-এর গুরুত্ব বুঝতে পারেন।

আকস্মিক ক্রস-মডিউল ডিলিট শনাক্ত করার জন্য টেস্টিং

লাইভ শপে পৌঁছানোর আগেই বাগটি ধরার একটি ব্যবহারিক উপায়:

  • একটি ভিন্ন মডিউলের key দিয়ে কনফিগারেশন টেবিলটি সিড (seed) করুন (যেমন, other_module_setting => test)।
  • একটি নিয়ন্ত্রিত পরিবেশে মডিউলের আনইনস্টল রুটিন চালান।
  • আনইনস্টল সম্পন্ন হওয়ার পরেও সিড করা key-টি বিদ্যমান আছে কি না তা নিশ্চিত (assert) করুন।

মডিউলের ইউনিট-টেস্ট সুইটে এই চেকটি অটোমেট করলে নিশ্চিত হওয়া যায় যে, ভবিষ্যতে কোনো পরিবর্তন যদি ভুলবশত কোনো deleteByName কল যুক্ত করে, তবে সেটি টেস্টে ফেল করবে এবং রিভিউ করার তাগিদ দেবে।

শপ মালিকদের যা খেয়াল রাখা উচিত

স্টোর মালিকরা খুব কমই ইন্টারনাল ডাটাবেস row দেখেন, কিন্তু তারা লক্ষণটি শনাক্ত করতে পারেন: একটি মডিউল ডিজেবল বা আনইনস্টল করার পর, অন্য কোনো এক্সটেনশন হঠাৎ ডিফল্ট সেটিংসে ফিরে যাচ্ছে। যদি এমনটি ঘটে, তবে ডেভেলপারকে মডিউলের আনইনস্টল কোডটি গ্লোবাল কনফিগারেশন টেবিলের নিয়ম মেনে চলছে কি না তা যাচাই করতে বলুন। মডিউলটি যে সমস্ত কনফিগারেশন key ব্যবহার করে তার একটি তালিকা চান; কোনো key-এর যদি স্পষ্ট প্রিফিক্স না থাকে, তবে সেটি একটি রেড ফ্ল্যাগ (red flag)।

সারসংক্ষেপ

PrestaShop-এর ডিজাইন কনফিগারেশন টেবিলটিকে একটি শেয়ারড রিসোর্স হিসেবে তৈরি করে, এবং একটি অসতর্ক আনইনস্টল রুটিন কোনো চিহ্ন ছাড়াই অন্য একটি মডিউলের সেটিংস মুছে ফেলতে পারে। কী (key) গুলোর জন্য নেমস্পেস ব্যবহার করে, অতিরিক্ত ক্লিনআপ থেকে বিরত থেকে এবং অন্য মডিউলের এন্ট্রিগুলো সুরক্ষিত রাখতে একটি সাধারণ টেস্ট যোগ করার মাধ্যমে, ডেভেলপাররা নিঃশব্দে ডেটা হারিয়ে যাওয়া রোধ করতে পারেন এবং মার্চেন্টদের শপ স্থিতিশীল রাখতে পারেন। এর জন্য প্রয়োজনীয় প্রচেষ্টা খুবই সামান্য, কিন্তু একটি সেটিংস হারিয়ে যাওয়ার ফলে সৃষ্ট ক্ষতি—যেমন গ্রাহকের অভিযোগ, সাপোর্ট টিকিট এবং সুনাম নষ্ট হওয়া—অনেক বেশি হতে পারে।