ডিডিডিতে, সঞ্চিতাগুলি কোনও সত্তা বা ডোমেন অবজেক্টকে প্রকাশ করতে পারে?


11

আমি এটি যেমন বুঝতে পেরেছি, ডিডিডি তে, একটি সামগ্রিক মূল সহ একটি সংগ্রহস্থল প্যাটার্ন ব্যবহার করা উপযুক্ত। আমার প্রশ্ন হ'ল আমি কি কোনও সত্তা বা ডোমেন অবজেক্টস / ডিটিও হিসাবে ডেটা ফিরিয়ে দেব?

হয়তো কিছু কোড আমার প্রশ্নটি আরও ব্যাখ্যা করবে:

সত্তা

public class Customer
{
  public Guid Id { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
}

আমার কি এমন কিছু করা উচিত?

public Customer GetCustomerByName(string name) { /*some code*/ }

নাকি এরকম কিছু?

public class CustomerDTO
{
  public Guid Id { get; set; }
  public FullName { get; set; }
}

public CustomerDTO GetCustomerByName(string name) { /*some code*/ }

অতিরিক্ত প্রশ্ন:

  1. একটি সংগ্রহস্থলে, আমি কি আইকিউয়েরেবল বা আইনিউবারেবল ফিরিয়ে দেব?
  2. একটি পরিষেবা বা সংগ্রহস্থলের, আমি ভালো কিছু করতে হবে .. GetCustomerByLastName, GetCustomerByFirstName, GetCustomerByEmail? বা শুধু এমন একটি পদ্ধতি তৈরি করুন যা এরকম কিছু GetCustomerBy(Func<string, bool> predicate)?

GetCustomerByName('John Smith')আপনার ডাটাবেসে বিশ জন স্মিথ থাকলে কী ফিরে আসবে ? দেখে মনে হচ্ছে আপনি দু'জনের একই নাম নেই বলে ধরে নিচ্ছেন।
বিডিএসএল

উত্তর:


8

আমি কি সত্তা বা ডোমেন অবজেক্টস / ডিটিও হিসাবে ডেটা ফিরিয়ে আনব?

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

যদি এটি হয় তবে আপনার ডোমেন মডেলটি পুনর্বিবেচনা করা উচিত এবং আপনার বড় সত্তাকে সম্পর্কিত ছোট ছোট সত্তায় বিভক্ত করা উচিত।

  1. একটি সংগ্রহস্থলে, আমি কি আইকিউয়েরেবল বা আইনিউবারেবল ফিরিয়ে দেব?

থাম্বের একটি ভাল নিয়ম হ'ল সর্বদা সহজতম (উত্তরাধিকারের স্তরক্রমের সর্বোচ্চ) প্রকারটি ফিরিয়ে দেওয়া। সুতরাং, IEnumerableযদি না আপনি रिपোজিটরি ভোক্তাকে একটি দিয়ে কাজ করতে না চান তবে ফিরে যান IQueryable

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

  1. কোনও পরিষেবা বা সংগ্রহশালায়, আমি কি এমন কিছু করা উচিত .. getCustomerByLastName, GetCustomerByFirstName, GetCustomerByEmail? বা কেবল এমন একটি পদ্ধতি তৈরি করুন যা গেটকাস্টমারবি (ফানক ভবিষ্যদ্বাণী) এর মতো কিছু?

আমি পয়েন্ট 1 এ উল্লিখিত হিসাবে একই কারণে, অবশ্যই ব্যবহার করবেন নাGetCustomerBy(Func<string, bool> predicate) । এটি প্রথমে প্রলুব্ধকর মনে হতে পারে তবে ঠিক এই কারণেই লোকেরা জেনেরিক সংগ্রহগুলি ঘৃণা করতে শিখেছে। এটা ফুটো

এই জাতীয় জিনিসগুলি GetByPredicate(Func<T, bool> predicate)কেবল তখনই কার্যকর যখন সেগুলি কংক্রিট শ্রেণীর পিছনে লুকানো থাকে hidden সুতরাং, যদি আপনার কাছে একটি বিমূর্ত বেস ক্লাস নামে পরিচিত RepositoryBase<T>যা প্রকাশিত হয় protected T GetByPredicate(Func<T, bool> predicate)যা কেবলমাত্র কংক্রিটের সংগ্রহস্থল (যেমন, public class CustomerRepository : RepositoryBase<Customer>) দ্বারা ব্যবহৃত হয় তবে তা ঠিক থাকবে।


সুতরাং আপনার বক্তব্য, ডোমেন স্তরে ডিটিও ক্লাস করা ঠিক আছে?
কোডফিশ

আমি যা বলার চেষ্টা করছিলাম তা নয়। আমি ডিডিডি গুরু নই তাই এটি গ্রহণযোগ্য কিনা তা আমি বলতে পারি না। কৌতূহলের বাইরে আপনি কেন পুরো সত্তা ফিরিয়ে দেননি? এটা কি অনেক বড়?
মেটাফাইট

ওহ আসলে না। আমি কেবল জানতে চাই যে সঠিক এবং গ্রহণযোগ্য জিনিসটি কী। এটি কি কোনও পূর্ণ সত্তা বা এটির কেবল উপসেটটি ফেরত দেবে? আমার ধারণা এটি আপনার উত্তরের উপর নির্ভর করে।
কোডফিশ

6

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

আমি যা দেখেছি তার উপর ভিত্তি করে ...

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

সুতরাং, আপনি যেখানে সামগ্রিক সংশোধন করতে চলেছেন সেই প্রসঙ্গে, আমি সংগ্রহস্থলটি সত্তাটি ফেরৎ প্রত্যাশা করব (উগ্র সমষ্টিগত মূল)।

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

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

আপনার সমস্ত getCustomerByPropertyকল আমার কাছে ক্যোয়ারির মতো দেখায় তাই সেগুলি পরবর্তী বিভাগে চলে আসবে। সংগ্রহটি উত্পন্ন করতে আমি সম্ভবত একটি একক এন্ট্রি পয়েন্ট ব্যবহার করতে চাই, তাই আমি যদি তা সন্ধান করতে চাই

getCustomersThatSatisfy(Specification spec)

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

যদিও কিছু নিদর্শন রয়েছে যা সাহায্য করতে পারে। উদাহরণস্বরূপ, হাত দ্বারা স্পেসিফিকেশন তৈরির পরিবর্তে, সীমাবদ্ধতার একটি বিবরণ সংগ্রহস্থলের নিকট প্রেরণ করুন এবং কী করবেন তা সিদ্ধান্ত নেওয়ার জন্য সংগ্রহস্থলের প্রয়োগের অনুমতি দিন।

সতর্কতা: জাভা টাইপ করার মতো সনাক্ত হয়েছে

interface CustomerRepository {
    interface ConstraintBuilder {
        void setLastName();
        void setFirstName();
    }

    interface ConstraintDescriptor {
        void copyTo(ConstraintBuilder builder);
    }

    List<CustomerProjection> getCustomersThatSatisfy(ConstraintDescriptor descriptor);
}

SQLBackedCustomerRepository implements CustomerRepository {
    List<CustomerProjection> getCustomersThatSatisfy(ConstraintDescriptor descriptor) {
        WhereClauseBuilder builder = new WhereClauseBuilder();
        descriptor.copyTo(builder);
        Query q = createQuery(builder.build());
        //...
     }
}

CollectionBackedCustomerRepository implements CustomerRepository {
    List<CustomerProjection> getCustomersThatSatisfy(ConstraintDescriptor descriptor) {
        PredicateBuilder builder = new PredicateBuilder();
        descriptor.copyTo(builder);
        Predicate p = builder.build();
        // ...
}

class MatchLastName implements CustomerRepository.ConstraintDescriptor {
    private final lastName;
    // ...

    void copyTo(CustomerRepository.ConstraintBuilder builder) {
        builder.setLastName(this.lastName);
    }
}

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


এগুলি সবই দুর্দান্ত এবং ভাল, তবে প্রশ্নকর্তা সিকিউআরএস ব্যবহার করে উল্লেখ করেন না। আপনি ঠিক বলেছেন, তিনি যদি করেন তবে তার সমস্যা অস্তিত্বহীন।
মেটাফাইট

আমি এটি সম্পর্কে শুনেছি সিকিউআরএস সম্পর্কে আমার কোনও জ্ঞান নেই। আমি যেমন এটি বুঝতে পেরেছি, AggregateDTO বা প্রজেকশনডিটিও যদি কী ফিরবে তা ভেবে আমি প্রজেকশনডিটিও ফিরিয়ে দেব। তারপরে getCustomersThatSatisfy(Specification spec)আমি সন্ধান বিকল্পগুলির জন্য আমার প্রয়োজনীয় বৈশিষ্ট্যগুলি তালিকাবদ্ধ করব। আমি ঠিক আছে?
কোডফিশ

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

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

1

আমার ডিডিডি সম্পর্কে আমার জ্ঞানের ভিত্তিতে আপনার এটি হওয়া উচিত,

public CustomerDTO GetCustomerByName(string name) { /*some code*/ }

একটি সংগ্রহস্থলে, আমি কি আইকিউয়েরেবল বা আইনিউবারেবল ফিরিয়ে দেব?

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

সংগ্রহস্থলগুলি কি আইকোয়ারিযোগ্য ফিরে আসতে হবে?

কোনও পরিষেবা বা সংগ্রহশালায়, আমি কি এমন কিছু করা উচিত .. getCustomerByLastName, GetCustomerByFirstName, GetCustomerByEmail? বা কেবল এমন একটি পদ্ধতি তৈরি করুন যা গেটকাস্টমারবি (ফানক ভবিষ্যদ্বাণী) এর মতো কিছু?

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

আপনি সাধারণ সিআরইউডির জন্য জেনেরিক রিপোজিটরি প্যাটার্নটিও ব্যবহার করতে পারেন , যদি আপনি ইতিমধ্যে সচেতন না হন।

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