কম্পিউটার টিউটোরিয়াল

সার্ভিস অবজেক্ট ব্যবহার করে আপনার রেইলস অ্যাপ্লিকেশন রূপান্তর: ক্লিন, স্কেলেবল আর্কিটেকচার

একটি সার্ভিস অবজেক্ট হলো একটি রুবি অবজেক্ট যা একটি একক অ্যাকশন পারফর্ম করে। এটি আপনার ডোমেন বা বিজনেস লজিকের একটি প্রসেস এনক্যাপসুলেট করে। কল্পনা করুন আপনাকে একটি কাল্পনিক লাইব্রেরি অ্যাপ্লিকেশনে একটি বুক ইনস্ট্যান্স তৈরি করতে হয়; একটি প্লেইন রেইলস অ্যাপে, আপনি নিচের মতো করতেন:

class BookController < ApplicationController def create Book.new(*args) end end 

এটি সিম্পল জিনিসের জন্য ঠিক। তবে, যেমন-जैसे অ্যাপ বড় হয়, আপনি এর চোড়া বয়লারপ্লেট দিয়ে শেষ হতে পারেন:

class BookController < ApplicationController def create default_args = { genre: find_genre(), author: find_author() } Book.new(attrs.merge(default_args)) end private def find_genre // ... end def find_author // ... end end 

সার্ভিস অবজেক্ট আপনাকে এই বিহেভিয়র একটি আলাদা ক্লাসে অ্যাবস্ট্রাক্ট করতে দেয়। তারপর, আপনার কোড আবার সিম্পল হয়ে যায়:

class BookController < ApplicationController def BookCreator.create_book end end 

কেন আপনার সার্ভিস অবজেক্ট দরকার

রেইলস নেটিভলি MVC (যেমন মডেল, কন্ট্রোলার, ভিউ, এবং হেল্পার) আর্গানাইজেশনাল স্ট্রাকচার সাপোর্ট করে। এই স্ট্রাকচার সিম্পল অ্যাপ্লিকেশনের জন্য যথেষ্ট। তবে, আপনার অ্যাপ্লিকেশন বড় হওয়ার সাথে সাথে, আপনি ডোমেন/বিজনেস লজিক মডেল এবং কন্ট্রোলার জুড়ে ছড়িয়ে পড়ে দেখতে পারেন। এই লজিকগুলো না কন্ট্রোলারের থাকে না মডেলের, তাই কোড রি-ইউজ এবং মেইনটেইন করা কঠিন হয়ে যায়। একটি রেইলস সার্ভিস অবজেক্ট একটি প্যাটার্ন যা আপনাকে বিজনেস লজিক কন্ট্রোলার এবং মডেল থেকে আলাদা করতে সাহায্য করে, যাতে মডেলগুলো সিম্পলি ডেটা লেয়ার হয় এবং কন্ট্রোলার আপনার API-র এন্ট্রি পয়েন্ট।

বিজনেস লজিক এনক্যাপসুলেট করতে সার্ভিস ইন্ট্রোডিউস করলে আমরা অনেক বেনিফিট পাই, যার মধ্যে:

  • লিন রেইলস কন্ট্রোলার - কন্ট্রোলার শুধু রিকোয়েস্ট বুঝতে এবং রিকোয়েস্ট প্যারামস, সেশন, এবং কুকিস আর্গুমেন্টে রূপান্তর করে দায়বদ্ধ যেগুলো সার্ভিস অবজেক্টে পাস করা হবে এক্ট করার জন্য। কন্ট্রোলার তারপর রিডাইরেক্ট বা রেন্ডার করে সার্ভিস রেসপন্স অনুযায়ী। বড় অ্যাপ্লিকেশনেও, সার্ভিস অবজেক্ট ব্যবহার করে কন্ট্রোলার অ্যাকশন সাধারণত ১০ লাইন কোডের বেশি নয়।

  • টেস্টেবল কন্ট্রোলার - যেহেতু কন্ট্রোলার লিন এবং সার্ভিসের কোলাবোরেটর হিসেবে সার্ভ করে, টেস্ট করা খুব সহজ হয়, কারণ আমরা শুধু চেক করতে পারি কন্ট্রোলারের নির্দিষ্ট মেথডগুলো কল হয় কিনা যখন একটি নির্দিষ্ট অ্যাকশন ঘটে।

  • বিজনেস প্রসেস আইসোলেশনে টেস্ট করার ক্ষমতা - সার্ভিসগুলো টেস্ট করা সহজ এবং দ্রুত যেহেতু সেগুলো ছোট রুবি অবজেক্ট যা তাদের এনভায়রনমেন্ট থেকে আলাদা করা হয়েছে। আমরা সহজে সব কোলাবোরেটর স্টাব করতে পারি এবং শুধু চেক করতে পারি আমাদের সার্ভিসের ভেতরে নির্দিষ্ট স্টেপগুলো পারফর্ম হচ্ছে কিনা।

  • রি-ইউজেবল সার্ভিস - সার্ভিস অবজেক্ট কল করা যেতে পারে কন্ট্রোলার, অন্যান্য সার্ভিস অবজেক্ট, কিউড জব, ইত্যাদি দ্বারা।

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

সার্ভিস অবজেক্ট তৈরী

প্রথমে, আসুন একটি নতুন BookCreator তৈরি করি একটি নতুন ফোল্ডার app/services-এ একটি কাল্পনিক লাইব্রেরি ম্যানেজমেন্ট অ্যাপ্লিকেশনের জন্য:

$ mkdir app/services && touch app/services/book_creator.rb 

পরবর্তী, আসুন আমাদের সকল লজিক একটি নতুন রুবি ক্লাসে ডাম্প করি:

# app/services/book_creator.rb class BookCreator def initialize(title:, description:, author_id:, genre_id:) @title = title @description = description @author_id = author_id @genre_id = genre_id end def create_book Boook.create!( title: @title description: @description author_id: @author_id genre_id: @genre_id ) rescue ActiveRecord::RecordNotUnique => e # handle duplicate entry end end end 

তারপর, আমরা সার্ভিস অবজেক্টকে কন্ট্রোলার বা অ্যাপ্লিকেশনের যেকোনো জায়গা থেকে কল করতে পারি:

class BookController < ApplicationController def create BookCreator.new(title: params[:title], description: params[:description], author_id: params[:author_id], genre_id: params[:genre_id]).create_book end end 

সার্ভিস অবজেক্ট সিনট্যাক্টিক শুगर

আমরা BookCreator.new(arguments).create চেইনকে সিম্পলিফাই করতে পারি একটি ক্লাস মেথড যোগ করে যা BookCreator ইনস্ট্যানশিয়েট করে এবং আমাদের জন্য create মেথড কল করে:

# app/services/book_creator.rb class BookCreator def initialize(title:, description:, author_id:, genre_id:) @title = title @description = description @author_id = author_id @genre_id = genre_id end def call(*args) new(*args).create_book end private def create_book Boook.create!( title: @title description: @description author_id: @author_id genre_id: @genre_id ) rescue ActiveRecord::RecordNotUnique => e # handle duplicate entry end end end 

কন্ট্রোলারে, বুক ক্রিয়েটর এখন নিচের মতো কল করা যাবে:

class BookController < ApplicationController def create BookCreator.call( title: params[:title], description: params[:description], author_id: params[:author_id], genre_id: params[:genre_id]) end end 

আমাদের কোড DRY (Don't Repeat Yourself) রাখতে এবং এই বিহেভিয়র অন্যান্য সার্ভিস অবজেক্টের সাথে রি-ইউজ করতে, আমরা call মেথডকে একটি বেস ApplicationService ক্লাসে অ্যাবস্ট্রাক্ট করতে পারি যা প্রতিটি সার্ভিস অবজেক্ট ইনহেরিট করবে:

class ApplicationService self.call(*args) new(*args).call end end 

এই কোড দিয়ে, আমরা BookCreator রিফ্যাক্টর করতে পারি ApplicationService থেকে ইনহেরিট করতে:

# app/services/book_creator.rb class BookCreator < ApplicationService def initialize(title:, description:, author_id:, genre_id:) @title = title @description = description @author_id = author_id @genre_id = genre_id end def call create_book end private def create_book # ... end end 

BusinessProcess জেম ব্যবহার করে সার্ভিস অবজেক্ট তৈরী

BusinessProcess জেম দিয়ে, আপনাকে একটি বেস অ্যাপ্লিকেশন সার্ভিস ক্লাস তৈরি করতে হয় না বা initialize মেথড ডিফাইন করতে হয় না কারণ জেমে এই কনফিগারেশনগুলো বিল্ট-ইন রয়েছে। আপনার সার্ভিস অবজেক্ট শুধু BusinessProcess::Base থেকে ইনহেরিট করতে হবে।

আপনার জেম ফাইলে নিচের কন্টেন্ট যোগ করুন:

gem 'business_process' 

এবং আপনার টার্মিনালে bundle কমান্ড রান করুন

class BookCreator < BusinessProcess::Base # প্রয়োজনীয়তা নির্দিষ্ট করুন needs :title needs :description needs :author_id needs :genre_id # প্রসেস (অ্যাকশন) নির্দিষ্ট করুন def call create_book end private def create_book # ... end end 

ভালো সার্ভিস অবজেক্ট তৈরি করার গাইডলাইন

এক পাবলিক মেথড

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

সার্ভিস অবজেক্টের নাম তারা যা রোল পারফর্ম করে সেটি অনুযায়ী রাখুন

একটি সার্ভিস অবজেক্টের নাম ইন্ডিকেট করা উচিত সেটি কী করে। সার্ভিস অবজেক্ট নামকরণের একটি জনপ্রিয় পদ্ধতি হলো "or" এবং "er" দিয়ে শেষ হওয়া শব্দ ব্যবহার করা। উদাহরণস্বরূপ, যদি সার্ভিস অবজেক্টের কাজ হয় বুক তৈরি করা, নাম দিন BookCreator, এবং যদি কাজ হয় বুক পড়া, নাম দিন BookReader।

সার্ভিস অবজেক্ট সরাসরি ইনস্ট্যানশিয়েট ন করুন

সিনট্যাক্টিক শুगर প্যাটার্ন বা BusinessProcess এর মতো জেমের মতো অ্যাবস্ট্রাকশন ব্যবহার করুন সার্ভিস অবজেক্ট কল করার নোটেশন সংক্ষিপ্ত করতে। এই অ্যাপ্রোচ ব্যবহার করলে আপনি BookCreator.new(*args).call বা BookCreator.new.call(*args) কে BookCreator.call(*args), এ সিম্পলিফাই করতে পারবেন, যা ছোট এবং বেশি রিডেবল।

সার্ভিস অবজেক্ট নেমস্পেসে গ্রুপ করুন

সার্ভিস অবজেক্ট ইন্ট্রোডিউস করা, বিশেষত একটি বড় অ্যাপ্লিকেশনে, মানে আপনি এক সার্ভিস অবজেক্ট থেকে দশক সার্ভিস অবজেক্টে বড়বেন। কোড অর্গানাইজেশন উন্নত করতে, কমন সার্ভিস অবজেক্টগুলো নেমস্পেসে গ্রুপ করা ভালো প্র্যাকটিস। লাইব্রেরি অ্যাপ্লিকেশনে, উদাহরণস্বরূপ, আমরা সকল বুক-রিলেটেড সার্ভিস একসাথে গ্রুপ করব এবং সকল অথর-রিলেটেড সার্ভিস আলাদা নেমস্পেসে। আমাদের ফোল্ডার স্ট্রাকচার এখন এমন দেখাবে:

services ├── application_service.rb └── book ├── book_creator.rb └── book_reader.rb 

আমাদের সার্ভিস অবজেক্টগুলো এখন এমন দেখাবে:

# services/book/book_creator.rb module Book class BookCreator < ApplicationService ... end end 
# services/twitter_manager/book_reader.rb module Book class BookReader < ApplicationService ... end end 

আমাদের কলগুলো এখন হবে Book::BookCreator.call(*args) and Book::BookReader.call(*args)।

প্রতি সার্ভিস অবজেক্ট এক দায়িত্ব

একটি সার্ভিস অবজেক্ট যেটি একের অধিক জিনিস করে সেটি "বিজনেস অ্যাকশন" মাইন্ডসেটের বিপরীত যায়। কনভেনশনালি, একটি জেনেরিক সার্ভিস অবজেক্ট যেটি একাধিক অ্যাকশন পারফর্ম করে সেটি ডিসকরেজ করা হয়। যদি আপনি সার্ভিস অবজেক্টগুলোর মধ্যে কোড শেয়ার করতে চান, একটি বেস বা হেল্পার মডিউল তৈরি করুন এবং মিক্সিন ব্যবহার করে আপনার সার্ভিস অবজেক্টে ইনক্লুড করুন।

এক্সেপশন রেসকিউ করুন এবং কাস্টম এক্সেপশন রেইজ করুন

একটি সার্ভিস অবজেক্টের উদ্দেশ্য হলো বাস্তবায়নের ডিটেইল এনক্যাপসুলেট করা তার ভেতরে, যেমন থার্ড-পার্টি সার্ভিস বা লাইব্রেরির সাথে ইন্টারঅ্যাকশন বা রেইলস ActiveRecord-এ ডেটাবেস ম্যানিপুলেশন। যদি কোনো এরর হয়, যেমন ActiveRecord::RecordNotUnique, ActiveRecord-এর সাথে ইন্টারঅ্যাক্ট করার সময়, সার্ভিসটিকে এক্সেপশন সঠিকভাবে রেসকিউ করতে হবে। এররগুলকে কল স্ট্যাকে উপরে প্রোপেগেট হওয়া দেয়া উচিত নয়। যদি সেটি রেসকিউ ব্লকে হ্যান্ডেল করা না যায়, সার্ভিস অবজেক্টের জন্য স্পেসিফিক একটি কাস্টম-ডিফাইনড এক্সেপশন রেইজ করুন।

উপসংহার

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

  1. Apache JMeter দিয়ে রেইলস অ্যাপ ইফেক্টিভলি লোড টেস্ট করা

  2. ডকারে আপনার রেইলস অ্যাপ সহজে টেস্ট করুন: ধাপে ধাপে গাইড

  3. Angular এবং Rails 5 ইন্টিগ্রেশন: একটি স্মুথ ফুল-স্ট্যাক পদ্ধতি

  4. অবজেক্ট রিকগনিশন আবিষ্কার করুন: আপনার ফোন ক্যামেরাকে স্মার্ট আইডেন্টিফায়ার বানান এমন টপ অ্যাপস