অ্যাপ্লিকেশন বা ডোমেন পরিষেবাতে ডিডিডি সংগ্রহস্থল


29

আমি আজকাল ডিডিডি নিয়ে অধ্যয়ন করছি এবং ডিডিডি দিয়ে কীভাবে সংগ্রহস্থল পরিচালনা করবেন সে সম্পর্কে আমার কিছু প্রশ্ন রয়েছে।

আসলে, আমি দুটি সম্ভাব্য ব্যক্তির সাথে দেখা করেছি:

প্রথমটি

আমি যে পরিষেবাগুলি পড়েছি তা পরিচালনা করার প্রথম উপায় হ'ল একটি অ্যাপ্লিকেশন পরিষেবাতে একটি সংগ্রহস্থল এবং একটি ডোমেন মডেল ইনজেকশন করা।

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

এটি করার একটি সহজ উপায় হ'ল:

class ApplicationService{

  constructor(domainService, repository){
    this.domainService = domainService
    this.repository = repository
  }

  postAction(data){
    if(this.domainService.validateRules(data)){
      this.repository.persist(new Entity(data.name, data.surname))
    }
    // ...
  }

}

দ্বিতীয়

দ্বিতীয় সম্ভাবনাটি হ'ল পরিবর্তে ডোমেন সার্ভিসের অভ্যন্তরে সংগ্রহস্থল ইনজেকশন করা এবং কেবলমাত্র ডোমেন পরিষেবাদির মাধ্যমে সংগ্রহস্থল ব্যবহার করা:

class ApplicationService{

  constructor(domainService){
    this.domainService = domainService
  }

  postAction(data){
    if(this.domainService.persist(data)){
      console.log('all is good')
    }
    // ...
  }

}

class DomainService{

  constructor(repository){
    this.repository = repository
  }

  persist(data){
    if(this.validateRules(data)){
      this.repository.save(new Entity(data.name))
    }
  }

  validateRules(data){
    // returns a rule matching
  }

}

এখন থেকে, আমি কোনটি সেরা (কোনও যদি সেরা থাকে) বা তারা উভয়কেই তাদের প্রসঙ্গে বোঝায় তা পার্থক্য করতে পারছি না।

আপনি কি আমাকে উদাহরণ প্রদান করতে পারেন যেখানে একজনের চেয়ে অপরটির চেয়ে ভাল হতে পারে এবং কেন?



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

উত্তর:


31

সংক্ষিপ্ত উত্তরটি হ'ল - আপনি কোনও অ্যাপ্লিকেশন পরিষেবা বা একটি ডোমেন পরিষেবা থেকে সংগ্রহস্থলগুলি ব্যবহার করতে পারেন - তবে কেন এবং কীভাবে আপনি এটি করছেন তা বিবেচনা করা গুরুত্বপূর্ণ।

একটি ডোমেন পরিষেবার উদ্দেশ্য

ডোমেন পরিষেবাদিগুলিতে ডোমেন ধারণাগুলি / লজিককে সজ্জিত করা উচিত - যেমন ডোমেন পরিষেবা পদ্ধতি:

domainService.persist(data)

কোনও ডোমেন পরিষেবায় অন্তর্ভুক্ত নয়, কারণ persistএটি সর্বব্যাপী ভাষার অংশ নয় এবং অধ্যবসায় পরিচালন ডোমেন ব্যবসায় যুক্তির অংশ নয়।

সাধারণত যখন আপনার ব্যবসায়িক বিধি / যুক্তি থাকে তবে একাধিক সামগ্রিকের সাথে সমন্বয় বা কাজ করার প্রয়োজন হয় তখন ডোমেন পরিষেবাগুলি কার্যকর হয় are যদি যুক্তিটি কেবল একটি সমষ্টিগতভাবে জড়িত থাকে তবে তা সেই সামগ্রিক সত্তার কোনও পদ্ধতিতে হওয়া উচিত।

অ্যাপ্লিকেশন পরিষেবাগুলিতে সংগ্রহস্থল ories

সুতরাং সেই অর্থে, উদাহরণস্বরূপ, আমি আপনার প্রথম বিকল্পটি পছন্দ করি - তবে উন্নতির জন্য এখানে আরও জায়গা রয়েছে, কারণ আপনার ডোমেন পরিষেবাটি এপিআই থেকে কাঁচা ডেটা গ্রহণ করছে - কেন ডোমেন পরিষেবাটি কাঠামোর সম্পর্কে জানতে হবে data? তদ্ব্যতীত, ডেটা কেবলমাত্র একক সামগ্রীর সাথে সম্পর্কিত বলে মনে হয়, সুতরাং এর জন্য একটি ডোমেন পরিষেবা ব্যবহার করার ক্ষেত্রে সীমিত মূল্য রয়েছে - সাধারণত আমি সত্তা নির্মাতার ভিতরে বৈধতা রাখি। যেমন

postAction(data){

  Entity entity = new Entity(data.name, data.surname);

  this.repository.persist(entity);

  // ...
}

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

ডোমেন পরিষেবাগুলিতে সংগ্রহস্থল it

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

postAction(data){

  this.domainService.doSomeBusinessProcess(data.name, data.surname, data.otherAggregateId);

  // ...
}

ডোমেন পরিষেবা বাস্তবায়নের মত দেখতে হবে:

doSomeBusinessProcess(name, surname, otherAggregateId) {

  OtherEntity otherEntity = this.otherEntityRepository.get(otherAggregateId);

  Entity entity = this.entityFactory.create(name, surname);

  int calculationResult = this.someCalculationMethod(entity, otherEntity);

  entity.applyCalculationResultWithBusinessMeaningfulName(calculationResult);

  this.entityRepository.add(entity);

}

উপসংহার

এখানে মূল কথাটি হ'ল ডোমেন পরিষেবা এমন একটি প্রক্রিয়া encapsulates যা সর্বব্যাপী ভাষার অংশ। এর ভূমিকাটি সম্পাদন করার জন্য, এটি সংগ্রহস্থলগুলি ব্যবহার করা দরকার - এবং এটি করা পুরোপুরি ঠিক।

তবে একটি ডোমেন পরিষেবা যুক্ত করা যা একটি পদ্ধতির সাহায্যে একটি সংগ্রহস্থল persistগুটিয়ে রাখে তাতে খুব কম মান যুক্ত হয়।

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


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

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

ঠিক আছে আমি এখন কেন ভ্যালু অবজেক্টটি ব্যবহার করব তা দেখছি। তবে এর অর্থ হল যে মান অবজেক্টটি এমন একটি সম্পত্তি ণী যা ব্যবসায়ের নিয়ম বিন্যাস পরিচালনা করে?
এমফ্রেচেট

1
মান অবজেক্টগুলি পরিবর্তনযোগ্য হওয়া উচিত। সাধারণত এর অর্থ আপনি কনস্ট্রাক্টরকে আরম্ভ এবং বৈধতা দিন, এবং কোনও বৈশিষ্ট্যের জন্য পাবলিক গেট / প্রাইভেট সেট প্যাটার্ন ব্যবহার করুন। তবে আপনি সাম্যতা, টোস্ট্রিং প্রক্রিয়া ইত্যাদির জন্য ভাষা নির্মাণগুলি ব্যবহার করতে পারেন যেমন kacper.gunia.me/ddd-building-blocks-in-php-value-object বা github.com/spring-projects/spring-gemfire-exferences/ ব্লব / মাস্টার /…
ক্রিস সাইমন

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

2

গৃহীত উত্তর নিয়ে সমস্যা রয়েছে:

ডোমেন মডেলটিকে সংগ্রহশালার উপর নির্ভর করতে দেওয়া হয় না এবং ডোমেন পরিষেবাটি ডোমেন মডেলের অংশ -> ডোমেন পরিষেবাটি সংগ্রহস্থলের উপর নির্ভর করা উচিত নয়।

পরিবর্তে আপনার যা করা উচিত তা হ'ল ইতিমধ্যে অ্যাপ্লিকেশন পরিষেবাতে ব্যবসায়িক যুক্তি সম্পাদনের জন্য প্রয়োজনীয় আপনার সমস্ত সত্ত্বাকে একত্রিত করা এবং তারপরে কেবলমাত্র আপনার মডেলগুলিকে তাত্ক্ষণিকৃত বস্তু সরবরাহ করুন।

আপনার উদাহরণের ভিত্তিতে এটি দেখতে এরকম হতে পারে:

class ApplicationService{

  constructor(domainService, repository){
    this.domainService = domainService
    this.repositoryA = repositoryA
    this.repositoryB = repositoryB
    this.repositoryC = repositoryC
  }

  // any parsing and/or pre-business validation already happened in controller or whoever is a caller
  executeUserStory(data){
    const entityA = this.repositoryA.get(data.criterionForEntityA)
    const entityB = this.repositoryB.get(data.criterionForEntityB)

    if(this.domainService.validateSomeBusinessRules(entityA, entityB)){
      this.repositoryC.persist(new EntityC(entityA.name, entityB.surname))
    }
    // ...
  }
}

সুতরাং, থাম্বের নিয়ম: ডোমেন মডেল বাইরের স্তরগুলির উপর নির্ভর করে না

অ্যাপ্লিকেশন বনাম ডোমেন পরিষেবা এই নিবন্ধ থেকে :

  • ডোমেন পরিষেবাদিগুলি খুব দানাদার যেখানে অ্যাপ্লিকেশন পরিষেবাদি একটি এপিআই সরবরাহ করার উদ্দেশ্যে তৈরি একটি মুখোমুখি।

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

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

  • অ্যাপ্লিকেশন পরিষেবাগুলি ডোমেন লজিক কার্যকর করতে প্রয়োজনীয় অবকাঠামোগত পরিষেবার উপর নির্ভরতা ঘোষণা করে।


1

আপনার পরিষেবাদি এবং অবজেক্টগুলি কিছু কিছু সুসংগত দায়িত্ব সংযুক্ত না করে আপনার প্যাটার্নগুলির কোনওটিই ভাল নয়।

সবার আগে আপনার ডোমেন অবজেক্টটি কী তা বলুন এবং এটি ডোমেন ভাষার ভিতরে কী করতে পারে তা নিয়ে কথা বলুন। যদি এটি বৈধ বা অবৈধ হতে পারে তবে কেন এটি ডোমেন অবজেক্টের সম্পত্তি হিসাবে নেই?

উদাহরণস্বরূপ, যদি বস্তুর বৈধতা কেবলমাত্র অন্য কোনও অবজেক্টের বিবেচনায় আসে তবে সম্ভবত আপনার একটি দায়বদ্ধতা রয়েছে 'ডোমেন অবজেক্টের জন্য বৈধতা বিধি এক্স' যা পরিষেবাদির সেটগুলিতে আবশ্যক can

কোনও জিনিসকে বৈধতা দেওয়ার জন্য কি এটি আপনার ব্যবসায়ের বিধিগুলির মধ্যে সংরক্ষণের প্রয়োজন? সম্ভবত না. 'স্টোরিং অবজেক্টস' দায়বদ্ধতা সাধারণত একটি পৃথক সংগ্রহস্থল অবজেক্টে যায়।

এখন আপনার একটি ক্রিয়াকলাপ সম্পাদন করতে চান যা বিভিন্ন দায়বদ্ধতার অন্তর্ভুক্ত করে, একটি অবজেক্ট তৈরি করে, এটি কার্যকর করে এবং যদি বৈধ হয় তবে এটি সংরক্ষণ করে।

এই অপারেশনটি কি ডোমেন অবজেক্টের অভ্যন্তরীণ? তারপরে এটিকে object বস্তুর অংশ হিসাবে তৈরি করুনExamQuestion.Answer(string answer)

এটি আপনার ডোমেনের অন্য কোনও অংশের সাথে খাপ খায়? এটা ওখানে রাখোBasket.Purchase(Order order)

আপনি কি বরং ADM REST পরিষেবাগুলি করবেন? ঠিক আছে তাহলে।

Controller.Post(json) 
{ 
    parse(json); 
    verify(parsedStruct); 
    save(parsedStruct); 
    return 400;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.