Monday, May 22, 2017

এনক্যাপসুলেশন নিয়ে যত পাগলামী ॥ পাগলের প্রলাপ

অবজেক্ট অরিয়েন্টেড ল্যাঙ্গুয়েজের যে কয়েকটি স্বকীয় বৈশিষ্ট্য রয়েছে তার মধ্যে অন্যতম গুরুত্বপূর্ন এবং সবচেয়ে সহজবোধ্য বৈশিষ্ট্য হল এনক্যাপসুলেশন । আমিতো পাগল, আপনারা যেহেতু এটা পড়ছেন কিছুক্ষন পর আপনারাও পাগল হয়ে গেলে আমার কিছুই করার থাকবে না । তো চলুন আর কথা না বলে পাগলামী শুরু করি ।

আশাকরি জীবনে একবার হলেও অসুস্থ হয়েছেন । না হলে তো খুবই খুশির কথা । আর সেটা না হলেও ঔষধ হিসাবে খাওয়া হয় যে ক্যাপসুল সেটা নিশ্চয় দেখেছেন । তো এখন কিছুটা ক্যাপসুল নিয়ে কথা বলি ।

খেয়াল করলে দেখবেন ক্যাপসুলের বাইরে শক্ত একটা পরত থাকে এর সেটার মাঝে অনেকগুলা উপাদান থাকে যেগুলাকে ওই শক্ত আবরনটা বেষ্টন করে থাকে । তার মানে ওই উপাদানগুলাকে শক্ত খোলস দ্বারা আবদ্ধ করা হয়েছে সুরক্ষিত রাখার জন্য । মানে উপাদানগুলাে এনক্যাপসুলেট করা হয়েছে ওই খোলসের মাঝে । এমনটা করার কারন হল উপাদানগুলা যেন প্রাকৃতিক আলো, বাতাস, জীবানুতে ক্ষতিগ্রস্থ না হয়ে ভেতরে সুরক্ষিত থাকে । এধরনের ক্যাপসুল যখন খাওয়া হয় তখন সেটা হিউম্যান বডিতে প্রবেশ করে উপরের খোলসটি ফেটে যায় এবং বডিতে কাজ শুরু করে । তার মানে এই ক্যাপসুলের খোলসটি দেওয়া হয়েছে একটা সিকিউরিটি লেয়ার হিসাবে । সেটা যেন বডিতে কাজ করতে পারে কিন্তু অন্যান্য প্রাকৃতিক ইনগ্রিডিয়েন্ট থেকে সুরক্ষিত থাকে ।

অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং এর অন্যতম একটি প্রধান বৈশিষ্ট্য কিন্তু ঠিক এই কনসেপ্ট যেটি একটু আগেই ব্যাখ্যা করলাম । আমরা সবাই জানি অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং এর কনসেপ্টে দুনিয়ার তাবৎ সবকিছুই অবজেক্ট । আপনি, আমি, লতা-পাতা, গাছ, পাখি, ফুল যত যা কিছু আমরা দেখতে পাই, দেখা যায়না, অনুভব করতে পারি, বা কল্পনা করতে পারি সবই অবজেক্ট । একটি অবজেক্টের (জাভার রেসপেক্টে) ৪ টি প্রধান কম্পোনেন্ট থাকে, (i) ব্লক (ii) কনস্ট্রাক্টর (iii) অ্যাট্রিবিউট (স্টেট) (iv) মেথড (বিহ্যেবিয়র) ।
(i) & (ii) এই দুইটি কম্পোনেন্ট আপাতত আমাদের দরকার হবেনা, যখন হবে তখন জেনে নেওয়া যাবে ।  তবে আমি আশাকরব যেহেতু আপনারা এই আর্টিকেলটি পড়তে এসেছেন তাই এদের কাজ হালকা পাতলা হলেও কিছুটা জানেন ।
(iii) অ্যাট্রিবিউটঃ অ্যাট্রিবিউট মানে হল ভ্যারিয়েবল । এখানে যে ভ্যারিয়েবলের কথা বলা হচ্ছে সেটিকে ফিল্ডও বলা হয় কারন এটি সরাসরি কনটেইনার ক্লাসের আন্ডারে ডিক্লেয়ার করা হয় । কোন মেথডের মাঝে ডিক্লেয়ার করা ভেরিয়েবলকে লোকাল ভ্যারিয়েবল বলা হবে এবং ওটা ভোলাটাইল । অ্যাট্রিবিউটকে অবজেক্টের স্টেটও বলা হয় । কারন একটি অবজেক্টের ইন্সট্যান্ট কন্ডিশন বা স্টেট ধারন করে বিধায় এর এরকম নামকরন ।
(iv) মেথডঃ যারা প্রোসিডিউরাল প্রোগ্রামিং এর সাথে পরিচিত তারা এটাকে ফাংশন হিসাবে চিনে থাকবেন হয়ত । মেথডের মাঝে বিভিন্ন অ্যাট্রিবিউট নিয়ে নাড়াচাড়া করা হয় । একই অ্যাট্রিবিউটের উপর আলাদা আলাদা মেথডের প্রভাব আলাদা আলাদা হয়ে থাকে । মানে একই অ্যাট্রিবিউটকে যদি ২ টি আলাদা মেথডের মাঝে প্যারামিটার হিসাবে পাস করা হয় তবে সেই মেথড ২ টি উক্ত অ্যাট্রিবিউটের সাথে একই রকম ভদ্র ব্যাবহার নাও করতে পারে, বেশিরভাগ ক্ষেত্রেই করেনা । এজন্য মেথডকে একটি অবজেক্টের বিহ্যেবিয়রও বলা হয় ।

পরিচিতি পর্ব শেষ , এবার পাগলের প্রলাপ শুরু করা যাক । আমরা সবাই জানি যে একটি অবজেক্টের ব্লুপ্রিন্ট হল ক্লাস । তার মানে একটি অবজেক্টের মাঝে কি কি স্টেট থাকবে এবং উক্ত স্টেট গুলার জন্য কি কি ধরনের বিহ্যেব (আচরন) করতে পারে অবজেক্টটি সেগুলা সব ডেসক্রাইব করা থাকে তার ক্লাসে ।

এখন কথা হল একটি ক্লাস লেখার সময় আমরা ৪ ধরনের অ্যাট্রিবিউট ডিক্লেয়ার করতে পারি তাদের অ্যাক্সেসিবিলিটির উপর নির্ভর করে । তার মানে উক্ত অ্যাট্রিবিউটটিকে কে কে বা কোন কোন জায়গা থেকে অ্যাক্সেস এবং মডিফাই করা সম্ভব । অ্যাক্সেসিবিলিটি কনট্রোল করার এই ৪ প্রকার মডিফায়ারকে বলা হয় অ্যাক্সেস মডিফায়ার । এদের নাম এবং কাজ সম্পর্কে নিচের টেবিলটি দেখলে বুঝতে পারব ।
এখানে দেখতে পারছি public মডিফায়ার ব্যাবহার করলে সেই অ্যট্রিবিউটটিকে যেকোন স্থান থেকে সরাসরি অ্যাক্সেস করা সম্ভব । আর private মডিফায়ার ব্যাবহার করলে কেবল উক্ত ক্লাসের মেফডগুলাতে সেটির অ্যাক্সেস পাওয়া সম্ভব । ছোট্ট একটা উদাহরন দেখি ।

কোডঃ
public class EncapTest {

    public int x;
    private int y;

    public void showX() {

        System.out.println("In EncapTest -> " + x);
    }

    public void showY() {

        System.out.println("In EncapTest -> " + y);
    }
}

public class Main {

    public static void main(String[] args) {

        EncapTest et = new EncapTest();
        et.x = 10;
//        et.y = 5; //This field is not accessible here outside from EncapTest class
        et.showX();
        et.showY();
        System.out.println("Outside from EncapTest -> " + et.x);
//        System.out.println("Outside from EncapTest -> " + et.y); // Not valid
    }
}

আউটপুটঃ
In EncapTest -> 10
In EncapTest -> 0
Outside from EncapTest -> 10

উপরোক্ত কোডটিতে আমরা 'EncapTest' ক্লাসে ২ টি অ্যাট্রিবিউট ডিক্লেয়ার করেছি, 'x' যেটি পাবলিক এবং 'y' যেটি প্রাইভেট । অর্থাৎ 'x' কে উক্ত ক্লাস এবং উক্ত ক্লাসের বাইরে যেকোন ক্লাস থেকে এবং যেকোন মেথড থেকে অ্যাক্সেস করা সম্ভব কিন্তু 'y' কে কেবল মাত্র 'EncapTest' ক্লাসের অবস্থিত মেথড ব্যাতীত অন্য কোন স্থান থেকে অ্যাক্সেস বা মডিফাই করা সম্ভব নয় । অর্থাৎ 'y' অ্যাট্রিবিউটটিকে আমরা 'EncapTest' ক্লাসে এনক্যাপসুলেট করে ফেলেছি ।

কথা হল এনক্যাপসুলেশন নাহয় বুঝলাম বা কিভাবে করা হয় সেটাও নাহয় বুঝলাম কিন্তু এটা করতে গেলাম কেন ! ওয়েট, কারন আছে । এটা করা হয় সিকিউরিটি মেইনটেইন করার জন্য । মানে খুব সফিসটিকেটেড এবং সেনসেটিভ কোন স্টেট যেন যেকোন স্থান থেকে মডিফাই হতে না পারে যেটা হলে উক্ত স্টেট পলুটেড হয়ে যাবে । এজন্য আমরা খুব সেনসেটিভ এবং সফিস্টিকেটেড অ্যাট্রিবিউটের অ্যাক্সেস বাউন্ডেড করে দেই যেন সেটা যেকোন স্থান থেকে মডিফাই না হতে পারে এবং সিস্টেম যেন পলুটেড হয়ে না যায় ।

কিন্তু একটা অ্যাট্রিবিউটকে যদি আমরা প্রয়োজনে মডিফাই নাই করতে পারলাম বা অ্যাক্সেসই না করতে পারলাম তাহলে সেটা রেখে লাভ কি ! ওকে, সেটার ব্যাবস্থাও আছে । এটার জন্য আমরা যে কাজটি করি সেটা হল পাবলিক একটা ইন্টারফেস (যে ইন্টারফেস ইমপ্লিমেন্ট করা হয় সেটা না) রাখি যে মাধ্যমে আমরা উক্ত অ্যাট্রিবিউটকে অ্যাক্সেস করতে পারি । এধরনের পাবলিক ইন্টারফেসকে বলা হয় গেটার (getter) এবং সেটার (setter) মেথড । এই মেথডগুলার অ্যাক্সেস মডিফায়ার সাধারনত (অসাধারনও হতে পারে) দেওয়া থাকে পাবলিক এবং যেকোন স্থান থেকে তাদের অ্যাক্সেস করা সম্ভব । গেটার মেথডের মাধ্যমে কোন একটি অ্যাট্রিবিউটের ভ্যালু রিড করা হয় এবং সেটার মেথডের মাধ্যমে কোন একটা অ্যাট্রিবিউটের ভ্যালু সেট করা হয় বা সহজ কথায় ভ্যালু ওভাররাইড করা হয় । চলুন একটা উদাহরন দেখে নেওয়া যাক ।

কোডঃ
public class EncapTest {

    private int x;
    private int y;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

public class Main {

    public static void main(String[] args) {

        EncapTest et = new EncapTest();
        et.setX(5);
        et.setY(7);
        System.out.println("Value of x: " + et.getX()); //x is accessible through getter
//        System.out.println(et.x); //x is not directly accessible
        System.out.println("Value of y: " + et.getY());
    }
}

আউটপুটঃ
Value of x: 5
Value of y: 7

উপরোক্ত ছোট্ট প্রোগ্রামটিতে আমরা দেখতে পারছি যে 'EncapTest' ক্লাসের মাঝে ডিক্লেয়ার কৃত ২ টি অ্যাট্রিবিউট 'x' & 'y' প্রাইভেট তাই মেইন মেথডের মাঝ থেকে সরাসরি তাদের কোনভাবেই অ্যাক্সেস করা সম্ভব নয় । কিন্তু তাদের গেটার এবং সেটারের মাধ্যমে অ্যাক্সেস করা সম্ভব ।

মূল লক্ষনীয় বিষয় এবার । খেয়াল করে দেখুনতো একটা অ্যাট্রিবিউটকে প্রাইভেটলি ডিক্লেয়ার করে সেটার গেটার এবং সেটারকে যদি পাবলিক ডিক্লেয়ার করা হয় তবে উক্ত অ্যাট্রিবিউটটিকে বরং পাবলিক ডিক্লেয়ার করার মাঝে কোন তফাৎ থাকে কি না । নাহ কোন তফাতই থাকবে না, কারন প্রাইভেট প্রোপার্টি হওয়া সত্তেও উক্ত অ্যাট্রিবিউটকে যেকোন স্থান থেকে মেনুপুলেট করা সম্ভব । তাহলে আর এনক্যাপসুলেট করলাম কিভাবে !

অ্যাক্সেস লেয়ার অনুযায়ী এনক্যাপসুলেশন আসলে আমাদের করতে হবে গেটার এবং সেটার মেথডে । অর্থাৎ একটি অ্যাট্রিবিউট (অবশ্যই সেটা যদি পাবলিক টাইপ স্ট্যাটিক বা ফাইনাল না হয় তবে) ডিক্লেয়ার করার সময় প্রাইভেটলি ডিক্লেয়ার করতে হবে এবং মডিফিকেশন স্কোপ সেট করে দিতে হবে মেথড লেয়ারে । ওকে একটা উদাহরন দেখে ফেলি ।

কোডঃ
public class EncapTest {

    private int x;
    private int y;

    public int getX() {
        return x;
    }

    void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    void setY(int y) {
        this.y = y;
    }
}

public class Main {

    public static void main(String[] args) {

        EncapTest et = new EncapTest();
        et.setX(5);
        et.setY(7);
        System.out.println("Value of x: " + et.getX()); //x is accessible through getter
//        System.out.println(et.x); //x is not directly accessible
        System.out.println("Value of y: " + et.getY());
    }
}

আউটপুটঃ
Value of x: 5
Value of y: 7

উপরোক্ত প্রোগ্রামটিতে খুব ছোট্ট কিন্তু অনেক গুরুত্বপূর্ন যে পরিবর্তনটুকু করা হয়েছে সেটা হল আমরা 'x' & 'y' এর সেটারকে এনক্যাপসুলেট করে দিয়েছি প্যাকেজ স্কোপে । অর্থাৎ, যেখান থেকেই 'EncapTest' এর অবজেক্ট ক্রিয়েট করা হোক না কেন সেটার গেটার দুটি ঠিকই অ্যাক্সেস পাবে কিন্তু সেটার কেবল মাত্র উক্ত প্যাকেজের বাইরে অ্যাক্সেস পাবে না । মানে 'EncapTest' ক্লাসটি যে প্যাকেজে থাকবে উক্ত প্যাকেজে অবস্থিত যেকোন ক্লাসে যদি 'EncapTest' এর অবজেক্ট ক্রিয়েট করা হয় তবে সেসব ক্লাসে উক্ত অবজেক্টগুলার সেটার মেথডের মাধ্যমে 'x' এবং 'y' এর ভ্যালু মডিফাই করা সম্ভব কিন্তু প্যাকেজ স্কোপের বাইরে সেটা করা সম্ভব নয় । গেটার মেথড পাবলিক হওয়ায় যেকোন স্থান থেকে 'x' এবং 'y' ভ্যালু রিড করা সম্ভব । এখানে 'x' এবং 'y' এর মডিফিকেশন এনক্যাপসুলেট করে দেওয়া হয়েছে প্যাকেজ স্কোপে এবং ডাটা রিডের ক্ষেত্রে কোন প্রকার এনক্যাপসুলেশন আরোপ করা হয়নি ।

ওকে, এবার একটা জিনিস দেখি । এতক্ষন আমরা 'x' এবং 'y' নিয়ে কাজ করলাম যে দুটিই প্রিমিটিভ ভ্যালু । যদি এমন হয় যে আমরা অ্যাট্রিবিউট হিসাবে অন্য কোন ক্লাসের অবজেক্ট নিয়ে কাজ করছি সেক্ষেত্রে কি হবে ? এক্ষেত্রে আমাদের জানতে হবে অবজেক্ট রেফারেন্স কিভাবে কাজ করে । সেটা জানার জন্য আপনারা এই আর্টিকেলটি পড়ে ফেলতে পারেন । ওকে তাহলে আমরা জানি যে রেফারেন্স টাইপের ক্ষেত্রে গেটার মেথড আমাদের উক্ত অবজেক্টের রেফারেন্স রিটার্ন করবে । মানে আমরা যদি কোন প্রকার সেটার মেথড ব্যাবহার নাও করি তার পরেও আমরা উক্ত অবজেক্টের ম্যানুপুলেশন করতে পারব । ছোট্ট একটা উদাহরন দেখে ফেলি ।

কোডঃ
public class EncapObject {

    private int id;

    public int getId() {
        return id;
    }

    void setId(int id) {
        this.id = id;
    }
}

public class EncapTest {

    private EncapObject encapObject;

    public EncapTest(EncapObject encapObject) {
        this.encapObject = encapObject;
    }

    public EncapObject getEncapObject() {
        return encapObject;
    }
}

public class Main {

    public static void main(String[] args) {

        EncapObject encapObject = new EncapObject();
        encapObject.setId(5);
        EncapTest et = new EncapTest(encapObject);
        et.getEncapObject().setId(7);
        System.out.println(et.getEncapObject().getId());
    }
}

আউটপুটঃ
7

উক্ত ছোট্ট প্রোগ্রামটিতে আমরা দেখতে পারছি যে 'EncapTest' ক্লাসের মাঝে 'EncapObject' ক্লাসের যে অবজেক্ট 'encapObject' রয়েছে তার অ্যাক্সেস মডিফায়ার প্রাইভেট । মানে বাইরে থেকে অ্যাক্সেস পাওয়া সম্ভব নয় । উক্ত অবজেক্সেট কোন সেটার মেথডও তৈরি করা হয়নি কিন্তু একটি গেটার মেথড রয়েছে যেটি পাবলিক এবং গেটার মেথড উক্ত অবজেক্টের রেফারেন্সই রিটার্ন করে ভ্যালু নয় যেজন্য উক্ত অবজেক্টকে খুব সহয়ে ম্যানুপুলেট করা সম্ভব যদিও কোন সেটার মেথড প্রেজেন্ট নেই । এজন্য রেফারেন্স টাইপ অ্যাট্রিবিউটের ক্ষেত্রে আমাদের অবশ্যই এনক্যাপসুলেশন স্কোপ এমন ভাবে সেট করতে হবে যেন সেটার পল্যুশন না হয় ।

আশাকরি আপনারা সবাই বুঝতে পেরেছেন এনক্যাপসুলেশন কি এবং কেন সেটা এতটা গুরুত্বপূর্ন । বড় এবং সফিসিস্টিকেটেড অ্যাপ্লিকেশন যেখানে সিকিউরিটি খুবই গুরুত্বপূর্ন সেসব ক্ষেত্রে এনক্যাপসুলেশনের গুরুত্ব অপরিসীম ।

সবশেষে একটি প্রশ্ন, এনক্যাপসুলেশন আসলে কি ? কোন একটা অ্যাট্রিবিউটকে প্রাইভেট ডিক্লেয়ার করে তার পাবলিক গেটার এবং সেটার তৈরি করাই কি এনক্যাপসুলেশন ?

প্রশ্নের উত্তরটি আমারো জানা নেই । যদি কেউ জেনে থাকেন তবে আমাকে সেটা জানিয়ে বাধিত করবেন । সবাইকে ধন্যবাদ । আর হ্যা এরপর থেকে অসুখ করলে ডাক্তার যদি ক্যাপসুল খেতে দেয় তবে খাওয়ার আগে বুঝেশুনে খাবেন । কি না কি আছে ভেতরে সেটা তো আর জানেন না, হয়ত আপনার কাছে সেটা জানার ক্ষমতা দেওয়া হয়নি !

No comments:

Post a Comment