পাঠ ৩২ · ৫৭-এর মধ্যে · মডিউল ৮
Home / Courses / Mobile App Development / লোকাল স্টোরেজ

কী-ভ্যালু স্টোরেজ

Key-value storage
৭ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • কী-ভ্যালু স্টোরেজ কী এবং কখন এটি ব্যবহার করা উচিত (ছোট, সমতল, স্ট্রাকচারবিহীন ডেটার জন্য)
  • get/set/remove — এই তিনটি অপারেশনের সঠিক আচরণ
  • একটি মিসিং কী-এর জন্য ডিফল্ট-ভ্যালু ফলব্যাক কেন গুরুত্বপূর্ণ
  • একটি সত্যিকারের, কার্যকর KeyValueStore ক্লাস — এবং কেন এই ইন-মেমোরি সংস্করণ বাস্তব ডিভাইসের পার্সিস্টেন্স প্রতিস্থাপন করতে পারে না

১ · কী-ভ্যালু স্টোরেজ কী

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

iOS — UserDefaults
অ্যাপ-স্কোপড একটি প্লিস্ট-ব্যাকড কী-ভ্যালু স্টোর, ছোট সেটিংসের জন্য অফিসিয়ালি সুপারিশকৃত।
Android — SharedPreferences
একটি XML ফাইলে ব্যাক-আপ করা কী-ভ্যালু স্টোর, প্রতিটি অ্যাপের নিজস্ব প্রাইভেট স্টোরেজে থাকে।
React Native — AsyncStorage
একটি অ্যাসিঙ্ক্রোনাস, আনএনক্রিপ্টেড কী-ভ্যালু স্টোর — নিচে প্ল্যাটফর্ম-নির্দিষ্ট মেকানিজম ব্যবহার করে।

২ · get / set / remove — তিনটি অপারেশন

যেকোনো কী-ভ্যালু স্টোরের ইন্টারফেস তিনটি অপারেশনে ফিট করে যায়। set(key, value) একটি মান সংরক্ষণ করে (আগে থেকে থাকলে ওভাররাইট করে)। get(key, default) মান ফিরিয়ে দেয় — কিন্তু কী-টি না থাকলে ক্র্যাশ না করে default প্যারামিটারে দেওয়া মান ফিরিয়ে দেয়, যা এই প্যাটার্নের সবচেয়ে গুরুত্বপূর্ণ নিরাপত্তা বৈশিষ্ট্য। remove(key) একটি কী মুছে দেয়, না থাকলে নিরাপদে কিছুই করে না।

Python
# একটি সত্যিকারের কী-ভ্যালু স্টোর -- একটি dict-এর উপর get/set/remove
# একটি বাস্তব ডিভাইসে এই dict-টি ডিস্কে (UserDefaults/SharedPreferences) লেখা হতো,
# যাতে অ্যাপ রিস্টার্টের পরও ডেটা টিকে থাকে -- এই in-memory সংস্করণ শুধু আচরণটি সিমুলেট করে

class KeyValueStore:
    def __init__(self):
        self._data = {}

    def set(self, key, value):
        self._data[key] = value
        print(f"SET    {key!r} = {value!r}")

    def get(self, key, default=None):
        found = key in self._data
        value = self._data.get(key, default)
        status = "পাওয়া গেছে" if found else "পাওয়া যায়নি -- ডিফল্ট ব্যবহার হলো"
        print(f"GET    {key!r} -> {value!r}  ({status})")
        return value

    def remove(self, key):
        existed = key in self._data
        if existed:
            del self._data[key]
        status = "মুছে ফেলা হলো" if existed else "ছিলোই না, কিছু করা হয়নি"
        print(f"REMOVE {key!r}  ({status})")

store = KeyValueStore()
store.set("theme", "dark")
store.set("font_size", 16)
store.set("onboarding_seen", True)

store.get("theme")
store.get("font_size")
store.get("notifications_enabled", default=True)   # এই কী কখনো set হয়নি

store.remove("onboarding_seen")
store.get("onboarding_seen", default=False)         # সরানোর পর আবার -- এখন মিসিং

print(f"\nবর্তমান সব সংরক্ষিত ডেটা: {store._data}")

    
লক্ষ্য করুন notifications_enabled কী-টি কখনো set করা হয়নি, তাই get এটি খুঁজে না পেয়ে সরাসরি default=True মানটি ফিরিয়ে দেয় — কোনো KeyError ছাড়াই। এই ফলব্যাক আচরণ ছাড়া প্রতিটি get কলের আগে "কী-টি আদৌ আছে কি না" আলাদাভাবে চেক করতে হতো, যা বাস্তব কোডে বিরক্তিকর ও ভুলপ্রবণ। একটি বাস্তব ডিভাইসে এই _data ডিকশনারিটি প্রতিটি set-এর পর (বা নির্দিষ্ট বিরতিতে) ডিস্কে ফ্লাশ হয়ে যায়, তাই অ্যাপ সম্পূর্ণ বন্ধ (killed) হয়ে আবার চালু হলেও মানগুলো টিকে থাকে — এই Pyodide স্যান্ডবক্সে প্রতিটি কোড-সেল রান একটি তাজা Python পরিবেশে চলে বলে এই ইন-মেমোরি dict নিজে থেকে সেই "রিস্টার্টের পরও টেকা" ব্যাপারটি প্রমাণ করতে পারে না — L31-এ আমরা সেই CONCEPT-টি একটি স্পষ্ট background→killed→relaunch সিমুলেশন দিয়ে আলাদাভাবে দেখিয়েছিলাম।
মূল কথা · Key takeaway

কী-ভ্যালু স্টোরেজ হলো "সবচেয়ে সরল যা কাজ করে" নীতির একটি প্র্যাকটিক্যাল উদাহরণ — এটি কোনো কোয়েরি ইঞ্জিন বা স্কিমা অফার করে না, কিন্তু ছোট, স্বাধীন সেটিংসের জন্য এটিই সবচেয়ে দ্রুত ও সহজ সমাধান। যখন ডেটার মধ্যে সম্পর্ক থাকে বা ফিল্টার/সর্ট করে কোয়েরি করার দরকার হয়, তখন পরের পাঠে (L33) আমরা একধাপ উপরে উঠে লোকাল SQL-স্টাইল ডেটাবেসে যাব।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ get মেথডে default প্যারামিটার না থাকলে কী সমস্যা হতো?

তখন প্রতিটি কল-সাইটে আগে থেকে if key in store._data: দিয়ে চেক করতে হতো, নয়তো একটি মিসিং কী-এর জন্য KeyError (বা None ফেরত পেয়ে পরবর্তী কোডে অপ্রত্যাশিতভাবে ভেঙে পড়া) হতো। ডিফল্ট-ভ্যালু ফলব্যাক এই চেকটিকে get-এর ভেতরেই একবার লিখে সবার জন্য সমাধান করে দেয়।

প্র ০২ কী-ভ্যালু স্টোরেজ দিয়ে কেন একাধিক সম্পর্কিত রেকর্ড (যেমন ১০০টি নোট) ভালোভাবে সংরক্ষণ করা যায় না?

কী-ভ্যালু স্টোরে কোনো "একাধিক রেকর্ডে ফিল্টার করো" বা "নির্দিষ্ট শর্তে সাজাও" ধরনের কোয়েরি নেই — প্রতিটি কী স্বাধীন। ১০০টি নোট রাখতে হলে ১০০টি আলাদা কী দরকার হতো, আর "শুধু পিন করা নোটগুলো দেখাও" জিজ্ঞেস করতে সবগুলো কী নিজে হাতে লুপ করে চেক করতে হতো — এটাই ঠিক সেই সমস্যা যা L33-এর লোকাল SQL-স্টাইল টেবিল সমাধান করে।

প্র ০৩ কোড সেলে remove("onboarding_seen")-এর পর আবার remove("onboarding_seen") কল করলে কী প্রিন্ট হবে?

"REMOVE 'onboarding_seen' (ছিলোই না, কিছু করা হয়নি)" প্রিন্ট হবে — কারণ existed = key in self._data এখন False হবে (কী-টি প্রথমবারই মুছে ফেলা হয়েছে), তাই del কল হবে না, শুধু নিরাপদে একটি বার্তা প্রিন্ট হয়ে ফাংশন রিটার্ন করবে — কোনো এরর ছাড়াই।

অনুশীলন

  1. চিন্তা করুন: আপনার ফোনের কোনো অ্যাপের সেটিংস মেনুতে এমন কোনো টগল/স্লাইডার মনে করুন (যেমন "ডার্ক মোড", "নোটিফিকেশন চালু") যা অ্যাপ বন্ধ করে আবার খুললেও একই অবস্থায় থাকে — এটি কী-ভ্যালু স্টোরেজের কোন অপারেশনের মাধ্যমে সম্ভব হয় বলে আপনার মনে হয়?

    টগল পরিবর্তনের মুহূর্তেই অ্যাপ একটি set("dark_mode", True)-জাতীয় কল করে সেই মানটি ডিস্কে লিখে ফেলে। অ্যাপ পরের বার চালু হওয়ার সময় UI তৈরি করার আগেই একটি get("dark_mode", default=False) কল করে সংরক্ষিত মানটি পড়ে এবং সেই অনুযায়ী টগলটি সঠিক অবস্থায় দেখায়।

  2. পরীক্ষা করুন: উপরের কোড সেলে store.set("font_size", 16)-এর পর একটি নতুন লাইনে store.set("font_size", 20) যোগ করুন, তারপর store.get("font_size") কল করে দেখুন কী প্রিন্ট হয়।

    "GET 'font_size' -> 20 (পাওয়া গেছে)" প্রিন্ট হবে — দ্বিতীয় set কলটি একই কী-এর পুরনো মান (১৬) ওভাররাইট করে ফেলেছে, কারণ self._data[key] = value লাইনটি শর্তহীনভাবে নতুন মান বসিয়ে দেয়। এটাই দেখায় কেন set-কে "insert-or-update" আচরণ বলা হয়, শুধু "insert" নয়।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

  • কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ অ্যাপ লাইফসাইকেল, মোবাইল UI/UX, MVVM/MVI আর্কিটেকচার, নেভিগেশন, স্টেট ম্যানেজমেন্ট, লোকাল স্টোরেজ, ডিভাইস ফিচার ও ডিপ্লয়মেন্ট — বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
  • পরের পাঠ L33 মোবাইলে লোকাল SQL ডেটাবেস — যখন ডেটার মধ্যে সম্পর্ক ও কোয়েরির দরকার হয়, কী-ভ্যালু স্টোরেজের পরের ধাপ।
  • সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Programming Languages & Compiler Design, Software Engineering & Git, Theory of Computation, Engineering Economics, Full-Stack Web Frameworks ও Mobile App Development — সব এক জায়গায়।
আগের পাঠ
অ্যাপ কিলের পর স্টেট রিস্টোরেশন