দিক ওরিয়েন্টেড প্রোগ্রামিং: কখন একটি কাঠামো ব্যবহার শুরু করবেন?


22

আমি শুধু প্রেক্ষিত এই আলাপ দ্বারা গ্রেগ ইয়াং চুম্বন করতে সাবধানবাণী লোক: এটা রাখা সহজ মূঢ়।

তিনি যে বিষয়গুলির পরামর্শ দিয়েছিলেন তার মধ্যে একটি হ'ল দিক-ভিত্তিক প্রোগ্রামিং করার জন্য, কোনও কাঠামোর প্রয়োজন হয় না

তিনি একটি শক্ত প্রতিবন্ধকতা তৈরি করে শুরু করেন: যে সমস্ত পদ্ধতিতে একটি, এবং কেবল একটিই, প্যারামিটার লাগে (যদিও তিনি আংশিক প্রয়োগ ব্যবহার করে এটিকে খানিকটা পরে শিথিল করেন )।

তিনি যে উদাহরণটি দিয়েছেন তা হল একটি ইন্টারফেস সংজ্ঞায়িত করা:

public interface IConsumes<T>
{
    void Consume(T message);
}

যদি আমরা একটি আদেশ জারি করতে চাই:

public class Command
{
    public string SomeInformation;
    public int ID;

    public override string ToString()
    {
       return ID + " : " + SomeInformation + Environment.NewLine;
    }
}

কমান্ডটি প্রয়োগ করা হয়েছে:

public class CommandService : IConsumes<Command>
{
    private IConsumes<Command> _next;

    public CommandService(IConsumes<Command> cmd = null)
    {
        _next = cmd;
    }
    public void Consume(Command message)
    {
       Console.WriteLine("Command complete!");
        if (_next != null)
            _next.Consume(message);
    }
}

কনসোলে লগিং করতে, তারপরে একটি কেবল প্রয়োগ করে:

public class Logger<T> : IConsumes<T>
{
    private readonly IConsumes<T> _next;

    public Logger(IConsumes<T> next)
    {
        _next = next;
    }
    public void Consume(T message)
    {
        Log(message);
        if (_next != null)
            _next.Consume(message);
    }

    private void Log(T message)
    {
        Console.WriteLine(message);
    }
}

তারপরে, প্রাক-কমান্ড লগিং, কমান্ড পরিষেবা এবং পোস্ট-কমান্ড লগিং কেবলমাত্র:

var log1 = new Logger<Command>(null);
var svr  = new CommandService(log);
var startOfChain = new Logger<Command>(svr);

এবং কমান্ডটি দ্বারা কার্যকর করা হয়:

var cmd = new Command();
startOfChain.Consume(cmd);

এটি করার জন্য, উদাহরণস্বরূপ, পোস্টশার্প , কেউ এইভাবে মন্তব্য করতে পারেন CommandService:

public class CommandService : IConsumes<Command>
{
    [Trace]
    public void Consume(Command message)
    {
       Console.WriteLine("Command complete!");
    }
}

এবং তারপরে একটি অ্যাট্রিবিউট ক্লাসে লগিংটি প্রয়োগ করতে হবে যেমন:

[Serializable]
public class TraceAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry( MethodExecutionArgs args )
    {
        Console.WriteLine(args.Method.Name + " : Entered!" );   
    }

    public override void OnSuccess( MethodExecutionArgs args )
    {
        Console.WriteLine(args.Method.Name + " : Exited!" );
    }

    public override void OnException( MethodExecutionArgs args )
    {
        Console.WriteLine(args.Method.Name + " : EX : " + args.Exception.Message );
    }
}

গ্রেগ যে যুক্তিটি ব্যবহার করে তা হ'ল গুণাবলী প্রয়োগ থেকে অ্যাট্রিবিউট থেকে সংযোগটি "খুব বেশি যাদু" হয় জুনিয়র বিকাশকারীকে কী ঘটছে তা ব্যাখ্যা করতে সক্ষম হতে। প্রাথমিক উদাহরণটি হ'ল "কেবল কোড" এবং সহজেই ব্যাখ্যা করা।

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


3
+1: অবশ্যই একটি ভাল প্রশ্ন। কেউ সহজেই বলতে পারেন "... যখন আপনি ইতিমধ্যে সমাধানটি বুঝতে না পারলে"।
স্টিভেন এভার্স

1
হতে পারে আমি কেবল শৈলীতে অভ্যস্ত নই, তবে এর মতো একটি সম্পূর্ণ অ্যাপ্লিকেশন লেখার ধারণাটি আমাকে সম্পূর্ণ উন্মাদ বলে আঘাত করে। আমি বরং একটি পদ্ধতি ইন্টারসেপ্টার ব্যবহার করব।
অ্যারোনআউট

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

আমি এখনও নিশ্চিত না যে আমি অনুপ্রেরণাটি বুঝতে পেরেছি; যেমন Aop যেমন ধারণার খুব সারাংশ উদ্বেগ প্রকাশ করার পাবে কোথায় declaratively কনফিগারেশন মাধ্যমে, অর্থাত্। আমার কাছে এটি কেবল বর্গাকার চাকাটি পুনর্নবীকরণ করছে। আপনার বা আপনার প্রশ্নের সমালোচনা নয়, তবে আমি মনে করি এর একমাত্র বুদ্ধিমান উত্তর হ'ল "প্রতিটি অপশন ব্যর্থ না হলে গ্রেগের দৃষ্টিভঙ্গি আমি কখনই ব্যবহার করতে পারব না।"
অ্যারোনআউট

এটি আমাকে মোটেও বিরক্ত করে না, তবে এটি স্ট্যাক ওভারফ্লো প্রশ্নটির চেয়ে কিছুটা বেশি হবে না?
রেই মিয়াসাকা

উত্তর:


17

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

এবং আপনি জানেন কি? আপনি Mono.Cecil এর সাহায্যে একটি সাধারণ অ্যাট্রিবিউট চালিত আইএল ভিত্তিক লগিং কাঠামো লিখতে পারেন । (এটি পরীক্ষা করা কিছুটা জটিল, তবে ...)

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

সমস্ত গ্রেগ সেখানে প্রদর্শন করেছে যে এটি বোকা বোকা দৃষ্টান্ত রাখুন।


6
এটি বোকা বোকা রাখার জন্য +1। আইনস্টাইনের বিখ্যাত উক্তিটির কথা মনে করিয়ে দেয়: "সবকিছুকে যতটা সম্ভব সহজ করুন তবে সহজ নয়"।
রে মিয়াসাকা

এফডব্লিউআইডাব্লু, এফ # এর একই সীমাবদ্ধতা রয়েছে, প্রতিটি পদ্ধতিতে সর্বাধিক একটি আর্গুমেন্ট লাগে।
R0MANARMY

1
let concat (x : string) y = x + y;; concat "Hello, " "World!";;দেখে মনে হচ্ছে এটি দুটি যুক্তি লাগে, আমি কী মিস করছি?

2
@ মাউথ - আসলে যা ঘটছে তা হ'ল concat "Hello, "আপনি আসলে এমন একটি ফাংশন তৈরি করছেন যা কেবলমাত্র লাগে y, এবং x"হ্যালো" হতে স্থানীয় বাইন্ডিং হিসাবে পূর্বনির্ধারিত রয়েছে । যদি এই মধ্যবর্তী ফাংশনটি দেখা যায়, তবে এটির মতো দেখতে লাগবে let concat_x y = "Hello, " + y। এবং তারপরে, আপনি কল করছেন concat_x "World!"। সিনট্যাক্স এটিকে কম স্পষ্ট করে তোলে, তবে এটি আপনাকে নতুন ক্রিয়াকলাপগুলি "বেক" করতে দেয় - উদাহরণস্বরূপ let printstrln = print "%s\n" ;; printstrln "woof",। এছাড়াও, আপনি যদি এমন কিছু করেন তবে let f(x,y) = x + yএটি আসলে একটি টিপল আর্গুমেন্ট।
রেই মিয়াসাকা

1
পাছার সময় আমি যে কোনও কার্যনির্বাহী প্রোগ্রামিং করেছি বিশ্ববিদ্যালয়ে ফিরে মিরান্ডায় ছিলাম, আমাকে এফ # তে একবার দেখে নিতে হবে, এটি আকর্ষণীয় বলে মনে হচ্ছে।

8

আমার godশ্বর, লোকটি অসহ্যভাবে ক্ষয়কর। আমি আশা করি আমি এই আলোচনাটি দেখার পরিবর্তে আপনার প্রশ্নে কোডটি পড়তে পারি।

আমি মনে করি না যে আমি যদি কখনও এওপি ব্যবহারের স্বার্থে এই পদ্ধতির ব্যবহার করতাম তবে। গ্রেগ বলেছেন যে এটি সাধারণ পরিস্থিতিতে ভাল। একটি সহজ পরিস্থিতিতে আমি যা করব তা এখানে:

public void DeactivateInventoryItem(CommandServices cs, Guid item, string reason)
{
    cs.Log.Write("Deactivated: {0} ({1})", item, reason);
    repo.Deactivate(item, reason);
}

হ্যাঁ, আমি এটি করেছি, আমি সম্পূর্ণভাবে এওপি থেকে মুক্তি পেয়েছি! কেন? কারণ আপনার সাধারণ পরিস্থিতিতে এওপি দরকার হয় না

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

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

অন্যথায়, আমি কেবল একটি কাঠামো বা কিছু প্রতিবিম্ব ব্যবহার করব। পোস্টশার্প এমনকি সিলভারলাইট এবং কমপ্যাক্ট ফ্রেমওয়ার্কেও কাজ করে - সুতরাং যাকে তিনি "যাদু" বলেছেন তা আদৌ মায়াবী নয়

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


5

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

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


"1 এর জন্য" আমি ঘোষণামূলক পদ্ধতির পর্যালোচনা করার চেয়ে একক প্যারামিটার পদ্ধতির বোঝার চেষ্টা করে বেশি সময় ব্যয় করেছি। " আমি যা IConsume<T>সম্পাদিত হচ্ছে তার জন্য অত্যধিক জটিল উদাহরণটি পেয়েছি ।
স্কট হুইটলক

4

আপনি যে কোডটি দেখিয়েছেন সেটিতে যদি আমি কিছু হারিয়ে না দিই তবে তা হল 'দায়িত্বের শৃঙ্খলা' ডিজাইন প্যাটার্ন যা আপনাকে যদি কোনও অবজেক্টের (যেমন কমান্ড হ্যান্ডলারের কয়েকটি ধারাবাহিক কমান্ডগুলি) ক্রমান্বিত করার প্রয়োজন হয় তবে তা দুর্দান্ত at রানটাইম।

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

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


4

তার বিকল্প সম্পর্কে - সেখানে আছে, যে কাজ। কোনও এক লাইনের বৈশিষ্ট্যের পাঠযোগ্যতার সাথে তুলনা করে না।

নতুন ছেলেদের এওপিতে কীভাবে জিনিসগুলি কাজ করে তা বোঝাতে একটি সংক্ষিপ্ত বক্তৃতা দিন।


4

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

আমি আরেকটি উদাহরণ দেওয়ার চেষ্টা করব। হয়তো নিখুঁত নয় তবে আমি আশা করি এটি বিষয়টিকে আরও স্পষ্ট করে তোলে।

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

public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }

    public override string ToString() { return String.Format("{0}, {1}", Name, Price); }
}

public static class ProductService
{
    public static IEnumerable<Product> GetAllProducts(ProductRepositoryStub repository)
    {
        return repository.GetAll();
    }
}

public class ProductRepositoryStub
{
    public ProductRepositoryStub(string connStr) {}

    public IEnumerable<Product> GetAll()
    {
        return new List<Product>
        {
            new Product {Name = "Cd Player", Price = 49.99m},
            new Product {Name = "Yacht", Price = 2999999m }
        };
    }
}

অবশ্যই আপনি পরিষেবাটিতে একটি ইন্টারফেসও পাস করতে পারেন।

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

public interface Handles<T>
{
    void Handle(T message);
}

এবং একটি কমান্ড যা পণ্যগুলির তালিকা ধারণ করে

public class ShowProductsCommand
{
    public IEnumerable<Product> Products { get; set; }
}

এবং দেখুন

public class View : Handles<ShowProductsCommand>
{
    public void Handle(ShowProductsCommand cmd)
    {
        cmd.Products.ToList().ForEach(x => Console.WriteLine(x.ToString()));
    }
}

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

public class Application
{
    private readonly Func<IEnumerable<Product>> _getAllProducts;
    private readonly Action<ShowProductsCommand> _showProducts;

    public Application(Func<IEnumerable<Product>> getAllProducts, Action<ShowProductsCommand> showProducts)
    {
        _getAllProducts = getAllProducts;
        _showProducts = showProducts;
    }

    public void Run()
    {
        var products = _getAllProducts();
        var cmd = new ShowProductsCommand { Products = products };
        _showProducts(cmd);
    }
}

শেষ পর্যন্ত আমরা মূল পদ্ধতিতে অ্যাপ্লিকেশনটি রচনা করি।

static void Main(string[] args)
{
    // composition
    Func<IEnumerable<Product>> getAllProducts = () => ProductService.GetAllProducts(new ProductRepositoryStub(""));
    Action<ShowProductsCommand> showProducts = (x) => new View().Handle(x);
    var app = new Application(getAllProducts, showProducts);

    app.Run();
}

এখন দুর্দান্ত জিনিস হ'ল আমরা বিদ্যমান কোডটি স্পর্শ না করে এবং কাঠামো বা টিকা ছাড়াই লগিং বা ব্যতিক্রম হ্যান্ডলিংয়ের মতো দিকগুলি যুক্ত করতে পারি। ব্যতিক্রম হ্যান্ডলিংয়ের জন্য উদাহরণস্বরূপ আমরা কেবল একটি নতুন শ্রেণি যুক্ত করেছি:

public class ExceptionHandler<T> : Handles<T>
{
    private readonly Handles<T> _next;

    public ExceptionHandler(Handles<T> next) { _next = next; }

    public void Handle(T message)
    {
        try
        {
            _next.Handle(message);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

এবং তারপরে আমরা অ্যাপ্লিকেশনটির প্রবেশের সময় রচনা চলাকালীন এটি একসাথে প্লাগ করি। আমাদের এমনকি অ্যাপ্লিকেশন ক্লাসে কোডটি স্পর্শ করতে হবে না। আমরা কেবল একটি লাইন প্রতিস্থাপন করেছি:

Action<ShowProductsCommand> showProducts = (x) => new ExceptionHandler<ShowProductsCommand>(new View()).Handle(x);

আবার শুরু করার জন্য: যখন আমাদের একটি প্রবাহমুখী নকশা থাকে তখন আমরা নতুন শ্রেণীর ভিতরে কার্যকারিতা যুক্ত করে দিকগুলি যুক্ত করতে পারি। তারপরে আমাদের রচনা পদ্ধতিতে একটি লাইন পরিবর্তন করতে হবে এবং এটিই।

সুতরাং আমি মনে করি আপনার প্রশ্নের উত্তর হ'ল আপনি সহজেই এক পদ্ধতির থেকে অন্য দিকে যেতে পারবেন না তবে আপনি আপনার প্রকল্পে কোন ধরণের আর্কিটেকচারাল পদ্ধতির জন্য যাবেন তা সিদ্ধান্ত নিতে হবে।

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

public class ProductQueries : Queries<IEnumerable<Product>>
{
    private readonly Func<IEnumerable<Product>> _query;

    public ProductQueries(Func<IEnumerable<Product>> query)
    {
        _query = query;
    }

    public IEnumerable<Product> Query()
    {
        return _query();
    }
}

public interface Queries<TResult>
{
    TResult Query();
}

এরপরে রচনাটি এভাবে পরিবর্তন করতে হবে:

Func<IEnumerable<Product>> getAllProducts = () => ProductService.GetAllProducts(new ProductRepositoryStub(""));
Func<IEnumerable<Product>> queryAllProducts = new ProductQueries(getAllProducts).Query;
Action<ShowProductsCommand> showProducts = (x) => new ExceptionHandler<ShowProductsCommand>(new View()).Handle(x);
var app = new Application(queryAllProducts, showProducts);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.