সত্তা পদ্ধতি কলগুলিতে ডিডিডি ইনজেকশন পরিষেবাদি


11

প্রশ্নের সংক্ষিপ্ত বিন্যাস

সত্তা পদ্ধতি কলগুলিতে পরিষেবাগুলি ইনজেক্ট করা কি ডিডিডি এবং ওওপির সেরা অনুশীলনের মধ্যে রয়েছে?

দীর্ঘ ফর্ম্যাট উদাহরণ

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

ধরুন আমরা আমাদের অ্যাপ্লিকেশনটিতে অনর্গল সিনট্যাক্স চাই, যাতে আমরা এরকম কিছু করতে পারি (লাইন ২-তে বাক্য গঠনটি লক্ষ করছি, যেখানে আমরা getLineItemsপদ্ধতিটি বলি ):

$order = $orderService->getOrderByID($orderID);
foreach($order->getLineItems($orderService) as $lineItem) {
  ...
}

আমরা অর্ডারইটিটিতে কোনও ধরণের লাইনআইটেমিপোজিটরি ইনজেকশন করতে চাই না, কারণ এটি আমি ভাবতে পারি এমন কয়েকটি নীতির লঙ্ঘন। তবে, সিনট্যাক্সের সাবলীলতা এমন কিছু যা আমরা সত্যই চাই, কারণ এটি পড়া এবং বজায় রাখা সহজ, পাশাপাশি পরীক্ষাও।

নিম্নলিখিত কোড বিবেচনা করুন, পদ্ধতি লক্ষ getLineItemsমধ্যে OrderEntity:

interface IOrderService {
    public function getOrderByID($orderID) : OrderEntity;
    public function getLineItems(OrderEntity $orderEntity) : LineItemCollection;
}

class OrderService implements IOrderService {
    private $orderRepository;
    private $lineItemRepository;

    public function __construct(IOrderRepository $orderRepository, ILineItemRepository $lineItemRepository) {
        $this->orderRepository = $orderRepository;
        $this->lineItemRepository = $lineItemRepository;
    }

    public function getOrderByID($orderID) : OrderEntity {
        return $this->orderRepository->getByID($orderID);
    }

    public function getLineItems(OrderEntity $orderEntity) : LineItemCollection {
        return $this->lineItemRepository->getLineItemsByOrderID($orderEntity->ID());
    }
}

class OrderEntity {
    private $ID;
    private $lineItems;

    public function getLineItems(IOrderServiceInternal $orderService) {
        if(!is_null($this->lineItems)) {
            $this->lineItems = $orderService->getLineItems($this);
        }
        return $this->lineItems;
    }
}

এটি কি ডিডিডি এবং ওওপির মূল নীতি লঙ্ঘন না করে সত্তাগুলিতে সাবলীল সিনট্যাক্স প্রয়োগের গ্রহণযোগ্য উপায়? আমার কাছে এটি দুর্দান্ত বলে মনে হচ্ছে, যেমন আমরা কেবল পরিষেবা স্তরটিই প্রকাশ করছি, পরিকাঠামো স্তরটি নয় (এটি পরিষেবাতে বাসা বাঁধার)

উত্তর:


9

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

class Invoice
{
    private $currency;
    private $customerId;

    public function __construct()
    {
    }

    public function sum(InvoiceCalculator $calculator)
    {
        $sum =
            new SumRecord(
                $calculator->calculate($this)
            )
        ;

        if ($sum->isZero()) {
            $this->events->add(new ZeroSumCalculated());
        }

        return $sum;
    }
}

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

আমি যদি নিজের একটি ডোমেইন সেবা ব্যবহার খুঁজে, সম্ভবত এর মানে হল যে আমি কিছু ডোমেইন ধারণা মিস যেহেতু আমি আমার ধারণা মডেল: তৃতীয় পদ্ধতির আমি পক্ষে নই হয় বিশেষ্য সঙ্গে প্রাথমিকভাবে , ক্রিয়া না। সুতরাং, আদর্শভাবে, আমি একটি ডোমেন সেবা প্রয়োজন হবে না এ সব এবং আমার সকল ব্যবসা যুক্তিবিজ্ঞান বসবাস তা থেকে উপকার লাভ টেকনিক


6

আমি এখানে কিছু উত্তর পড়ে হতবাক।

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

যা ভুল তা হ'ল এটির নির্মাণকারীর মাধ্যমে সামগ্রিকভাবে পরিষেবাগুলি ইনজেক্ট করা। তবে একটি ব্যবসায়ের পদ্ধতির মাধ্যমে এটি ঠিক এবং পুরোপুরি স্বাভাবিক।


1
আপনি যে কেসটি দিয়েছেন তা কেন কোনও ডোমেন পরিষেবার দায়িত্বে থাকবে না?
ই_আই_পি

1
এটি একটি ডোমেন পরিষেবা, তবে এটি ব্যবসায়ের পদ্ধতিতে সংক্রামিত। অ্যাপ্লিকেশন স্তরটি কেবল একটি অর্কেস্ট্রেটার,
ডায়গোসাসউ

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

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

5

সত্তা পদ্ধতি কলগুলিতে পরিষেবাগুলি ইনজেক্ট করা কি ডিডিডি এবং ওওপির সেরা অনুশীলনের মধ্যে রয়েছে?

না, আপনার ডোমেন স্তরের অভ্যন্তরে কোনও কিছুই ইনজেক্ট করা উচিত নয় (এতে সত্তা, মান বস্তু, কারখানা এবং ডোমেন পরিষেবা অন্তর্ভুক্ত রয়েছে)। এই স্তরটি কোনও কাঠামো, তৃতীয় পক্ষের লাইব্রেরি বা প্রযুক্তির অজ্ঞেয় হওয়া উচিত এবং কোনও আইও কল করা উচিত নয়।

$order->getLineItems($orderService)

এটি ভুল যেহেতু সমষ্টিটিকে অর্ডার আইটেমগুলি ফিরিয়ে আনার জন্য নিজের ছাড়া আর কিছুই প্রয়োজন হয় না। দ্যসমগ্র মোট ইতিমধ্যে তার পদ্ধতি কল করার আগে লোড করা উচিত নয়। আপনি যদি মনে করেন যে এটি অলস বোঝা হওয়া উচিত তবে দুটি সম্ভাবনা রয়েছে:

  1. আপনার সমষ্টিগুলির সীমানা ভুল, সেগুলি খুব বড়।

  2. এই ব্যবহারের ক্ষেত্রে আপনি কেবলমাত্র পড়ার জন্য সমষ্টিটি ব্যবহার করেন। সবচেয়ে ভাল সমাধান হ'ল লেখার মডেলটি পড়ার মডেল থেকে বিভক্ত করা (অর্থাত সিকিউআরএস ব্যবহার করুন )। এই ক্লিনার আর্কিটেকচারে আপনাকে সমষ্টিকে জিজ্ঞাসা করার অনুমতি দেওয়া হয়নি তবে একটি পঠিত মডেল।


যদি আমার বৈধতার জন্য ডেটাবেস কল প্রয়োজন হয়, আমাকে এপ্লিকেশন পরিষেবাতে কল করতে হবে এবং একটি ফলাফল ডোমেন পরিষেবাতে বা সরাসরি সামগ্রিক মূলের মধ্যে দিয়ে যেতে হবে তবে ডোমেন পরিষেবাতে সংগ্রহস্থল ইনজেকশন করতে হবে?
মুফ্লিক্স 20'19

1
@ মুফ্লিক্স হ্যাঁ, এটি ঠিক
কনস্টান্টিন গালবেনু

3

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

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

রিটার্নিং মান সমষ্টিগত মধ্যে থেকে জরিমানা, কারণ মান মজ্জাগতভাবে অপরিবর্তনীয় হয়; আপনি আমার অনুলিপি এর অনুলিপি পরিবর্তন করে পরিবর্তন করতে পারবেন না।

একটি যুক্তি হিসাবে একটি ডোমেন পরিষেবা ব্যবহার করা, সঠিক মান প্রদানের সামগ্রিকভাবে সহায়তা করা, একদম যুক্তিযুক্ত জিনিস।

সামগ্রীর অভ্যন্তরে থাকা ডেটাতে অ্যাক্সেস সরবরাহ করতে আপনি সাধারণত কোনও ডোমেন পরিষেবা ব্যবহার করবেন না, কারণ সামগ্রিকভাবে ইতিমধ্যে এটিতে অ্যাক্সেস থাকা উচিত।

$order = $orderService->getOrderByID($orderID);
foreach($order->getLineItems($orderService) as $lineItem) {
  ...
}

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

$order = $orderService->getOrderByID($orderID);
foreach($order->getLineItems() as $lineItem) {
  ...
}

অবশ্যই, এটি প্রাক-অনুমান করে যে লাইন আইটেমগুলি ইতিমধ্যে লোড করা হয়েছে।

সাধারণ প্যাটার্নটি হ'ল সমষ্টিগুলির বোঝা নির্দিষ্ট ব্যবহারের ক্ষেত্রে প্রয়োজনীয় সমস্ত রাজ্যের অন্তর্ভুক্ত করবে। অন্য কথায়, আপনার কাছে একই সমষ্টি লোড করার বিভিন্ন উপায় থাকতে পারে ; আপনার সংগ্রহস্থল পদ্ধতিগুলি কাজের জন্য উপযুক্ত

এই পদ্ধতির এমন কিছু নয় যা আপনি আসল ইভান্সটিতে পাবেন, যেখানে তিনি ধরে নিয়েছিলেন যে একটি সামগ্রিকের সাথে এটির সাথে একক ডেটা মডেল যুক্ত রয়েছে। এটি সিক্যুআরএস থেকে বেশি স্বাভাবিকভাবেই পড়ে।


এর জন্য ধন্যবাদ. আমি এখন "লাল বই" এর প্রায় অর্ধেকটি পড়েছি এবং অবকাঠামো স্তরে হলিউডের মূলনীতিটি সঠিকভাবে প্রয়োগ করার আমার প্রথম স্বাদ পেয়েছি। এই উত্তরগুলির সমস্ত পুনরায় পড়া, তারা সকলেই ভাল পয়েন্ট দেয় তবে আমার মনে হয় আপনার lineItems()সমষ্টিগত রুটের প্রথম পুনরুদ্ধারের উপর স্কোপ এবং প্রিলোডিং সম্পর্কিত কিছু গুরুত্বপূর্ণ পয়েন্ট রয়েছে ।
e_i_pi

3

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

সম্পর্কিত, অর্ডাররেপোসিটরির অবকাঠামোগত বাস্তবায়ন, ওআরএমের ক্ষেত্রে এটি একের মধ্যে একাধিক সম্পর্ক এবং আপনি অর্ডারলাইনটি আগ্রহী বা অলস লোডটি নির্বাচন করতে পারেন।

আমি নিশ্চিত না যে আপনার পরিষেবাগুলি ঠিক কী বোঝায়। এটি "অ্যাপ্লিকেশন পরিষেবা" এর একেবারে কাছাকাছি। যদি এটি হয় তবে সাধারণত সমষ্টিগত রুট / সত্তা / মান অবজেক্টে পরিষেবাগুলি ইনজেক্ট করা ভাল ধারণা নয়। অ্যাপ্লিকেশন পরিষেবাটি সমষ্টিগত রুট / সত্তা / মান বস্তু এবং ডোমেন পরিষেবার ক্লায়েন্ট হওয়া উচিত। আপনার পরিষেবাদি সম্পর্কে অন্য একটি বিষয় হ'ল অ্যাপ্লিকেশন পরিষেবাতে মান অবজেক্টগুলি প্রকাশ করা ভাল ধারণাও নয়। এগুলি সামগ্রিক মূল দ্বারা অ্যাক্সেস করা উচিত।


2

উত্তরটি হ'ল: অবশ্যই না, সত্তা পদ্ধতিতে পরিষেবাগুলি পাস করা এড়িয়ে চলুন।

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

বিস্তৃত নীতিটি হ'ল: কার্যকরী বিটগুলি (যেমন ডোমেন লজিক) অ-কার্যকরী বিট থেকে পৃথক রাখুন (যেমন, অধ্যবসায়)।

আরও একটি জিনিস: আপনি যদি পারেন তবে এটি না করার চেষ্টা করুন:

$order = $orderService->getOrderByID($orderID);
foreach($order->getLineItems() as $lineItem) {
  ...
}

পরিবর্তে এটি করুন

$order = $orderService->getOrderByID($orderID);
$order->doSomethingSignificant();

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.