ফ্যাক্টরি অবজেক্ট এবং ফ্যাক্টরি মেথড প্যাটার্ন - পর্ব এক
ফ্যাক্টরি শব্দের অর্থ আমাদের সবারই জানা। বাংলায় আমরা ফ্যাক্টরিকে বলি কারখানা।
- তো, কারখানায় আসলে কী হয়?
- কিছু একটা তৈরি হয়।
- আচ্ছা! সফটওয়্যার ডেভেলপমেন্টে আবার কারখানার কী প্রয়োজন?
- আমরা যখন কোন সফটওয়্যার লিখি তখন আমাদের বিভিন্ন ধরণের টাইপ (class, structure প্রভৃতি) নিয়ে কাজ করতে হয়। তো এই টাইপ গুলোর ইন্সট্যান্স আমরা ক্লায়েন্ট কোডেও তৈরি করতে পারি বা কোন ফ্যাক্টরিকে দিয়েও তৈরি করিয়ে নিতে পারি। কোন একটি নির্দিষ্ট ক্লাস যদি আমাদেরকে কোন টাইপের ইন্সট্যান্স তৈরি করে দেয় তবে তাকে ফ্যাক্টরি অবজেক্ট বলা হয়।
এখন প্রশ্ন হচ্ছে এই ফ্যাক্টরি অবজেক্ট আমাদের লাগবে কেন? এর সাথে ফ্যাক্টরি মেথড প্যাটার্নেরই বা কী সম্পর্ক? এসব প্রশ্নের উত্তর দেবার আগে চলুন দুটি সফটওয়্যার ডিজাইন প্রিন্সিপলসের সাথে পরিচয় হয়ে নেই। প্রিন্সিপলস দুটি হল DRY (Don't Repeat Yourself) এবং OCP (Open Closed Principle)।
DRY প্রিন্সিপল আমাদের বলে যে, আমরা যেন আমাদের সফটওয়্যারে একই কোড বারবার কপি-পেস্ট করে ব্যবহার না করি।
- কেন? করলে সমস্যা কী?
- প্রথম সমস্যা হচ্ছে, একই কোড বারবার লিখে আমরা আমাদের সময় এবং কম্পিউটারের মেমোরি দুটোরই অপব্যবহার করছি। আর দ্বিতীয় সমস্যা আপাতদৃষ্টিতে চোখে না পরলেও পরবর্তীতে স্টেকহোল্ডার যখন কোন চেঞ্জ চাইবে তখন ঠিকই চোখে পরবে। তখন প্রত্যেক সেসব জায়গায় গিয়ে আমাদের চেঞ্জ করতে হবে যেখানে আমরা কোড ডুপ্লিকেট করেছি। এতে করে মেইন্টেইনেন্স থেকে ইউনিট টেস্টিং পুরোটাই দুঃস্বপ্নে রূপান্তরিত হবে। আর ভুলক্রমে কোথাও যদি কোড রিফ্যাক্টর করতে ভুলে যাই! থাক! সেদিকে আর না-ই বা গেলাম।
OCP হচ্ছে SOLID প্রিন্সিপলসের O। ওসিপি আমাদের বলে যে একটি ক্লাস পরিবর্তনের জন্য বন্ধ এবং সম্প্রসারণের জন্য খোলা রাখতে হবে।
কি? গোলমেলে মনে হচ্ছে? আচ্ছা! আর একটু ক্লিয়ার করে বলি, যদি কোন কোড একবার রিলিজ হয়ে যায় অর্থাৎ আমরা যদি ক্লায়েন্ট এন্ডে কোন কোড একবার ডেপ্লোয় করে দেই এবং এরপর যদি নতুন কোন চেঞ্জ রিকোয়েস্ট আসে তাহলে আমরা সরাসরি আগের কোড পরিবর্তন না করে নতুন একটা ইমপ্লিমেন্টেশন লিখে দিব। এতে করে পুরনো ক্লায়েন্ট কোডও ব্রেক হবে না আর কেউ ইচ্ছা করলে নতুন ইমপ্লিমেন্টেশনটিও ব্যবহার করতে পারবে।
তো এই যে সফটওয়্যার ডিজাইনের দুটি মূলমন্ত্রের কথা বললাম, প্রায়শই আমরা চেঞ্জ রিকোয়েস্ট ইমপ্লিমেন্ট করতে গিয়ে এগুলো ভঙ্গ করে ফেলি। তবে আমরা যদি ফ্যাক্টরি মেথড প্যাটার্ন ব্যবহার করে কোড করি তবে এই সমস্যা আমরা সহজেই এড়িয়ে যেতে পারব। ফ্যাক্টরি মেথড প্যাটার্নেও আমরা ফ্যাক্টরি অবজেক্টের ব্যবহার দেখতে পাব তাই আগে যদি আমরা ফ্যাক্টরি অবজেক্ট সম্পর্কে জেনে নেই তাহলে আমাদের ফ্যাক্টরি মেথড প্যাটার্ন বুঝতে সুবিধা হবে।
আমরা একটি ডেমো অ্যাপ্লিকেশন লিখি তাহলে? ধরা যাক, আমাদের একটি কলমের দোকান আছে। আমরা বিভিন্ন ধরণের কলম বিক্রি করি। কোন কাস্টমার এসে যখন আমাদের কাছে কোন কলম চায় আমরা তাকে সেটা দিয়ে দেই। সে না বলার আগ পর্যন্ত কিন্তু আমরা আসলে জানিনা যে সে কোন কলম টা নিতে চাচ্ছে।
[নোটঃ যখনই আমরা দেখব যে, রানটাইমে আমাদের কোন অবজেক্ট অ্যালোকেট করতে হচ্ছে অর্থাৎ কম্পাইল টাইমে আমরা আসলে জানিনা যে ক্লায়েন্ট কোডের কোন টাইপের অবজেক্ট লাগবে সেই ক্ষেত্রে আমরা ফ্যাক্টরি মেথড প্যাটার্ন ইমপ্লিমেন্ট করার কথা ভাবতে পারি।]
ধরা যাক, আমাদের কাছে আপাতত দুই ধরণের কলম আছে। ইকনো এবং ম্যাটাডোর। যেহেতু দুইটা অবজেক্টই একই ধরণের সেহেতু আমরা এখানে ইনহেরিটেন্সের ব্যবহার করতে পারি। তো আমরা Pen নামে একটি বেজ ক্লাস বানালাম। বোঝার সুবিধার্থে আমরা এখানে শুধুমাত্র একটি প্রোপার্টি রেখেছি যেটা কিনা Price. আর যেহেতু Pen এখানে অ্যাবস্ট্রাকশন বা ধারণা মাত্র সেহেতু এটিকে আমরা abstract কী-ওয়ার্ড ব্যবহার করে ডিক্লেয়ার করেছি যাতে করে কেউ এই ক্লাসের ইন্সট্যান্স তৈরি করতে না পারে। তো আমাদের বেজ ক্লাস টা দেখতে এরকম হলঃ
এখন আমরা EconoPen এবং MatadorPen নামে দুইটা ক্লাস তৈরি করলাম যারা কিনা Pen ক্লাসকে ইনহেরিট করে। এখানে আমরা যার যার মূল্য সেট করে দিলাম। কোড দেখতে কিছুটা এরকম হলঃ
এবার আমরা নিম্নোক্ত উপায়ে ক্লায়েন্ট কোড থেকে আমাদের সুবিধামত Econo/Matador ক্লাসের ইন্সট্যান্স তৈরি করতে পারব।
স্পষ্টতই দেখা যাচ্ছে যে আমাদের ডিজাইনে একটি ঝামেলা আছে। ঝামেলাটি হচ্ছে ক্লায়েন্ট কোড নিজে Pen অবজেক্ট তৈরি করার দায়িত্ব নিচ্ছে। ভবিষ্যতে আমরা যদি নতুন কোন ধরণের কলম বিক্রির সিদ্ধান্ত নেই তাহলে ক্লায়েন্ট কোডে আরও একটি else if বাড়ানো লাগবে। অর্থাৎ আমরা কী কী ধরনের কলম বিক্রি করব ক্লায়েন্ট কোডের সেটা আগে থেকে জানা থাকতে হবে। আবার আমরা যদি কোন কলম বিক্রি বন্ধ করে দেই তাহলে ক্লায়েন্ট কোডে এসে সেই else if ব্লক টা তুলে দিতে হচ্ছে।
এই যে আমরা নতুন কোন ফিচার যোগ/বিয়োগ হলে ক্লায়েন্ট কোড পরিবর্তন করছি এটা কিন্তু ওপেন ক্লোজ প্রিন্সিপল ভঙ্গ করছে। তাছাড়া শুধু এক জায়গা থেকেই যে এভাবে Pen অবজেক্ট তৈরি হবে তাও কিন্তু নয়। আমাদের প্রোগ্রামের অন্য কোন ক্লাস থেকে যদি অন্য কেউ Pen অবজেক্ট তৈরি করতে চায় তাকেও এসব কোড পুনরাবৃত্তি করতে হবে যেটা কিনা DRY প্রিন্সিপল ভঙ্গ করে।
বোঝাই যাচ্ছে নেহাত ছোট একটি অ্যাপ্লিকেশনেই যদি আমাদের এতসব প্রবলেমে পরতে হয় তাহলে রিয়েল লাইফ প্রজেক্টে কী ধরণের বিশৃঙ্খলা তৈরি হতে পারে। আশা করি ফ্যাক্টরি অবজেক্টের প্রয়োজনীয়তা তুলে ধরতে পেরেছি। এবার আমরা দেখব, কীভাবে ফ্যাক্টরি অবজেক্ট আমাদের এসব ঝামেলা থেকে মুক্তি দিতে পারে।
তো আমাদের যেটা করতে হবে সেটা হচ্ছে PenFactory নামে একটি ক্লাস বানাতে হবে। এবং এই ক্লাসে একটি কন্সট্রাক্টর ডিফাইন করতে হবে যেটা কিনা প্যারামিটার হিসেবে penName নিবে এবং সেই অনুযায়ী আমাদেরকে অবজেক্ট বানিয়ে দিবে। অবজেক্ট পাবার জন্য আমরা একটি GetPen নামে একটি মেথড লিখলাম। কোড দেখতে কিছুটা নিচের মত হলঃ
এবার ক্লায়েন্ট কোড থেকে আমরা নিম্নোক্ত উপায়ে যেকোন Pen অবজেক্ট একসেস করতে পারব।
এখন PenFactory তে আমরা যতখুশি নতুন ধরণের কলম যোগ করি না কেন, ক্লায়েন্ট কোডের তা জানা লাগবে না এবং নতুন ফিচার যোগ/বিয়োগ করলেও ক্লায়েন্ট কোড ব্রেক করবে না। তাছাড়া Pen অবজেক্ট তৈরি করার দায়িত্ব PenFactory কে দিয়ে দেয়ায় অন্য কাউকে কোড ডুপ্লিকেট ও করতে হবে না।
এবার তাহলে আমরা নতুন একটি ফিচার যোগ করে দেখি যে আমাদের ক্লাসটি কী রকম ফ্লেক্সিবল/মেইন্টেইনবল হল। তো আমরা যেটা করব সেটা হচ্ছে Pen ক্লাসে Stock নামে নতুন একটি প্রোপার্টি যোগ করব। যদি স্টক থাকে তাহলে আমরা অবজেক্ট রিটার্ন করব আর যদি না থাকে তাহলে null রিটার্ন করব। তো দেখি ক্ল্যায়েন্ট কোডে হাত না দিয়ে আমরা এই কাজটা করতে পারি কিনা। নতুন ফিচার যোগ করার পর ক্লাস গুলোর চেহারা কিছুটা এরকম হলঃ
খেয়াল করার বিষয় হল আমরা কিন্তু ক্লায়েন্ট কোডে কোন চেঞ্জ করিনি। ক্লায়েন্ট কোড টেরও পায়নি যে আমরা নতুন একটা বিজনেস লজিকের উপর ভিত্তি করে এখন Pen অবজেক্ট রিটার্ন করছি। তো এই হচ্ছে ফ্যাক্টরি অবজেক্ট।
দুঃখের বিষয় হচ্ছে যে আমরা এখনো ফ্যাক্টরি মেথড প্যাটার্ন নিয়ে কথা বলা শুরু করতে পারলাম না। তবে আমরা ব্যাসিক টা কাভার করে ফেলেছি। এবার খুব সহজেই আমরা ফ্যাক্টরি মেথড প্যাটার্ন কীভাবে কাজ করে তা বুঝতে পারব। যেহেতু আর্টিকেল টি খুব বড় হয়ে যাচ্ছে তাই এই পর্বে আর ফ্যাক্টরি মেথড প্যাটার্ন নিয়ে আলোচনা করলাম না। তবে এই আর্টিকেলের পরবর্তী সিকুয়েলে আমরা ফ্যাক্টরি মেথড প্যাটার্ন নিয়ে ইন-ডিটেইলস আলোচনা করব।
0 মন্তব্য(গুলি)