ব্যবসায়ের যুক্তিটিকে পরিষেবা স্তরে না নিয়ে ডোমেন অবজেক্টের বৈশিষ্ট্যে অনন্য প্রতিবন্ধকতাগুলি পরীক্ষা করার কি দুর্দান্ত উপায় আছে?


10

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

২০১৩ সালের সেপ্টেম্বরে মার্টিন ফোলার টেলডোনটঅ্যাস্ক নীতিটি উল্লেখ করেছিলেন , যা সম্ভব হলে সমস্ত ডোমেন অবজেক্টে প্রয়োগ করা উচিত, যা একটি বার্তা ফেরত পাঠানো উচিত, কীভাবে অপারেশনটি চলেছিল (অবজেক্ট-ওরিয়েন্টেড ডিজাইনে এটি বেশিরভাগ ব্যতিক্রমের মধ্য দিয়ে করা হয়, যখন অপারেশন ব্যর্থ হয়েছিল)।

আমার প্রকল্পগুলি সাধারণত অনেকগুলি ভাগে বিভক্ত হয়, যেখানে তাদের দুটি ডোমেন (ব্যবসায়িক বিধি এবং অন্য কিছুই থাকে না, ডোমেনটি সম্পূর্ণ অধ্যবসায়-অজ্ঞ)। পরিষেবাগুলি CRUD ডেটাতে ব্যবহৃত রেপোজিটরি স্তর সম্পর্কে জানত।

যেহেতু কোনও সামগ্রীর সাথে সম্পর্কিত কোনও গুণাবলীর স্বতন্ত্রতা একটি ডোমেন / ব্যবসায়িক নিয়ম, এটি ডোমেন মডিউল থেকে দীর্ঘ হওয়া উচিত, সুতরাং নিয়মটি যেখানে এটি হওয়ার কথা ঠিক ঠিক সেখানেই হয়।

রেকর্ডের স্বতন্ত্রতা পরীক্ষা করতে সক্ষম হওয়ার জন্য, আপনাকে বর্তমান ডেটাসেট, সাধারণত একটি ডাটাবেস, জিজ্ঞাসা করতে হবে, এটির জন্য একটি রেকর্ড Nameইতিমধ্যে উপস্থিত রয়েছে কিনা তা খুঁজে বের করতে হবে ।

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

আমি তখন নকশাটি খাপ খাইয়েছি এমন দেখায়:

class ProductRepository
{
    // throws Repository.RecordNotFoundException
    public Product GetBySKU(string sku);
}

class ProductCrudService
{
    private ProductRepository pr;

    public ProductCrudService(ProductRepository repository)
    {
        pr = repository;
    }

    public void SaveProduct(Domain.Product product)
    {
        try {
            pr.GetBySKU(product.SKU);

            throw Service.ProductWithSKUAlreadyExistsException("msg");
        } catch (Repository.RecordNotFoundException e) {
            // suppress/log exception
        }

        pr.MarkFresh(product);
        pr.ProcessChanges();
    }
}

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

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

সুস্পষ্ট সমাধান হ'ল Domain.ProductCollectionএকটি Add(Domain.Product)পদ্ধতি নিক্ষেপ করে একটি ক্লাস তৈরি করা ProductWithSKUAlreadyExistsException, তবে এটির কার্যকারিতা অনেকটাই অভাব, কারণ কোডের সন্ধানের জন্য আপনার সমস্ত পণ্য ডেটা স্টোরেজ থেকে সংগ্রহ করতে হবে, কোনও পণ্য ইতিমধ্যে একই এসকিউ রয়েছে কিনা তা খুঁজে বের করতে হবে would আপনি যে পণ্যটি যুক্ত করার চেষ্টা করছেন তা হিসাবে।

আপনি ছেলেরা কীভাবে এই নির্দিষ্ট সমস্যাটি সমাধান করবেন? এটি সত্যিই প্রতি সমস্যা নয়, আমার কয়েক বছরের জন্য পরিষেবা স্তরটি ডোমেনের কিছু নিয়মের প্রতিনিধিত্ব করেছে। পরিষেবা স্তরটি সাধারণত আরও জটিল ডোমেন ক্রিয়াকলাপ পরিবেশন করে, আমি কেবল ভাবছি যে আপনি আপনার ক্যারিয়ারের সময় আরও ভাল, আরও কেন্দ্রীভূত, সমাধানের উপর ঝাঁপিয়ে পড়েছেন কিনা।


আপনি যখন কেবল একটিটির জন্য জিজ্ঞাসা করতে পারেন এবং সন্ধান পাওয়া গেছে কি না তার উপর যুক্তিটি বজায় রাখতে পারবেন কেন নামের একটি সম্পূর্ণ তালিকা টানবেন? ইন্টারফেসের সাথে একটি চুক্তি রয়েছে, আপনি কী করবেন এবং কীভাবে করবেন না তা দৃ the়তা স্তরকে বলছেন।
JeffO

1
পরিষেবা শব্দটি ব্যবহার করার সময়, আমাদের আরও স্বচ্ছতার দিকে মনোনিবেশ করা উচিত, যেমন ডোমেন স্তরের ডোমেন পরিষেবাদি এবং অ্যাপ্লিকেশন স্তরের অ্যাপ্লিকেশন পরিষেবাগুলির মধ্যে পার্থক্য। Gorodinski.com/blog/2012/04/14/…
এরিক

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

"বলুন, জিজ্ঞাসা করবেন না" রেফারেন্সের একটি উদ্ধৃতি: "তবে ব্যক্তিগতভাবে আমি টেল-ডন্ট-টু জিজ্ঞাসা করি না।"
রাডারবাব

উত্তর:


7

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

আমি এই অংশের সাথে একমত হবে না। বিশেষত শেষ বাক্য।

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

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

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


ইনপুট দেওয়ার জন্য আপনাকে ধন্যবাদ। Domain.ProductCollectionডোমেন স্তর থেকে বস্তু পুনরুদ্ধারের জন্য তারা দায়বদ্ধ বলে বিবেচনা করে বাস্তবে আমার মনে যে রিপোজিটরিটি ছিল তা প্রতিনিধিত্ব করতে পারে?
অ্যান্ডি

@ ডেভিডপ্যাকার আপনার অর্থ কী তা আমি সত্যিই বুঝতে পারি না। কারণ সমস্ত জিনিস স্মৃতিতে রাখার দরকার নেই should "DoNameExist" পদ্ধতির বাস্তবায়ন ডেটা স্টোর সাইডে (সম্ভবত সম্ভবত) এসকিউএল কোয়েরি হওয়া উচিত।
ইউফোরিক

এর অর্থ হ'ল মেমরির কোনও সংকলনে ডেটা সংরক্ষণ করার পরিবর্তে, যখন আমি সমস্ত পণ্য জানতে চাই Domain.ProductCollectionতবে আমার কাছে সেগুলি নেওয়ার দরকার নেই, তবে পরিবর্তে সংগ্রহশালাটি জিজ্ঞাসা করা উচিত, জিজ্ঞাসার সাথে একই, Domain.ProductCollectionএটিতে কোনও পণ্য রয়েছে কিনা এবার এসকিউ পাস করে আবারও, এর পরিবর্তে সংগ্রহস্থল জিজ্ঞাসা করলেন (এটি আসলে উদাহরণ), যা পূর্ব-লোড পণ্যগুলি পুনরুক্ত করার পরিবর্তে অন্তর্নিহিত ডাটাবেস অনুসন্ধান করে। আমি না চাইলে সমস্ত পণ্য স্মৃতিতে সঞ্চয় করতে চাই না, এটি করা সম্পূর্ণ বাজে কথা।
অ্যান্ডি

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

@ ডেভিডপ্যাকার ওয়েল, "ডোমেন জ্ঞান" ইন্টারফেসে রয়েছে। ইন্টারফেসটি বলে যে "ডোমেনটির এই কার্যকারিতা প্রয়োজন" এবং ডেটা স্টোর সেই কার্যকারিতা সরবরাহ করে। আপনার যদি IProductRepositoryইন্টারফেস থাকে DoesNameExistতবে পদ্ধতিটি কী করা উচিত তা স্পষ্ট। তবে বিদ্যমান পণ্যটির নামের সাথে পণ্যটির একই নাম না থাকা নিশ্চিত করে কোথাও কোথাও ডোমেনে থাকা উচিত।
ইউফোরিক

4

সেট বৈধকরণের জন্য আপনাকে গ্রেগ ইয়ং পড়তে হবে ।

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

"স্বতন্ত্রতা" প্রয়োজনীয়তাগুলির সাথে সমস্যাটি হ'ল, বেশিরভাগ ক্ষেত্রেই লোকেরা তাদের চাওয়ার আরও গভীর অন্তর্নিহিত কারণ রয়েছে - ইয়ভেস রেইনহাউট

দীর্ঘ উত্তর: আমি সম্ভাবনার একটি মেনু দেখেছি, তবে তাদের সকলেরই বাণিজ্য রয়েছে।

ডোমেনে কমান্ড প্রেরণের আগে আপনি সদৃশগুলি পরীক্ষা করতে পারেন। এটি ক্লায়েন্টে বা পরিষেবাতে করা যেতে পারে (আপনার উদাহরণটি কৌশলটি দেখায়)। আপনি যদি ডোমেন স্তরটি থেকে যুক্তি বের হওয়ার বিষয়ে সন্তুষ্ট না হন তবে আপনি এ এর ​​সাথে একই ধরণের ফলাফল অর্জন করতে পারেন DomainService

class Product {
    void register(SKU sku, DuplicationService skuLookup) {
        if (skuLookup.isKnownSku(sku) {
            throw ProductWithSKUAlreadyExistsException(...)
        }
        ...
    }
}

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

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

আপনি আপনার ডোমেনে একটি পৃথক সমষ্টি তৈরি করতে পারেন যা জ্ঞাত স্কাসের সেট উপস্থাপন করে। আমি এখানে দুটি প্রকরণের কথা ভাবতে পারি।

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

একটি বিকল্প হ'ল স্কু রিজার্ভেশন সার্ভিসের মতো আরও কিছু। মৌলিক প্রক্রিয়াটি একই: একটি সামগ্রিক স্কাসের সমস্ত সম্পর্কে জানে, সুতরাং নকলগুলির প্রবর্তনকে আটকাতে পারে। তবে প্রক্রিয়াটি কিছুটা পৃথক: আপনি কোনও পণ্যকে বরাদ্দের আগে কোনও স্কুতে ইজারা অর্জন করেন; পণ্য তৈরি করার সময়, আপনি এটি স্কুকে ইজারা দিয়ে দেন pass প্লেতে এখনও একটি রেসের শর্ত রয়েছে (বিভিন্ন সমষ্টি, অতএব স্বতন্ত্র লেনদেন), তবে এটির মধ্যে আলাদা স্বাদ পেল। এখানে আসল খারাপ দিকটি হ'ল আপনি ডোমেন মডেলটিতে ডোমেনের ভাষায় কোনও যৌক্তিকতা ছাড়াই একটি ইজারা পরিষেবা প্রজেক্ট করছেন।

আপনি সমস্ত পণ্য সত্তাকে একটি একক সামগ্রীতে টানতে পারেন - অর্থাত, উপরে বর্ণিত পণ্য ক্যাটালগ। আপনি যখন এটি করেন তখন আপনি পুরোপুরি স্কুজের স্বাতন্ত্র্য অর্জন করেন, তবে ব্যয় অতিরিক্ত যুক্তিযুক্ত, কোনও পণ্যকে সংশোধন করা মানেই পুরো ক্যাটালগটি সংশোধন করা।

স্মরণে অপারেশন করতে সমস্ত পণ্য এসকিউগুলিকে ডাটাবেসের বাইরে টানতে চাই না।

হয়তো আপনার দরকার নেই। আপনি যদি ব্লুম ফিল্টার দিয়ে আপনার স্কুকে পরীক্ষা করেন তবে সেটটি মোটেও লোড না করে আপনি অনেকগুলি অনন্য স্কু আবিষ্কার করতে পারেন।

যদি আপনার ব্যবহারের কেসটি আপনাকে কোন স্কাসটি প্রত্যাখ্যান করে তা স্বেচ্ছায় থাকতে দেয় তবে আপনি সমস্ত মিথ্যা ধনাত্মক বিষয়টিকে সরিয়ে ফেলতে পারেন (আপনি যদি ক্লায়েন্টদের কমান্ডটি জমা দেওয়ার আগে তাদের প্রস্তাবিত স্কাস পরীক্ষা করার অনুমতি দেন) তবে এটি বড় কথা নয়। এটি আপনাকে মেমরিতে সেট লোড করা এড়াতে দেয়।

(আপনি যদি আরও গ্রহণযোগ্য হতে চান, তবে আপনি ব্লুম ফিল্টারের কোনও ম্যাচ হওয়ার সময় স্কাস লোডিংটি বিবেচনা করতে পারেন; আপনি এখনও কখনও কখনও সমস্ত স্কলকে মেমরিতে লোড করার ঝুঁকি নিতে পারেন, তবে আপনি যদি অনুমতি দেন তবে এটি সাধারণ ক্ষেত্রে হওয়া উচিত নয়) প্রেরণের আগে ত্রুটির জন্য কমান্ডটি পরীক্ষা করতে ক্লায়েন্ট কোড)।


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

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