যদি আধুনিক ওআরএম (ইএফ, এনহাইবারনেট) এর জন্য রেপোজিটরি প্যাটার্নটি ওভারকিল হয় তবে এর থেকে আরও ভাল বিমূর্ততা কী?


12

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

ইউনিট টেস্টিংয়ের মতো পরিস্থিতির জন্য প্যাটার্নটি ব্যবহার করার বিরুদ্ধে আর একটি যুক্তি হ'ল রেপোজিটরি প্যাটার্নটি একটি জোঁক বিমূর্ততা যেহেতু আরও জেনেরিক বাস্তবায়নগুলি আইকুয়েরেবলের উত্স।

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

জিমি বোগার্ডস সমাধানটি অ্যাবস্ট্রাকশনগুলি দূরে ফুটিয়ে তোলার মিশ্রণ বলে মনে হচ্ছে, তবে তার নিজস্ব আর্কিটেকচারও প্রবর্তন করছে। https://lostechies.com/jimmybogard/2012/10/08/favor-query-objects-over-repositories/

অপ্রয়োজনীয় ভান্ডারগুলির আরেকটি উদাহরণ .... তবে আমার আর্কিটেকচারটি ব্যবহার করুন! http://blog.gauffin.org/2012/10/22/griffin-decoupled-the-queries/

আরেকটি ... http://www.thereforprogrammer.net/is-the-repository- Pattern-useful- with- entity- framework

আমি "অত্যধিক জটিল" রিপোজিটরি প্যাটার্ন পদ্ধতির কোনও পরিষ্কার প্রতিস্থাপন বা বিকল্প খুঁজে পাইনি যা নিজে আর আর্কিটেক্ট নয়।


4
আপনি বিশেষত কী অর্জন করার চেষ্টা করছেন? বিমূর্তনের একটি উদ্দেশ্য থাকা উচিত। আপনি যদি CRUD অ্যাপ্লিকেশন লিখছেন তবে একটি ORM সম্ভবত যথেষ্ট বিমূর্ত।
জ্যাকবিবি 18'16

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

রিড Cospey এখানে IQuerable সম্পর্কে বলার ইতিবাচক জিনিস অনেক আছে: stackoverflow.com/questions/1578778/using-iqueryable-with-linq এটি ট্রান্সপোর্ট লেয়ার এ ভালো বোঝা। যতদূর বিমূর্ততা হিসাবে আমি জেনেরিক রিপোজিটরি প্যাটার্নের কাজটি ভালভাবে ব্যবহার করতে পেলাম যখন আমাকে যখন এনটিটিটাইপ ইনজেক্ট করার প্রয়োজন হয়েছিল তবে এখনও সাধারণ পদ্ধতি বজায় রাখতে চেয়েছিলাম। অন্যদিকে, আমি নিজেই এমএসডিএন লিনকিউ ফোরামে যুক্তি দিয়েছি যে ইএফ একটি সংগ্রহস্থল ধরণ কারণ এটি সমস্ত স্মৃতিতে রয়েছে। একটি প্রকল্পে মেথড কল হিসাবে বেশিরভাগ ক্লজ ব্যবহার করা হয়েছে যা ভাল কাজ করেছে।
জন পিটারস 0

তবে একটি ক্ষেত্র যা আমি দেখেছি কিন্তু প্রত্যাখ্যানিত তা হ'ল এক্সপ্রেশন ট্রি ব্যবসায়, কিছু সত্যই এটি পছন্দ করে তবে .... আপনাকে কার্যকর মনে হওয়ার আগে আপনাকে এটিকে কঠোরভাবে অধ্যয়ন করতে হবে।
জন পিটারস 0

2
আমাদের
নিয়ামকগণ

উত্তর:


12

আমি মনে করি আপনি সংগ্রহস্থল এবং জেনেরিক সংগ্রহস্থলগুলি বিভক্ত করছেন।

একটি প্রাথমিক সংগ্রহস্থল কেবল আপনার ডেটা স্টোরকে ইন্টারফেস করে এবং ডেটা ফেরত দেওয়ার পদ্ধতি সরবরাহ করে

IRepository {
   List<Data> GetDataById(string id);
}

এটি আইকুয়ারিযোগ্য বা এলোমেলো প্রশ্নগুলিতে পাস করার অন্যান্য উপায়ে আপনার কোডে ডেটা স্তরটি ফাঁস করে না এবং পদ্ধতিগুলির একটি ভাল সংজ্ঞায়িত টেস্টেবল এবং ইনজেক্টেবল পৃষ্ঠ সরবরাহ করে।

একটি জেনেরিক রিপোজিটরি আপনাকে আপনার কোয়েরিতে একটি ওআরএম এর মতো পাস করতে দেয়

IGenericRepository<T> {
    List<T> Get<T>(IQuery query);
    //or
    IQueryable<T> Get<T>();
}

আমি সম্মত হলাম যে কোনও ওআরএম এর শীর্ষে জেনেরিক রিপোজিটরি ব্যবহার করার মতো খুব বেশি পয়েন্ট নেই যা মূলত অন্য একটি জেনেরিক রিপোজিটরি।

উত্তরটি হ'ল আপনার ওআরএমটি লুকানোর জন্য বেসিক রিপোজিটরি প্যাটার্নটি ব্যবহার করা


1
একটি ORM এর একটি ORM? আমি মজার হওয়ার চেষ্টা করছিলাম। আপনার কেন ORM বিমূর্ত করা দরকার?
জননি

1
একই কারণে আপনি কিছু বিমূর্ত। মালিকানাধীন শ্রেণীর সাথে আপনার কোডকে দূষিত করা এড়াতে
ইভান

6

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

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

একটি সংগ্রহস্থল বাস্তবায়ন যা ফাঁসযুক্ত বিমূর্ততা ( IQueryablesউদাহরণস্বরূপ উন্মোচন করা) হ'ল একটি দুর্বল সংগ্রহস্থল বাস্তবায়ন।

একটি সংগ্রহস্থল বাস্তবায়ন যা কেবল সংগ্রহের ক্রিয়াকলাপের চেয়ে বেশি প্রকাশ করে (উদাহরণস্বরূপ, ওয়ার্কের বৈশিষ্ট্যগুলির ইউনিট) একটি দুর্বল সংগ্রহস্থল বাস্তবায়ন।

ডেটা অ্যাক্সেসের জন্য কি রেপোজিটরির বিকল্প রয়েছে? হ্যাঁ, তবে আপনি আপনার প্রশ্নের উত্থাপিত সমস্যার সাথে এগুলি সম্পর্কিত নয়।



1

আমার কাছে, ওআরএম বা অন্যান্য ডিবি জেদী স্তরগুলির সাথে মিলিত সংগ্রহস্থলগুলির এই অসুবিধাগুলি রয়েছে:

  1. কাজের ইউনিট Coverেকে রাখা ইউওডাব্লুটিকে প্রোগ্রামার দ্বারা কোডিং করতে হয় এবং পটভূমিতে খুব কমই এক ধরণের যাদু হিসাবে প্রয়োগ করা যেতে পারে, যেখানে ব্যবহারকারী কেবল ইউওডাব্লু সীমানা সংজ্ঞায়িত না করে এবং সম্ভবত প্রতিশ্রুতি বিন্দু ব্যতীত প্রশ্ন এবং পরিবর্তন করে makes কখনও কখনও, প্রতিটি সংগ্রহস্থল অ্যাক্সেস পদ্ধতিতে ইউওডাব্লুটিকে মাইক্রো ইউওডাব্লুতে (যেমন এনএইচবারনেট সেশনগুলি) কমিয়ে এড়িয়ে যায়।
  2. আড়ালকরণ বা সবচেয়ে খারাপ ক্ষেত্রে, অধ্যবসায় অজ্ঞতা ধ্বংস: "লোড ()", "পান () (" সংরক্ষণ করুন) "বা" আপডেট () "এর মতো পদ্ধতিগুলি তাত্ক্ষণিক, একক অবজেক্টের ক্রিয়াকলাপের পরামর্শ দেয়, যেন পৃথক প্রেরণ এসকিউএল / ডিএমএল বা ফাইলগুলির সাথে কাজ করার মতো। প্রকৃতপক্ষে, উদাহরণস্বরূপ, এই বিভ্রান্তকারী নামগুলির সাথে এনএইচবারনেট পদ্ধতিগুলি সাধারণত স্বতন্ত্র অ্যাক্সেস করে না, তবে অলস লোড বা সন্নিবেশ / আপডেট ব্যাচের সন্ধান করে (দৃistence়তা অজ্ঞতা)। কখনও কখনও, প্রোগ্রামাররা অবাক করে যে কেন তারা তাত্ক্ষণিকভাবে ডিবি অপারেশনগুলি পাবে না এবং জোর করে জেদীভাবে অজ্ঞতা ছিন্ন করে, ফলে কর্মক্ষমতা হ্রাস করে এবং বাস্তবে সিস্টেমটিকে আরও খারাপ করার জন্য বড় প্রচেষ্টা চালায়।
  3. অনিয়ন্ত্রিত বৃদ্ধি। একটি সাধারণ সংগ্রহস্থল সুনির্দিষ্ট প্রয়োজনের জন্য আরও বেশি করে পদ্ধতি সংগ্রহ করতে পারে।

যেমন:

public interface ICarsRepository  /* initial */
{
    ICar CreateNewCar();
    ICar LoadCar(int id); // bad, should be for multiple IDs.
    void SaveCar(ICar carToSave); // bad, no individual saves, use UoW commit!
}

public interface ICarsRepository  /* a few years later */
{
    ICar CreateNewCar();
    ICar LoadCar(int id); 
    IList<ICar> GetBlueCars();
    IList<ICar> GetRedYellowGreenCars();
    IList<ICar> GetCarsByColor(Color colorOfCars); // a bit better
    IList<ICar> GetCarsByColor(IEnumerable<Color> colorsOfCars); // better!
    IList<ICar> GetCarsWithPowerBetween(int hpFrom, int hpTo);
    IList<ICar> GetCarsWithPowerKwBetween(int kwFrom, int kwTo);
    IList<ICar> GetCarsBuiltBetween(int yearFrom, int yearTo);
    IList<ICar> GetCarsBuiltBetween(DateTime from, DateTime to); // some also need month and day
    IList<ICar> GetHybridCarsBuiltBetween(DateTime from, DateTime to); 
    IList<ICar> GetElectricCarsBuiltBetween(DateTime from, DateTime to); 
    IList<ICar> GetCarsFromManufacturer(IManufacturer carManufacturer); 
    bool HasCarMeanwhileBeenChangedBySomebodyElseInDb(ICar car); // persistence ignorance broken
    void SaveCar(ICar carToSave);
}

৪. Godশ্বরের বিপদ আপত্তি: আপনার মডেল বা ডেটা অ্যাক্সেস লেয়ারের সমস্তটি কভার করে আপনি একটি godশ্বর শ্রেণি তৈরির জন্য প্রলুব্ধ হতে পারেন। সংগ্রহস্থল শ্রেণিতে কেবল গাড়ী পদ্ধতিই থাকবে না তবে সমস্ত সত্তার জন্য পদ্ধতি রয়েছে।

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


4
যদি কেউ সংগ্রহস্থল প্যাটার্ন ব্যবহার না করে তবে এই সমস্ত পদ্ধতিগুলি কোথায় যাবে?
জননি

এখানে @johnny আপনি যান: softwareengineering.stackexchange.com/a/220126/100617
lexeme

1

যদি রিপোজিটরি-ইন্টারফেসের উদ্দেশ্যটি হ'ল এককদ্বীপের জন্য ডাটাবেসটিকে উপহাস করা ((বিচ্ছিন্নতার মধ্যে পরীক্ষা =)) সেরা বিমূর্ততা এমন একটি বিষয় যা উপহাস করা সহজ।

একটি আইপোক্যারেবল ফলাফলের উপর ভিত্তি করে এমন একটি সংগ্রহস্থল ইন্টারফেসটিকে উপহাস করা কঠিন।

ইউনিট-পরীক্ষার দৃষ্টিকোণ থেকে

IRepository {
   List<Data> GetDataById(string id);
}

সহজেই উপহাস করা যায়

IGenericRepository<T> {
    List<T> Get<T>(IQuery query);
}

মক যদি ক্যোয়ারী প্যারামিটারের সামগ্রীটি উপেক্ষা করে তবেই এটি উপহাস করা যায়।

IGenericRepository<T> {
    IQueryable<T> Get<T>(some_parameters);
}

সহজেই উপহাস করা যায় না


0

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

উদাহরণ স্বরূপ:

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        UserRepository ur = new UserRepository();
        var userWithA = ur.GetBy(u => u.Name.StartsWith("A"));

        Console.WriteLine(userWithA.Name);


        ur.GetAllBy(u => u.Name.StartsWith("M"))
          .ForEach(u => Console.WriteLine(u.Name));


        ur.GetAllBy(u => u.Age > 13)
          .ForEach(u => Console.WriteLine(u.Name));
    }
}

public class UserRepository 
{
    List<User> users = new List<User> { 
        new User{Name="Joe", Age=10},
            new User{Name="Allen", Age=12},
            new User{Name="Martin", Age=14},
            new User{Name="Mary", Age=15},
            new User{Name="Ashton", Age=29}
    };

    public User GetBy(Predicate<User> userPredicate)
    {
        return users.Find(userPredicate);
    }

    public List<User> GetAllBy(Predicate<User> userPredicate)
    {
        return users.FindAll(userPredicate);
    }
}

public class User
{
    public string Name { get; set; }

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