এইভাবে আমি এই কোডটি লিখছি তা পরীক্ষামূলক, তবে এটির সাথে আমি কী অনুপস্থিত রয়েছি তাতে কিছু ভুল আছে?


13

আমার কাছে একটি ইন্টারফেস রয়েছে IContext। এর উদ্দেশ্যগুলির জন্য এটি নীচে ব্যতীত এটি যা করে তা সত্যিই আসে না:

T GetService<T>();

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

আমার এএসপি.এনইটি এমভিসি অ্যাপ্লিকেশনটিতে, আমার নির্মাতাকে এটির মতো দেখাচ্ছে।

protected MyControllerBase(IContext ctx)
{
    TheContext = ctx;
    SomeService = ctx.GetService<ISomeService>();
    AnotherService = ctx.GetService<IAnotherService>();
}

সুতরাং প্রতিটি পরিষেবার জন্য কনস্ট্রাক্টরে একাধিক পরামিতি যুক্ত করার পরিবর্তে (কারণ এটি বিকাশকারীদের অ্যাপ্লিকেশনটি প্রসারিত করার জন্য সত্যই বিরক্তিকর এবং সময় সাপেক্ষ হবে) আমি পরিষেবাগুলি পেতে এই পদ্ধতিটি ব্যবহার করছি।

এখন, এটি ভুল মনে হচ্ছে । যাইহোক, আমি বর্তমানে এটি আমার মাথায় যেভাবে ন্যায়সঙ্গত করছি তা হ'ল - আমি এটি উপহাস করতে পারি

আমি পারি. IContextকন্ট্রোলার পরীক্ষা করার জন্য উপহাস করা কঠিন হবে না । আমার যাই হোক:

public class MyMockContext : IContext
{
    public T GetService<T>()
    {
        if (typeof(T) == typeof(ISomeService))
        {
            // return another mock, or concrete etc etc
        }

        // etc etc
    }
}

তবে আমি যেমন বলেছি, এটি ভুল বলে মনে হচ্ছে। কোন চিন্তা / আপত্তিজনক স্বাগত।


8
এটিকে সার্ভিস লোকেটার বলা হয় এবং এটি আমার পছন্দ হয় না। বিষয়টিতে প্রচুর লেখালেখি হয়েছে - একটি স্টার্টারের জন্য martinfowler.com/articles/inication.html এবং blog.ploeh.dk/2010/02/03/S सर्विस LocatorisanAnti- প্যাটার্ন দেখুন ।
বেনিয়ামিন হজসন

মার্টিন ফোলার নিবন্ধ থেকে: "আমি প্রায়শই অভিযোগ শুনেছি যে এই ধরণের পরিষেবা লোকেটার একটি খারাপ জিনিস কারণ তারা পরীক্ষার জন্য পরীক্ষামূলক নয় কারণ আপনি তাদের জন্য বাস্তবায়নের বিকল্প দিতে পারবেন না। অবশ্যই আপনি এগুলিতে প্রবেশের জন্য এগুলি খারাপভাবে ডিজাইন করতে পারেন এক ধরণের ঝামেলা, তবে আপনার দরকার নেই this এক্ষেত্রে পরিষেবাটি লোকেটার উদাহরণটি কেবল একটি সাধারণ ডেটা ধারক I আমি আমার পরিষেবাদির পরীক্ষার প্রয়োগগুলি সহ সহজেই লোকেটারটি তৈরি করতে পারি "" আপনি কেন এটি পছন্দ করেন না তা ব্যাখ্যা করতে পারেন? একটি উত্তরে হতে পারে?
লিভারপুলস

8
তিনি ঠিক বলেছেন, এটি খারাপ নকশা। এটা সহজ: public SomeClass(Context c)। এই কোডটি বেশ পরিষ্কার, তাই না? এটিতে বলা আছে, that SomeClassক এর উপর নির্ভর করে Context। এরর, কিন্তু অপেক্ষা করুন, এটি না! এটি কেবল Xপ্রসঙ্গ থেকে প্রাপ্ত নির্ভরতার উপর নির্ভর করে । এর মানে হল যে, প্রত্যেক সময় আপনাকে পরিবর্তন করতে Contextএটা পারে বিরতি SomeObject, যদিও আপনি শুধুমাত্র পরিবর্তিত Contextগুলি Y। তবে হ্যাঁ, আপনি জানেন যে আপনি কেবল পরিবর্তন করেন Yনি X, তাই SomeClassঠিক। তবে ভাল কোড লেখার বিষয়টি আপনি যা জানেন তা নয় তবে নতুন কর্মী যখন প্রথমবার আপনার কোডটি দেখবে তখন কী জানে about
ভ্যালেনটারি

@ ডকব্রাউন আমার কাছে ঠিক সেটাই বলেছিল - আমি এখানে পার্থক্য দেখছি না। আপনি আরও ব্যাখ্যা করতে পারেন?
ভ্যালেন্টারি

1
@ ডকব্রাউন আমি এখন আপনার পয়েন্টটি দেখছি। হ্যাঁ, যদি তার প্রসঙ্গটি সমস্ত নির্ভরতার কেবল একটি বান্ডিল হয়, তবে এটি খারাপ নকশা নয়। এটি যদিও নামকরণ খারাপ হতে পারে তবে এটি কেবল একটি অনুমানও। প্রসঙ্গের আরও পদ্ধতি (অভ্যন্তরীণ বস্তু) রয়েছে কিনা ওপি স্পষ্ট করে দিতে হবে। এছাড়াও কোডটি নিয়ে আলোচনা করা ঠিক আছে তবে এটি প্রোগ্রামার্স st স্ট্যাকেক্সচেঞ্জইন আমার কাছে আমাদেরও ওপিটির উন্নতি করার জন্য "পিছনে" জিনিসগুলি দেখার চেষ্টা করা উচিত।
ভ্যালেন্টারি

উত্তর:


5

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

আপনার প্রথম উদাহরণে পরিবর্তিত হতে পারে

protected MyControllerBase(IContext ctx)
{
    TheContext = ctx;
    SomeService = ctx.GetSomeService();
    AnotherService = ctx.GetAnotherService();
}

এটির যথেষ্ট নকশা পরিবর্তন হবে না MyControllerBase। এই নকশাটি ভাল বা খারাপ যদি নির্ভর করতে পারে তবে তা নির্ভর করে

  • নিশ্চিত করুন TheContext, SomeServiceএবং AnotherServiceসবসময় সব উপহাস বস্তুর সঙ্গে সক্রিয়া, অথবা তাদের সব বাস্তব বস্তুর সঙ্গে
  • বা, 3 টি অবজেক্টের বিভিন্ন সংমিশ্রণে তাদের আরম্ভের অনুমতি দেওয়ার জন্য (যার অর্থ এই ক্ষেত্রে আপনার পৃথকভাবে পরামিতিগুলি পাস করতে হবে)

সুতরাং কনস্ট্রাক্টরে 3 এর পরিবর্তে কেবলমাত্র একটি প্যারামিটার ব্যবহার করা সম্পূর্ণ যুক্তিসঙ্গত হতে পারে।

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

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


আমি এটার সাথে একমত. উদাহরণ সহ সমস্যাটি হল জেনেরিক GetServiceপদ্ধতি। সুস্পষ্টভাবে নামকরণ এবং টাইপ করা পদ্ধতিতে রিফ্যাক্টরিং আরও ভাল। IContextকনস্ট্রাক্টরে স্পষ্টভাবে বাস্তবায়নের নির্ভরতাগুলি স্পেল করা আরও ভাল ।
বেনিয়ামিন হজসন

1
@ বেঞ্জামিনহডসন: এটি কখনও কখনও ভাল হতে পারে তবে এটি সবসময় ভাল হয় না । কোডার প্যারামিটারের তালিকাটি দীর্ঘ এবং দীর্ঘতর হয়ে গেলে আপনি কোডের গন্ধ নোট করুন। আমার প্রাক্তন উত্তরটি এখানে দেখুন: প্রোগ্রামারস.স্ট্যাকেক্সেঞ্জার.কম
ডক ব্রাউন

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

... মনে রাখবেন যে "কোড গন্ধ" যেমন কনস্ট্রাক্টর ওভার-ইনজেকশন নিজেই সমস্যা নয় is এটি কেবল একটি ইঙ্গিত যে
কোডটিতে

মাইক্রোসফ্ট এটিকে বেক করার সময় আপনি কোথায় ছিলেন IValidatableObject?
রাবারডাক

15

এই নকশাটি সার্ভিস লোকেটার * নামে পরিচিত এবং আমি এটি পছন্দ করি না। এর বিরুদ্ধে প্রচুর যুক্তি রয়েছে:

পরিষেবা লোকেটার আপনাকে আপনার ধারকটিতে কাপল করে । নিয়মিত নির্ভরতা ইনজেকশন ব্যবহার করে (যেখানে newনির্মাতারা স্পষ্টভাবে নির্ভরশীলতার উচ্চারণ করে ) আপনি সরাসরি আপনার ধারকটিকে আলাদা আলাদা করে প্রতিস্থাপন করতে পারেন, বা এক্সপ্রেসনে ফিরে যেতে পারেন। আপনার সাথে IContextএটি সত্যই সম্ভব নয়।

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

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

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

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

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

* আমি জেনেরিক Resolve<T>পদ্ধতিতে একটি পরিষেবা হিসাবে সার্ভিস লোকেটারকে সংজ্ঞায়িত করছি যা স্বেচ্ছাসেবী নির্ভরতাগুলি সমাধান করতে সক্ষম এবং কোডবেজ জুড়ে ব্যবহৃত হয় (কেবলমাত্র কম্পোজিশন রুটে নয়)। এটি সার্ভিস ফেক্যাডের মতো নয় (একটি অবজেক্ট যা কিছু ছোট ছোট পরিচিত নির্ভরতা বান্ডিল করে) বা অ্যাবস্ট্রাক্ট ফ্যাক্টরি (এমন একটি জিনিস যা একক ধরণের উদাহরণ তৈরি করে - একটি অ্যাবস্ট্রাক্ট ফ্যাক্টরির ধরণ জেনেরিক হতে পারে তবে পদ্ধতিটি নয়) ।


1
আপনি পরিষেবা লোকেটার প্যাটার্ন সম্পর্কে অভিযোগ করছেন (যার সাথে আমি সম্মত)। তবে প্রকৃতপক্ষে, ওপি-র উদাহরণে, MyControllerBaseকোনও নির্দিষ্ট ডিআই কন্টেইনারে নয়, সার্ভিস লোকেটার বিরোধী-প্যাটার্নের জন্য এটি "সত্যই" উদাহরণ নয়।
ডক ব্রাউন

@ ডকব্রাউন আমি সম্মত এটি আমার জীবনকে সহজ করে না বলে নয়, তবে উপরে বর্ণিত বেশিরভাগ উদাহরণগুলি আমার কোডের সাথে প্রাসঙ্গিক নয়।
লিভারপুলস

2
আমার কাছে, সার্ভিস লোকেটার অ্যান্টি-প্যাটার্নের হলমার্ক হল সাধারণ GetService<T>পদ্ধতি। ইচ্ছামত নির্ভরতা সমাধানের আসল গন্ধ, যা ওপির উদাহরণে উপস্থিত এবং সঠিক।
বেনজমিন হজসন

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

1
@ ডকব্রাউন GetService<T>()পদ্ধতিটি স্বেচ্ছাসেবী শ্রেণিকে অনুরোধ করার অনুমতি দেয়: "এই পদ্ধতিটি যা করে তা প্রয়োগের বর্তমান ডিআই কনটেইনারের দিকে দৃষ্টিপাত করে এবং নির্ভরতা সমাধানের চেষ্টা করে Fair আমি মনে করি মোটামুটি আদর্শ।" । আমি এই উত্তরের শীর্ষে আপনার মন্তব্যের জবাব দিচ্ছিলাম। এটি 100% একটি পরিষেবা লোকেটার
এলেক্সফক্সগিল

5

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

ঠিক আছে তাই প্রশ্নের উত্তর দিতে - আসুন আপনার আসল সমস্যাটি আবার বলি :

সুতরাং প্রতিটি পরিষেবার জন্য কনস্ট্রাক্টরে একাধিক পরামিতি যুক্ত করার পরিবর্তে (কারণ এটি বিকাশকারীদের অ্যাপ্লিকেশনটি প্রসারিত করার ক্ষেত্রে সত্যই বিরক্তিকর এবং সময় সাপেক্ষ হবে) আমি পরিষেবাগুলি পেতে এই পদ্ধতিটি ব্যবহার করছি।

স্ট্যাক ওভারফ্লোতে এই সমস্যাটিকে সম্বোধন করে এমন একটি প্রশ্ন রয়েছে । সেখানে একটি মন্তব্যে যেমন উল্লেখ করা হয়েছে:

সর্বোত্তম মন্তব্য: "কনস্ট্রাক্টর ইঞ্জেকশনের একটি দুর্দান্ত সুবিধা হ'ল এটি একক দায়িত্বের নীতি লঙ্ঘনকে অত্যন্ত স্পষ্ট করে তোলে" "

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

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

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

আরও সঠিক রায় দেওয়ার জন্য এটি আপনার ব্যবহারের কেসটি জানতে সত্যই সহায়তা করবে, তবে সত্যই আমি এমন কোনও দৃশ্যের কথা ভাবতে পারি না যেখানে বেস ক্লাসটি ভাল-নির্ভরশীল নির্ভরতার চেয়ে বেশি পছন্দ করে।


+1 - এটি এমন একটি নতুন প্রশ্ন যা অন্য উত্তরগুলির কোনও উত্তরই সত্যই দেয় নি
বেনজমিন হডসন

1
"কনস্ট্রাক্টর ইনজেকশনের একটি দুর্দান্ত সুবিধা হ'ল এটি একক দায়িত্বের নীতি লঙ্ঘন করে যে এটি স্পষ্টভাবে" ভালোবাসা। সত্যিই ভাল উত্তর। এটির সাথে একমত হবেন না। আমার ব্যবহারের ক্ষেত্রে যথেষ্ট মজাদার, এমন কোনও সিস্টেমে কোড নকল করার দরকার নেই যেটিতে 100 টিরও বেশি নিয়ামক থাকবে (কমপক্ষে)। তবে পুনরায় এসআরপি - প্রতিটি ইনজেকশনের পরিষেবাদির একটি একক দায়িত্ব রয়েছে, নিয়ামক হিসাবে যা সেগুলি ব্যবহার করে - একজন কীভাবে এটি প্রতিহত করবে ??
লিভারপুলস

1
@ লিভারপুলস নম্বার 9 বেস-কন্ট্রোলার থেকে কার্যকারিতাটিকে নির্ভরতার মধ্যে সরিয়ে নিয়ে যাওয়া কীটি আপনার অবধি protectedনতুন উপাদানগুলিতে ওয়ান-লাইনারের প্রতিনিধি ব্যতীত বেসকন্ট্রোলারে আর কিছু অবশিষ্ট থাকে না । তারপরে আপনি বেসকন্ট্রোলারকে হারাতে পারেন এবং protectedনির্ভর করে সরাসরি কলগুলির সাথে সেই পদ্ধতিগুলি প্রতিস্থাপন করতে পারেন - এটি আপনার মডেলকে সহজ করবে এবং আপনার সমস্ত নির্ভরতা সুস্পষ্ট করে তুলবে (যা 100s কন্ট্রোলার সহ একটি প্রকল্পে খুব ভাল জিনিস!)
অ্যালেক্সফক্সগিল

@ লিভারপুলস নম্বার - আপনি যদি আপনার বেসকন্ট্রোলারের একটি অংশ একটি পেস্টবিনে অনুলিপি করতে পারতেন তবে আমি কিছু
কড়া

-2

আমি প্রত্যেকের অবদানের ভিত্তিতে এটিতে একটি উত্তর যুক্ত করছি। অনেক ধন্যবাদ সর্বদা। প্রথমে এখানে আমার উত্তর: "না, এটিতে কোনও ভুল নেই"।

ডক ব্রাউন এর "পরিষেবা মুখোমুখি" উত্তর আমি এই উত্তরটি গ্রহণ করেছি কারণ আমি যা খুঁজছিলাম (যদি উত্তরটি "না" ছিল) তবে আমি যা করছি তার কিছু উদাহরণ বা কিছু বিস্তৃতি ছিল। তিনি এ পরামর্শ দিয়েছিলেন যে ক) এটির একটি নাম পেয়েছে, এবং খ) সম্ভবত এটি করার আরও ভাল উপায় আছে।

বেনিয়ামিন হজসনের "সার্ভিস লোকেটার" উত্তরটি আমি এখানে যে জ্ঞান অর্জন করেছি তার যতটুকু প্রশংসা করি, আমার কাছে যা আছে তা কোনও "সার্ভিস লোকেটার" নয়। এটি একটি "পরিষেবা মুখোমুখি"। এই উত্তরের সমস্ত কিছুই সঠিক তবে আমার পরিস্থিতির জন্য নয়।

ইউএসআর এর উত্তর

আমি এটিকে আরও বিশদে সমাধান করব:

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

আমি কোনও সরঞ্জামাদি হারাব না এবং আমি কোনও "স্ট্যাটিক" টাইপিং হারাচ্ছি না। পরিষেবা মুখোমুখি আমার ডিআই কনটেইনারে যা আমি কনফিগার করেছি তা ফিরিয়ে দেবে, বা default(T)। এবং এটি কী ফিরে আসে তা "টাইপড"। প্রতিচ্ছবি encapsulated হয়।

কনস্ট্রাক্টর আর্গুমেন্ট হিসাবে অতিরিক্ত পরিষেবা যুক্ত করা কেন একটি বড় বোঝা আমি তা দেখতে পাচ্ছি না।

এটি অবশ্যই "বিরল" নয়। যেহেতু আমি বেস কন্ট্রোলারটি ব্যবহার করছি , প্রতিবার যখনই আমি এটির নির্মাতা পরিবর্তন করতে হবে তখন আমাকে 10, 100, 1000 অন্যান্য নিয়ামক পরিবর্তন করতে হতে পারে।

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

আমি নির্ভরতা ইনজেকশন ব্যবহার করছি। এটাই আসল কথা.

এবং অবশেষে, বেনিয়ামিনের উত্তর সম্পর্কে জুলসের মন্তব্য আমি কোনও নমনীয়তা হারাচ্ছি না। এটা আমার পরিষেবা সম্মুখ। আমি GetService<T>বিভিন্ন বাস্তবায়নের মধ্যে পার্থক্য করতে চাই যতগুলি পরামিতি যুক্ত করতে পারি, যেমন একটি ডিআই কনটেইনারটি কনফিগার করার সময় কেউ করত। সুতরাং উদাহরণস্বরূপ, আমি এই "সম্ভাব্য সমস্যা" কাছাকাছি পেতে পরিবর্তন GetService<T>()করতে GetService<T>(string extraInfo = null)পারে।


যাইহোক, আবার সবাইকে ধন্যবাদ। এটা সত্যিই দরকারী হয়েছে। চিয়ার্স।


4
আমি একমত নই যে আপনার এখানে একটি পরিষেবা মুখোমুখি আছে। GetService<T>()পদ্ধতি (প্রয়াস করা) সমাধান করতে সক্ষম হয় নির্বিচারে নির্ভরতা । আমি আমার উত্তরের পাদটীকাতে যেমন ব্যাখ্যা করেছি এটি এটি একটি পরিষেবা মুখোমুখি নয় , পরিষেবা লোকেটার হিসাবে তৈরি করে। আপনি যদি @ ডকব্রাউন এর পরামর্শ অনুসারে এটি GetServiceX()/ GetServiceY()পদ্ধতিগুলির একটি ছোট সেট দিয়ে প্রতিস্থাপন করতে থাকেন তবে এটি ফেকড হবে।
বেনিয়ামিন হডসন

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

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

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

2
@ লিভারপুলস নাম্বার 9 ভুল: আপনার পরীক্ষাগুলি এখন একটি তৈরি করতে হবে IContextএবং এটি ইনজেক্ট করতে হবে এবং অত্যন্ত গুরুত্বপূর্ণ: আপনি যদি নতুন নির্ভরতা যুক্ত করেন তবে কোডটি এখনও
সংকলিত
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.