আইওসি-র জন্য ইন্টারফেসের পরিবর্তে ফানক ব্যবহার করা হচ্ছে


15

প্রসঙ্গ: আমি সি # ব্যবহার করছি

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

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

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

আরও নির্দিষ্ট ইন্টারফেসের বিপরীতে জেনেরিক প্রতিনিধি / উচ্চতর অর্ডার ফাংশন যেমন আইওসির জন্য ফানক ব্যবহারে কোনও সমস্যা আছে?


2
আপনি যা বর্ণনা করছেন তা হ'ল অর্ডার ফাংশন, ক্রিয়ামূলক প্রোগ্রামিংয়ের
রবার্ট হার্ভে

2
Funcআপনি প্যারামিটারগুলির নাম রাখতে পারার পরিবর্তে আমি একটি প্রতিনিধি ব্যবহার করব , যেখানে আপনি তাদের উদ্দেশ্য বলতে পারেন।
স্টিফান হ্যাঙ্ক

1
সম্পর্কিত: স্ট্যাকওভারফ্লো: আইওসি-কারখানা-পেশাদার-এবং-বিপরীতে-ইন্টারফেস-বনাম-প্রতিনিধিদের । @ চ্যাটহিসার প্রশ্নটি আরও সাধারণ, যখন স্ট্যাকওভারফ্লো প্রশ্নটি বিশেষ কেস "ফ্যাক্টরি"
K3b

উত্তর:


11

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

আমার ধারণা প্রচুর লোক ব্যবহারে বেশি interfacesঅভ্যস্ত, কারণ যে সময় নির্ভরতা ইনজেকশন এবং আইওসি জনপ্রিয় হয়ে উঠছিল, তখন Funcজাভা বা সি ++ এর শ্রেণীর সাথে কোনও সমতুল্য সমতুল্য ছিল না (আমি তখনও নিশ্চিত নই Funcযে সি # তে সেই সময় উপলব্ধ ছিল কিনা? )। সুতরাং প্রচুর টিউটোরিয়াল, উদাহরণ বা পাঠ্যপুস্তক এখনও interfaceফর্ম পছন্দ করে , এমনকি যদি ব্যবহার Funcকরা আরও মার্জিত হয়।

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

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


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

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

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

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

9

আইওসির সাথে আমি যে প্রধান সুবিধাগুলি পাই তাগুলির মধ্যে একটি হ'ল এটি আমার সমস্ত নির্ভরতা তাদের ইন্টারফেসের নামকরণের মাধ্যমে নামকরণের অনুমতি দেবে এবং ধারকটি জানবে যে প্রকারের নামের সাথে মিল রেখে নির্ধারককে কোনটি সরবরাহ করতে হবে। এটি সুবিধাজনক এবং এটি নির্ভরতার তুলনায় অনেক বেশি বর্ণনামূলক নামগুলিকে মঞ্জুরি দেয় Func<string, string>

আমি প্রায়শই দেখতে পাই যে এমনকি একটি একক, সাধারণ নির্ভরতা থাকা সত্ত্বেও, কখনও কখনও এটির জন্য একাধিক ফাংশন থাকা প্রয়োজন - একটি ইন্টারফেস আপনাকে এই ফাংশনগুলিকে এমনভাবে একসাথে দলবদ্ধ করতে দেয় যা স্ব-ডকুমেন্টিং থাকে, যা একাধিক পরামিতি থাকে যা সমস্ত যেমন পড়ে থাকে Func<string, string>, Func<string, int>

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


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

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

আমার অভিজ্ঞতায়, এটি কেবল সরঞ্জামদানের বিষয়। রিশার্পার্স ইন্সপেক্ট-> ইনকামিং কলগুলি ফানকস / ল্যাম্বডাসের পথটি ফলের ক্ষেত্রে ভাল কাজ করে।
খ্রিস্টান

3

আরও নির্দিষ্ট ইন্টারফেসের বিপরীতে জেনেরিক প্রতিনিধি / উচ্চতর অর্ডার ফাংশন যেমন আইওসির জন্য ফানক ব্যবহারে কোনও সমস্যা আছে?

আসলে তা না. একটি ফানক হ'ল নিজস্ব ধরণের ইন্টারফেস (ইংরেজি অর্থ সি # অর্থ নয়)। "এই পরামিতিটি এমন কিছু যা জিজ্ঞাসা করা হলে এক্স সরবরাহ করে" " এমনকি প্রয়োজন অনুযায়ী অলসভাবে তথ্য সরবরাহ করার সুবিধাও ফানকের রয়েছে। আমি এটি কিছুটা করি এবং এটি সংযম করে সুপারিশ করি।

ডাউনসাইড হিসাবে:

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

1
আমি oতিহ্যবাহী উপায়ে কারখানাটি তৈরি করতে আইওসি কনটেইনারটি ব্যবহার করি, তারপরে কারখানাটি ইন্টারফেসের পদ্ধতিগুলি ল্যাম্বডাসে প্যাকেজ করে, আপনার প্রথম বিষয়টিতে উল্লিখিত সমস্যাটি ঘিরে। ভাল দিক.
দ্যাটিক্যাটহিস্পেরার 21

1

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

একটি ক্লাস ইনজেকশন

class Worker: IWorker
{
    ILogger _logger;

    Worker(ILogger logger)
    {
        _logger = logger;
    }
    void SomeMethod()
    {
        _logger.Debug("This is a debug log statement.");
    }
}        

আমি মনে করি এটি কি চলছে তা বেশ পরিষ্কার। আরও কী, আপনি যদি আইওসি পাত্রে ব্যবহার করেন তবে আপনার স্পষ্টতই কিছু ইনজেক্ট করার দরকার নেই, আপনি কেবল আপনার রচনার মূলটিতে যুক্ত করুন:

container.RegisterType<ILogger, ConcreteLogger>();
container.RegisterType<IWorker, Worker>();
....
var worker = container.Resolve<IWorker>();

ডিবাগ করার সময় Worker, কোন বিকাশকারীকে ঠিক কী কংক্রিট শ্রেণি ব্যবহার করা হচ্ছে তা নির্ধারণের জন্য কম্পোজিশনের মূলের সাথে পরামর্শ করতে হবে।

যদি কোনও বিকাশকারী আরও জটিল যুক্তি প্রয়োজন, তার সাথে কাজ করার পুরো ইন্টারফেস রয়েছে:

    void SomeMethod()
    { 
       if (_logger.IsDebugEnabled) {
           _logger.Debug("This is a debug log statement.");
       }
    }

একটি পদ্ধতি ইনজেকশন

class Worker
{
    Action<string> _methodThatLogs;

    Worker(Action<string> methodThatLogs)
    {
        _methodThatLogs = methodThatLogs;
    }
    void SomeMethod()
    {
        _methodThatLogs("This is a logging statement");
    }
}        

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

এখন, আমরা এই পদ্ধতিটি কীভাবে ইনজেক্ট করব? আচ্ছা, আইওসি পাত্রে এটি আপনার জন্য করবে না। সুতরাং আপনি তাত্ক্ষণিকভাবে যখন এটি স্পষ্টভাবে ইনজেকশনের বাকি আছে Worker। এটি কয়েকটি সমস্যা উত্থাপন করে:

  1. এটি তাত্ক্ষণিক কাজ আরও কাজ Worker
  2. ডিবাগ করার চেষ্টা করা বিকাশকারীরা Workerখুঁজে পাবেন যে কংক্রিটের উদাহরণটি কী বলা হয় তা নির্ধারণ করা আরও কঠিন। তারা কেবল কম্পোজিশনের মূলের সাথে পরামর্শ করতে পারে না; তাদের কোডের মাধ্যমে ট্রেস করতে হবে।

আমাদের আরও জটিল যুক্তি লাগলে কীভাবে হয়? আপনার কৌশলটি কেবল একটি পদ্ধতি প্রকাশ করে। এখন আমি মনে করি আপনি ল্যাম্বডায় জটিল জিনিসগুলি বেক করতে পারেন:

var worker = new Worker((s) => { if (log.IsDebugEnabled) log.Debug(s) } );

কিন্তু আপনি যখন নিজের ইউনিট পরীক্ষা লিখছেন, আপনি কীভাবে সেই ল্যাম্বডা এক্সপ্রেশনটি পরীক্ষা করেন? এটি বেনামে, তাই আপনার ইউনিট পরীক্ষার কাঠামোটি সরাসরি এটি ইনস্ট্যান্ট করতে পারে না। সম্ভবত আপনি এটি করার জন্য কিছু চতুর উপায়টি বুঝতে পারেন, তবে এটি কোনও ইন্টারফেস ব্যবহার করার চেয়ে সম্ভবত আরও বড় পিটা হবে।

পার্থক্যের সংক্ষিপ্তসার:

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

যদি আপনি উপরের সমস্তটির সাথে ঠিক থাকেন তবে কেবল পদ্ধতিটি ইনজেক করা ঠিক আছে। অন্যথায় আমি আপনাকে traditionতিহ্য ধরে থাকা এবং একটি ইন্টারফেস ইনজেকশনের পরামর্শ দেব।


আমার নির্দিষ্ট করা উচিত ছিল, আমি যে ক্লাসটি তৈরি করছি এটি একটি প্রক্রিয়া যুক্তিযুক্ত ক্লাস class এটি অবহিত সিদ্ধান্ত নেওয়ার জন্য প্রয়োজনীয় ডেটা পাওয়ার জন্য এটি বাহ্যিক শ্রেণীর উপর নির্ভর করছে, পার্শ্ব প্রতিক্রিয়া প্রেরণাকারী শ্রেণি যেমন লগার ব্যবহার করা হয় না। আপনার উদাহরণ সহ একটি সমস্যা হ'ল এটি ওও দরিদ্র, বিশেষত একটি আইওসি ধারক ব্যবহারের প্রসঙ্গে। ক্লাসে অতিরিক্ত জটিলতা যুক্ত করে একটি if স্টেটমেন্ট ব্যবহার না করে এটি কেবল একটি জড় লগার পাস করা উচিত। এছাড়াও, ল্যাম্বডাসে যুক্তি প্রবর্তন করা সত্যই পরীক্ষা আরও শক্ত করে তুলবে ... এর ব্যবহারের উদ্দেশ্যকে পরাস্ত করে, যার কারণে এটি করা হয় না।
দ্যাটিক্যাটহিস্পেরার

ল্যাম্বডাস অ্যাপ্লিকেশনটিতে একটি ইন্টারফেস পদ্ধতিতে নির্দেশ করে এবং ইউনিট পরীক্ষায় স্বেচ্ছাসেবী ডেটা কাঠামো তৈরি করে।
দ্যাটিক্যাটহিস্পেরার 14

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

"ল্যাম্বডাস একটি ইন্টারফেস পদ্ধতির দিকে ইঙ্গিত করে" আপনি কী বোঝেন তা আমি নিশ্চিত নই। আমি মনে করি আপনাকে ডেলিগেটের স্বাক্ষরের সাথে মেলে এমন কোনও পদ্ধতির একটি প্রয়োগকরণ করতে হবে। পদ্ধতিটি যদি কোনও ইন্টারফেসের সাথে সম্পর্কিত হয় তবে তা ঘটনাক্রমে; কোনও কম্পাইল- বা রানটাইম চেক নেই তা নিশ্চিত করার জন্য। আমি কি ভুল বুঝছি? সম্ভবত আপনি আপনার পোস্টে একটি কোড উদাহরণ অন্তর্ভুক্ত করতে পারেন?
জন উঃ

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

0

নীচের কোডটি আমি অনেক আগে লিখেছি বিবেচনা করুন:

public interface IPhysicalPathMapper
{
    /// <summary>
    /// Gets the physical path represented by the relative URL.
    /// </summary>
    /// <param name="relativeURL"></param>
    /// <returns></returns>
    String GetPhysicalPath(String relativeURL);
}

public class EmailBuilder : IEmailBuilder
{
    public IPhysicalPathMapper PhysicalPathMapper { get; set; }
    public ITextFileLoader TextFileLoader { get; set; }
    public IEmailTemplateParser EmailTemplateParser { get; set; }
    public IEmaiBodyRenderer EmailBodyRenderer { get; set; }

    public String FromAddress { get; set; }

    public MailMessage BuildMailMessage(String templateRelativeURL, Object model, IEnumerable<String> toAddresses)
    {
        String templateText = this.TextFileLoader.LoadTextFromFile(this.PhysicalPathMapper.GetPhysicalPath(templateRelativeURL));

        EmailTemplate template = this.EmailTemplateParser.Parse(templateText);

        MailMessage email = new MailMessage()
        {
            From = new MailAddress(this.FromAddress),
            Subject = template.Subject,
            IsBodyHtml = true,
            Body = this.EmailBodyRenderer.RenderBodyToHtml(template.BodyTemplate, model)
        };

        foreach (MailAddress recipient in toAddresses.Select<String, MailAddress>(toAddress => new MailAddress(toAddress)))
        {
            email.To.Add(recipient);
        }

        return email;
    }
}

এটি কোনও টেমপ্লেট ফাইলে একটি আপেক্ষিক অবস্থান নেয়, এটিকে মেমরিতে লোড করে, বার্তার মূল অংশকে রেন্ডার করে এবং ই-মেইল অবজেক্টকে একত্রিত করে।

আপনি তাকান IPhysicalPathMapperএবং ভাবতে পারেন, "এখানে কেবল একটি ফাংশন রয়েছে That এটি একটি হতে পারে Func" " কিন্তু আসলে, এখানে সমস্যাটি এমনটিও নেই যা IPhysicalPathMapperথাকাও উচিত নয়। এর চেয়ে আরও ভাল সমাধান হ'ল পথটি পরামিতি করা :

public class EmailBuilder : IEmailBuilder
{
    public ITextFileLoader TextFileLoader { get; set; }
    public IEmailTemplateParser EmailTemplateParser { get; set; }
    public IEmaiBodyRenderer EmailBodyRenderer { get; set; }

    public String FromAddress { get; set; }

    public MailMessage BuildMailMessage(String templatePath, Object model, IEnumerable<String> toAddresses)
    {
        String templateText = this.TextFileLoader.LoadTextFromFile(templatePath);

        EmailTemplate template = this.EmailTemplateParser.Parse(templateText);

        MailMessage email = new MailMessage()
        {
            From = new MailAddress(this.FromAddress),
            Subject = template.Subject,
            IsBodyHtml = true,
            Body = this.EmailBodyRenderer.RenderBodyToHtml(template.BodyTemplate, model)
        };

        foreach (MailAddress recipient in toAddresses.Select<String, MailAddress>(toAddress => new MailAddress(toAddress)))
        {
            email.To.Add(recipient);
        }

        return email;
    }
}

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

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

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

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