Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

सेवा वस्तुओं के साथ अपने रेल ऐप को फिर से तैयार करना

एक सेवा वस्तु एक रूबी वस्तु है जो एक ही क्रिया करती है। यह आपके डोमेन या व्यावसायिक तर्क में एक प्रक्रिया को समाहित करता है। कल्पना कीजिए कि आपको एक काल्पनिक पुस्तकालय अनुप्रयोग में एक पुस्तक उदाहरण बनाने की आवश्यकता है; एक सादे रेल ऐप में, आप निम्न कार्य करेंगे:

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 (जैसे, मॉडल, नियंत्रक, विचार और सहायक) संगठनात्मक संरचना का समर्थन करने के लिए डिज़ाइन किया गया है। यह संरचना सरल अनुप्रयोगों के लिए पर्याप्त है। हालाँकि, जैसे-जैसे आपका एप्लिकेशन बढ़ता है, आप मॉडल और नियंत्रक में डोमेन/व्यावसायिक तर्क देखना शुरू कर सकते हैं। इस तरह के तर्क न तो नियंत्रक या मॉडल से संबंधित होते हैं, इसलिए वे कोड को फिर से उपयोग करने और बनाए रखने में मुश्किल बनाते हैं। रेल सेवा ऑब्जेक्ट एक ऐसा पैटर्न है जो आपको व्यावसायिक तर्क को नियंत्रकों और मॉडलों से अलग करने में मदद कर सकता है, जिससे मॉडल को केवल डेटा स्तर और आपके एपीआई के नियंत्रक प्रवेश बिंदु के रूप में सक्षम किया जा सकता है।

जब हम व्यावसायिक तर्क को समाहित करने के लिए सेवाओं की शुरुआत करते हैं, तो हमें बहुत सारे लाभ मिलते हैं, जिनमें निम्न शामिल हैं:

  • लीन रेल नियंत्रक - नियंत्रक केवल अनुरोधों को समझने और अनुरोध पैरामीटर, सत्र और कुकीज़ को तर्कों में बदलने के लिए ज़िम्मेदार है जो सेवा ऑब्जेक्ट में कार्य करने के लिए पारित किए जाते हैं। नियंत्रक तब सेवा प्रतिक्रिया के अनुसार पुनर्निर्देशित या प्रस्तुत करता है। बड़े अनुप्रयोगों में भी, सेवा वस्तुओं का उपयोग करने वाली नियंत्रक क्रियाएं आमतौर पर कोड की 10 पंक्तियों से अधिक नहीं होती हैं।

  • परीक्षण योग्य नियंत्रक - चूंकि नियंत्रक दुबले होते हैं और सेवा के सहयोगी के रूप में काम करते हैं, इसलिए इसका परीक्षण करना वास्तव में आसान हो जाता है, क्योंकि हम केवल यह जांच सकते हैं कि जब कोई निश्चित क्रिया होती है तो नियंत्रक के भीतर कुछ विधियों को कॉल किया जाता है या नहीं।

  • व्यावसायिक प्रक्रिया का अलग-अलग परीक्षण करने की क्षमता - सेवाओं का परीक्षण करना आसान और तेज़ है क्योंकि वे छोटी रूबी वस्तुएं हैं जिन्हें उनके पर्यावरण से अलग कर दिया गया है। हम सभी सहयोगियों को आसानी से रोक सकते हैं और केवल यह जांच सकते हैं कि हमारी सेवा में कुछ कदम उठाए गए हैं या नहीं।

  • पुन:प्रयोज्य सेवाएं - सेवा वस्तुओं को नियंत्रकों, अन्य सेवा वस्तुओं, कतारबद्ध नौकरियों आदि द्वारा बुलाया जा सकता है।

  • ढांचे और व्यावसायिक डोमेन के बीच अलगाव - रेल नियंत्रक केवल सेवाओं को देखते हैं और उनका उपयोग करके डोमेन ऑब्जेक्ट के साथ इंटरैक्ट करते हैं। युग्मन में यह कमी स्केलेबिलिटी को आसान बनाती है, खासकर जब आप एक मोनोलिथ से एक माइक्रोसर्विस में जाना चाहते हैं। आपकी सेवाओं को आसानी से निकाला जा सकता है और न्यूनतम संशोधन के साथ एक नई सेवा में स्थानांतरित किया जा सकता है।

सेवा ऑब्जेक्ट बनाना

सबसे पहले, आइए एक नए फोल्डर में एक नया BookCreator बनाएँ, जिसे एक काल्पनिक लाइब्रेरी प्रबंधन एप्लिकेशन के लिए ऐप/सेवाएँ कहा जाता है:

$ 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 (डोंट रिपीट योरसेल्फ) रखने के लिए और अन्य सेवा वस्तुओं के साथ इस व्यवहार का पुन:उपयोग करने के लिए, हम 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 Gem का उपयोग करके सेवा ऑब्जेक्ट बनाना

BusinessProcess रत्न के साथ, आपको एक मूल अनुप्रयोग सेवा वर्ग बनाने या initialize को परिभाषित करने की आवश्यकता नहीं है विधि क्योंकि मणि में इन सभी विन्यासों को बनाया गया है। आपकी सेवा वस्तु को केवल BusinessProcess::Base . से इनहेरिट करना है ।

अपनी रत्न फ़ाइल में, निम्नलिखित जोड़ें:

gem 'business_process'

और फिर bundleचलाएं अपने टर्मिनल में कमांड करें

class BookCreator < BusinessProcess::Base
  # Specify requirements
  needs :title
  needs :description
   needs :author_id
    needs :genre_id

  # Specify process (action)
  def call
    create_book
  end

   private

  def create_book
    # ...
  end
end

गुड सर्विस ऑब्जेक्ट बनाने के लिए गाइड

एक सार्वजनिक तरीका

एक सेवा वस्तु को एक व्यावसायिक क्रिया करने और इसे अच्छी तरह से करने के लिए माना जाता है, इसलिए उसे ऐसा करने के लिए केवल एक ही सार्वजनिक विधि का खुलासा करना चाहिए। अन्य विधियां निजी होनी चाहिए और सार्वजनिक विधि द्वारा बुलाई जानी चाहिए। आप जो चाहें सार्वजनिक पद्धति का नाम चुन सकते हैं, जब तक कि नामकरण सभी सेवा वस्तुओं के अनुरूप हो। हमारे उदाहरण में, हमने इसे call . नाम दिया है . अन्य पारंपरिक नाम हैं perform और execute

सेवा ऑब्जेक्ट को उनकी भूमिका के अनुसार नाम दें

सर्विस ऑब्जेक्ट का नाम इंगित करना चाहिए कि यह क्या करता है। "या" और "एर" के साथ समाप्त होने वाले शब्दों के साथ सेवा वस्तुओं का नामकरण करने का एक लोकप्रिय तरीका है। उदाहरण के लिए, यदि सेवा वस्तु का कार्य पुस्तक बनाना है, तो उसे BookCreator नाम दें, और यदि कार्य किसी पुस्तक को पढ़ना है, तो उसे BookReader नाम दें।

सेवा वस्तुओं को सीधे न करें

सेवा वस्तुओं को कॉल करने के संकेतन को छोटा करने के लिए सिंटैक्टिक चीनी पैटर्न या बिजनेसप्रोसेस जैसे रत्नों का उपयोग करें। इस दृष्टिकोण का उपयोग करने से आप 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) हो जाएंगी। ।

प्रति सेवा वस्तु के लिए एक जिम्मेदारी

एक सेवा वस्तु का होना जो एक से अधिक कार्य करता है, सेवा वस्तुओं की "व्यावसायिक क्रिया" मानसिकता के विरुद्ध जाता है। परंपरागत रूप से, एक सामान्य सेवा वस्तु जो कई क्रियाएं करती है, को हतोत्साहित किया जाता है। यदि आप सेवा वस्तुओं के बीच कोड साझा करना चाहते हैं, तो आधार या सहायक मॉड्यूल बनाएं और अपनी सेवा वस्तुओं में शामिल करने के लिए मिक्सिन का उपयोग करें।

बचाव अपवाद और कस्टम अपवाद बढ़ाएँ

सर्विस ऑब्जेक्ट का उद्देश्य इसके अंदर कार्यान्वयन विवरण को समाहित करना है, जैसे कि तृतीय-पक्ष सेवाओं या पुस्तकालयों के बीच बातचीत या Rails ActiveRecord के साथ डेटाबेस हेरफेर। यदि कोई त्रुटि होती है, जैसे ActiveRecord::RecordNotUnique, ActiveRecord के साथ इंटरैक्ट करते समय, सेवा को अपवाद को ठीक से बचाने की आवश्यकता होती है। कॉल स्टैक को प्रचारित करने के लिए त्रुटियों की अनुमति नहीं दी जानी चाहिए। अगर इसे रेस्क्यू ब्लॉक में हैंडल नहीं किया जा सकता है, तो उस सर्विस ऑब्जेक्ट के लिए विशिष्ट कस्टम-डिफ़ाइंड अपवाद उठाएँ।

निष्कर्ष

जब आप अपने एप्लिकेशन में नई सुविधाएँ जोड़ते हैं तो सर्विस ऑब्जेक्ट पैटर्न आपके एप्लिकेशन के समग्र डिज़ाइन में बहुत सुधार कर सकता है। यह आपके कोडबेस को अधिक अभिव्यंजक, बनाए रखने में आसान और परीक्षण के लिए कम दर्दनाक बना देगा।


  1. अपने रेल ऐप का परीक्षण करने के लिए एक डॉकर कंटेनर सेट करें

    रूबी/रेल डेवलपर्स के रूप में, हम परीक्षण लिखना पसंद करते हैं। परीक्षण सॉफ्टवेयर विकास का एक अभिन्न अंग है। अच्छे परीक्षण हमें उच्च-गुणवत्ता वाला कोड लिखने में मदद करते हैं। वे समग्र विकास प्रक्रिया में मूल्य जोड़ते हैं, लेकिन अगर हम परीक्षण को अच्छी तरह से प्रबंधित नहीं करते हैं, तो वे हमें धीमा कर

  1. रेल के साथ कोणीय का उपयोग करना 5

    आपने पहले कहानी सुनी है। आपके पास पहले से ही आपके विकेन्द्रीकृत और पूरी तरह से काम कर रहे बैक-एंड एपीआई और किसी भी सामान्य टूलसेट से बने फ्रंट-एंड पर चलने वाला एक एप्लिकेशन है। अब, आप कोणीय पर आगे बढ़ना चाहते हैं। या, शायद आप अपनी रेल परियोजनाओं के साथ एंगुलर को एकीकृत करने का एक तरीका ढूंढ रहे हैं

  1. इन ऐप्स का उपयोग करके अपने कैमरे से वस्तुओं की पहचान करें

    कैमरे वाला स्मार्टफोन तस्वीरें क्लिक करने का पारंपरिक घटक नहीं रह गया है। इसका उपयोग बहुत अधिक आकर्षक करने के लिए किया जाता है जैसे कि छवियों को रोचक बनाने के लिए AR स्टिकर का उपयोग करना . एक तस्वीर क्लिक करने के लिए चेहरे और इशारों को पहचानने के लिए कैमरे का उपयोग किया जा सकता है। इसी तरह, अब आप अप