Springboot - Design Patterns

জ্যাঙ্গো (Django) নিয়ে আমাদের আগের আলোচনার পর, তুমি এখন জাভা (Java) ইকোসিস্টেমের সবচেয়ে জনপ্রিয় এবং শক্তিশালী ফ্রেমওয়ার্ক Spring Boot নিয়ে জানতে চেয়েছ। এটি একটি চমৎকার উদ্যোগ!

সফটওয়্যার ইঞ্জিনিয়ারিংয়ে স্প্রিং ফ্রেমওয়ার্ককে বলা হয় ডিজাইন প্যাটার্নসের একটি জীবন্ত জাদুঘর। স্প্রিংয়ের মূল ভিত্তি Inversion of Control (IoC) এবং Dependency Injection (DI) নিজেই একটি বিশাল আর্কিটেকচারাল প্যাটার্ন। স্প্রিং বুট ডেভেলপারদের জন্য ডাটাবেস কানেকশন, সিকিউরিটি, ট্রানজ্যাকশন এবং এপিআই তৈরির কাজকে যতটা সহজ করেছে, তার পেছনে লুকিয়ে আছে ক্লাসিক ডিজাইন প্যাটার্নগুলোর মাস্টারক্লাস ইমপ্লিমেন্টেশন।

চলো, গভীরভাবে বিশ্লেষণ করে দেখি স্প্রিং বুট কীভাবে এর কোর আর্কিটেকচারে ডিজাইন প্যাটার্নগুলো ব্যবহার করে।

১. Singleton Pattern (সিঙ্গেলটন প্যাটার্ন)

স্প্রিং বুটে ব্যবহার: Spring Beans-এর ডিফল্ট স্কোপ। গভীর বিশ্লেষণ: তুমি যখন কোনো ক্লাসের ওপরে @Component, @Service, @Repository বা @Controller অ্যানোটেশন ব্যবহার করো, স্প্রিংয়ের IoC কন্টেইনার স্টার্টআপের সময় সেই ক্লাসের মাত্র একটিমাত্র (Single) ইনস্ট্যান্স তৈরি করে মেমোরিতে রেখে দেয়। যখনই অ্যাপ্লিকেশনের অন্য কোথাও সেই ক্লাসটিকে @Autowired করা হয়, স্প্রিং নতুন অবজেক্ট তৈরি না করে ওই একই ইনস্ট্যান্সটি প্রোভাইড করে। এর ফলে মেমোরি কনজাম্পশন একদম কমে যায় এবং এন্টারপ্রাইজ লেভেলের অ্যাপ্লিকেশনে পারফরম্যান্স কয়েক গুণ বেড়ে যায়।

২. Factory Pattern (ফ্যাক্টরি প্যাটার্ন)

স্প্রিং বুটে ব্যবহার: BeanFactory এবং ApplicationContext। গভীর বিশ্লেষণ: স্প্রিং ফ্রেমওয়ার্কের হার্ট বা হৃৎপিণ্ড হলো এর কন্টেইনার। স্প্রিং কোডে ডেভেলপারদের সরাসরি new কিওয়ার্ড ব্যবহার করতে নিরুৎসাহিত করে। এর বদলে স্প্রিংয়ের ApplicationContext একটি বিশাল ফ্যাক্টরি হিসেবে কাজ করে। রানটাইমে স্প্রিং তোমার ক্লাসগুলো স্ক্যান করে, তাদের ডিপেন্ডেন্সিগুলো রিজল্ভ করে এবং তোমার হয়ে অবজেক্ট তৈরি করে দেয়। অবজেক্ট ক্রিয়েশনের এই জটিল লজিক ফ্যাক্টরির কাছে থাকায় কোড থাকে লুজলি কাপলড (Loosely Coupled)।

৩. Proxy Pattern (প্রক্সি প্যাটার্ন) - সবচেয়ে গুরুত্বপূর্ণ

স্প্রিং বুটে ব্যবহার: Spring AOP, @Transactional, এবং @Cacheable। গভীর বিশ্লেষণ: স্প্রিং বুটে প্রক্সি প্যাটার্নের ব্যবহার সবচেয়ে বেশি এবং ম্যাজিক্যাল। ধরো, তুমি ডাটাবেসে ডেটা সেভ করার জন্য একটি মেথডের ওপর @Transactional লিখেছ। স্প্রিং সরাসরি তোমার মেথড কল করে না; বরং সে ডাইনামিকভাবে তোমার ক্লাসের একটি "প্রক্সি (Proxy) ক্লাস" তৈরি করে। যখন ক্লায়েন্ট মেথডটি কল করে, সেটি প্রথমে প্রক্সির কাছে যায়। প্রক্সি ডাটাবেস ট্রানজ্যাকশন শুরু করে, তারপর তোমার মূল মেথড এক্সিকিউট করে, এবং শেষে ট্রানজ্যাকশন কমিট বা রোলব্যাক করে। তুমি টেরই পাও না যে ব্যাকগ্রাউন্ডে এত কিছু হচ্ছে!

৪. Observer Pattern (অবজার্ভার প্যাটার্ন)

স্প্রিং বুটে ব্যবহার: Spring Application Events। গভীর বিশ্লেষণ: স্প্রিংয়ে ইভেন্ট-ড্রিভেন আর্কিটেকচার (Event-Driven Architecture) তৈরি করার জন্য অবজার্ভার প্যাটার্ন ব্যবহৃত হয়। তুমি ApplicationEventPublisher ব্যবহার করে যেকোনো ইভেন্ট পাবলিশ করতে পারো। আর স্প্রিংয়ের যেকোনো বিনে @EventListener অ্যানোটেশন দিয়ে সেই ইভেন্ট লিসেন করতে পারো। যেমন: ইউজার রেজিস্ট্রেশন হওয়ার পর ইমেইল পাঠানো এবং ডাটাবেসে লগ রাখা—এই কাজগুলো একে অপরের সাথে টাইটলি কাপলড না রেখে ইভেন্টের মাধ্যমে ট্রিগার করা যায়।

৫. Template Method Pattern (টেমপ্লেট মেথড প্যাটার্ন)

স্প্রিং বুটে ব্যবহার: JdbcTemplate, RestTemplate, MongoTemplate। গভীর বিশ্লেষণ: জাভাতে র (Raw) JDBC ব্যবহার করে ডাটাবেস কানেকশন ওপেন করা, স্টেটমেন্ট তৈরি করা, রেজাল্ট ফেচ করা এবং শেষে finally ব্লকে কানেকশন ক্লোজ করা—খুবই বিরক্তিকর এবং বয়লারপ্লেট (Boilerplate) কোড। স্প্রিংয়ের JdbcTemplate টেমপ্লেট মেথড প্যাটার্ন ব্যবহার করে এই কমন কাজগুলো ফ্রেমওয়ার্কের ভেতরেই করে ফেলে। তুমি শুধু SQL কোয়েরি এবং অবজেক্ট ম্যাপিং লজিকটুকু প্রোভাইড করো। এতে কোডের সাইজ ৮০% কমে যায় এবং ডাটাবেস লিক হওয়ার ঝুঁকি থাকে না।

৬. Strategy Pattern (স্ট্র্যাটেজি প্যাটার্ন)

স্প্রিং বুটে ব্যবহার: PlatformTransactionManager এবং Spring Security-এর AuthenticationProvider। গভীর বিশ্লেষণ: স্প্রিং জানে না তুমি কোন ডাটাবেস টেকনোলজি ব্যবহার করবে (JPA, Hibernate, নাকি JTA)। তাই স্প্রিং PlatformTransactionManager নামে একটি ইন্টারফেস বানিয়েছে। রানটাইমে তুমি যে টেকনোলজি ব্যবহার করবে, স্প্রিং সেই নির্দিষ্ট স্ট্র্যাটেজি ইমপ্লিমেন্ট করে নেবে। একইভাবে স্প্রিং সিকিউরিটিতে পাসওয়ার্ড ম্যাচ করার জন্য PasswordEncoder ইন্টারফেসটি স্ট্র্যাটেজি প্যাটার্ন অনুসরণ করে, যেখানে তুমি রানটাইমে Bcrypt, Argon2 বা Pbkdf2 অ্যালগরিদমে সুইচ করতে পারো।

৭. Builder Pattern (বিল্ডার প্যাটার্ন)

স্প্রিং বুটে ব্যবহার: ResponseEntity, UriComponentsBuilder, এবং Security Configuration। গভীর বিশ্লেষণ: একটি রেস্ট এপিআই (REST API) থেকে রেসপন্স পাঠানোর সময় স্ট্যাটাস কোড, হেডার এবং বডি একসাথে গুছিয়ে পাঠানোর জন্য স্প্রিং ResponseEntity.Builder ব্যবহার করে। এছাড়া স্প্রিং সিকিউরিটিতে HttpSecurity কনফিগার করার সময় যে চেইনিং মেথডগুলো (যেমন: .authorizeHttpRequests().anyRequest().authenticated()) ব্যবহার করা হয়, তা পুরোপুরি বিল্ডার প্যাটার্নের চমৎকার উদাহরণ।

৮. Adapter Pattern (অ্যাডাপ্টার প্যাটার্ন)

স্প্রিং বুটে ব্যবহার: Spring MVC-এর HandlerAdapter। গভীর বিশ্লেষণ: স্প্রিং এমভিসির কোর কম্পোনেন্ট DispatcherServlet যখন কোনো রিকোয়েস্ট পায়, তখন সে জানে না কন্ট্রোলারটি কীভাবে লেখা হয়েছে (সেটি কি @RestController, নাকি পুরোনো কোনো XML-বেসড কন্ট্রোলার)। এখানে HandlerAdapter অ্যাডাপ্টার প্যাটার্ন ব্যবহার করে সেই নির্দিষ্ট কন্ট্রোলারকে কল করার উপযোগী করে তোলে, যাতে DispatcherServlet-কে কন্ট্রোলারের ভেতরের ইমপ্লিমেন্টেশন নিয়ে ভাবতে না হয়।

৯. Chain of Responsibility (চেইন অফ রেসপনসিবিলিটি)

স্প্রিং বুটে ব্যবহার: Spring Security Filter Chain এবং HandlerInterceptor। গভীর বিশ্লেষণ: জ্যাঙ্গোর মিডলওয়্যারের মতোই স্প্রিং বুটে সিকিউরিটি ফিল্টার চেইন কাজ করে। একটি রিকোয়েস্ট যখন আসে, তখন সেটি CorsFilter, CsrfFilter, UsernamePasswordAuthenticationFilter-এর মতো একাধিক ফিল্টারের চেইন অতিক্রম করে। যেকোনো একটি ফিল্টার চাইলে রিকোয়েস্টটিকে আটকে দিয়ে সরাসরি 401 Unauthorized রেসপন্স ফিরিয়ে দিতে পারে, ঠিক যেমন Chain of Responsibility প্যাটার্নে কাজ করে।

১০. Facade Pattern (ফেসেড প্যাটার্ন)

স্প্রিং বুটে ব্যবহার: @RestController এবং Data Access Layer। গভীর বিশ্লেষণ: তুমি যখন একটি @RestController তৈরি করো, সেটি ক্লায়েন্টের (যেমন: React বা Angular ফ্রন্টএন্ড) কাছে পুরো সিস্টেমের একটি Facade বা সহজ ইন্টারফেস হিসেবে কাজ করে। ক্লায়েন্ট শুধু একটি URL-এ কল করে; সে জানে না যে ব্যাকএন্ডে কন্ট্রোলারটি একাধিক সার্ভিস ক্লাস, রিপোজিটরি ক্লাস এবং এক্সটার্নাল এপিআই কল করে পুরো কাজটি সম্পন্ন করছে।

জ্যাঙ্গো বা স্প্রিং বুটের মতো ফ্রেমওয়ার্কগুলো ডেভেলপারদের বারবার চাকা আবিষ্কার করা (Reinventing the wheel) থেকে বিরত রাখে। ডিজাইন প্যাটার্নগুলো ফ্রেমওয়ার্কের গভীরে মিশে থাকে বলে আমরা খুব সহজেই মেইনটেইনেবল, সিকিউর এবং হাই-পারফরম্যান্স এন্টারপ্রাইজ অ্যাপ্লিকেশন তৈরি করতে পারি। স্প্রিং বুটের এই আর্কিটেকচারাল সৌন্দর্যই একে এন্টারপ্রাইজ দুনিয়ার অপ্রতিদ্বন্দ্বী রাজা বানিয়েছে।