কীভাবে এপিআই ডিজাইনে "অনেকগুলি পরামিতি" সমস্যা এড়ানো যায়?


160

আমি এই এপিআই ফাংশন আছে:

public ResultEnum DoSomeAction(string a, string b, DateTime c, OtherEnum d, 
     string e, string f, out Guid code)

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

আমি সর্বাধিক সুস্পষ্ট ধারণা নিয়ে হাজির হয়েছি: একটি বস্তু ডেটা encapsulating এবং প্রতিটি পরামিতি এক এক করে পাস করার পরিবর্তে এটি পাস। আমি এখানে যা এলাম:

public class DoSomeActionParameters
{
    public string A;
    public string B;
    public DateTime C;
    public OtherEnum D;
    public string E;
    public string F;        
}

এটি আমার এপিআই ঘোষণাটি এতে কমিয়ে দিয়েছে:

public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code)

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

public class DoSomeActionParameters
{
    public string A { get; private set; }
    public string B { get; private set; }
    public DateTime C { get; private set; }
    public OtherEnum D { get; private set; }
    public string E { get; private set; }
    public string F { get; private set; }        

    public DoSomeActionParameters(string a, string b, DateTime c, OtherEnum d, 
     string e, string f)
    {
        this.A = a;
        this.B = b;
        // ... tears erased the text here
    }
}

আপনি দেখতে পাচ্ছেন যে আমি আসলে আমার মূল সমস্যাটি আবার তৈরি করেছি: অনেকগুলি পরামিতি। এটা সুস্পষ্ট যে এটি যাওয়ার উপায় নয়। আমি কি করতে পারি? এইরকম অপরিবর্তনীয়তা অর্জনের শেষ বিকল্পটি হ'ল "পঠনযোগ্য" কাঠামোটি এভাবে ব্যবহার করা:

public struct DoSomeActionParameters
{
    public readonly string A;
    public readonly string B;
    public readonly DateTime C;
    public readonly OtherEnum D;
    public readonly string E;
    public readonly string F;        
}

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

আমি তখনই বিভ্রান্ত হয়ে পড়েছিলাম এবং এই প্রশ্নটি লেখার সিদ্ধান্ত নিয়েছি: "# অনেকগুলি পরামিতি" সমস্যা এড়াতে সি # এর সবচেয়ে সোজা উপায় কী? সেই উদ্দেশ্যে কী কেবল পঠনযোগ্য কাঠামো ব্যবহার করা সম্ভব এবং তবুও কোনও খারাপ এপিআই নকশা নেই?

ব্যাখ্যা:

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

হালনাগাদ

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


ক্লিন কোড: রবার্ট সি মার্টিন এবং মার্টিন ফাউলারের রিফ্যাক্টরিংয়ের অ্যাগ্রিল সফটওয়্যার কারুশিল্পের একটি হ্যান্ডবুক এটিকে কিছুটা কভার করে
ইয়ান রিংরোজ

1
আপনি যদি সি # 4 ব্যবহার করেন যেখানে আপনার alচ্ছিক প্যারামিটারগুলি থাকে তবে সেই বিল্ডার-সলিউশন রিডানড্যান্ট নয় ?
খেলাং

1
আমি বোকা হতে পারি তবে এটি কীভাবে সমস্যা তা আমি দেখতে ব্যর্থ হয়েছি, বিবেচনা করে যে এটি DoSomeActionParametersএকটি নিক্ষেপযোগ্য বস্তু, যা পদ্ধতি কলের পরে বাতিল করা হবে।
ভিলাক্স-

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

7
@ এসএসজি: আমিও এটি পছন্দ করতাম। আমরা সি # তে এমন বৈশিষ্ট্যগুলি যুক্ত করেছি যা একই সাথে অপরিবর্তনীয়তা (লিনকুইয়ের মতো) প্রচার করে যা আমরা এমন বৈশিষ্ট্যগুলি যুক্ত করেছি যা পরিবর্তনগুলি প্রচার করে (যেমন অবজেক্ট ইনিশিয়ালাইজার্স)) অপরিবর্তনীয় প্রকারের প্রচারের জন্য আরও ভাল সিনট্যাক্স থাকলে ভাল লাগবে। আমরা এটি সম্পর্কে কঠোরভাবে চিন্তা করছি এবং কিছু আকর্ষণীয় ধারণা পেয়েছি তবে পরবর্তী সংস্করণের জন্য আমি এ জাতীয় কোনও প্রত্যাশা করব না।
এরিক লিপার্ট

উত্তর:


22

ফ্রেমওয়ার্কগুলিতে অন্তর্ভুক্ত একটি স্টাইল সাধারণত সম্পর্কিত ক্লাসগুলিতে সম্পর্কিত প্যারামিটারগুলি গোষ্ঠীকরণের মতো হয় (তবে আবার মিউটিয়েটেটি নিয়ে সমস্যাযুক্ত):

var request = new HttpWebRequest(a, b);
var service = new RestService(request, c, d, e);
var client = new RestClient(service, f, g);
var resource = client.RequestRestResource(); // O params after 3 objects

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

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

প্রশ্নে আমার প্রথম উদাহরণের চেয়ে কীভাবে আলাদা?
সেদাত কাপানোগলু

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

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

87

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

public class Param
{
        public string A { get; private set; }
        public string B { get; private set; }
        public string C { get; private set; }


  public class Builder
  {
        private string a;
        private string b;
        private string c;

        public Builder WithA(string value)
        {
              a = value;
              return this;
        }

        public Builder WithB(string value)
        {
              b = value;
              return this;
        }

        public Builder WithC(string value)
        {
              c = value;
              return this;
        }

        public Param Build()
        {
              return new Param { A = a, B = b, C = c };
        }
  }


  DoSomeAction(new Param.Builder()
        .WithA("a")
        .WithB("b")
        .WithC("c")
        .Build());

+1 - এই ধরণের পদ্ধতির (যা আমি সাধারণত "ফ্লুয়েન્ટ ইন্টারফেস" নামে দেখেছি) ঠিক আমার মনেও ছিল।
ড্যানিয়েল প্রাইডেন

+1 - আমি একই পরিস্থিতিতে শেষ করেছি। এখানে কেবলমাত্র একটি শ্রেণি DoSomeActionছিল এবং এটির একটি পদ্ধতি ছিল।
ভিলাক্স-

+1 আমি এটির জন্যও ভেবেছিলাম, তবে যেহেতু আমি সাবলীল ইন্টারফেসে নতুন আছি, আমি জানি না যে এটি এখানে উপযুক্ত was আমার নিজের স্বজ্ঞাতটি যাচাই করার জন্য ধন্যবাদ
ম্যাট

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

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

10

আপনার যা আছে তা খুব নিশ্চিত ইঙ্গিত দেয় যে প্রশ্নে থাকা বর্গটি একক দায়িত্বের নীতি লঙ্ঘন করছে কারণ এতে অনেক বেশি নির্ভরতা রয়েছে। উপায়ে ক্লাস্টার মধ্যে যারা নির্ভরতা refactor করার জন্য ছদ্মরূপ অধীনস্থ


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

2
আপনি প্রতিটি দলকে নিজের মধ্যে একটি অপরিবর্তনীয় বস্তুতে পরিণত করতে পারেন। প্রতিটি বস্তুর কেবল কয়েকটি পরামিতি নেওয়া দরকার, সুতরাং আর্গুমেন্টের আসল সংখ্যাটি একই থাকে, তবে কোনও একক কনস্ট্রাক্টরে ব্যবহৃত আর্গুমেন্টের সংখ্যা হ্রাস পাবে।
সিমমান

2
+1 @ এসএসজি: প্রতিবার আমি কখনই নিজেকে এই জাতীয় কিছুতে বোঝাতে পরিচালিত হয়েছি, এই স্তরের পরামিতিগুলির প্রয়োজনীয় বড় পদ্ধতিতে দরকারী বিমূর্ততা চালিয়ে আমি সময়ের সাথে নিজেকে ভুল প্রমাণ করেছি। ইভান্সের ডিডিডি বইটি আপনাকে কীভাবে এটি সম্পর্কে চিন্তাভাবনা করতে পারে (যদিও আপনার সিস্টেমের মতো মনে হয় এটি সম্ভাব্য স্থান থেকে এই জাতীয় প্যাটার্স প্রয়োগের তুলনায় অনেক দূরে) - (এবং এটি কেবল একটি দুর্দান্ত বই)।
রুবেন বারটেলিংক

3
@ রুবেন: কোনও বুদ্ধিমান বইটি "ভাল ওও ডিজাইনে কোনও শ্রেণীর 5 টিরও বেশি সম্পত্তি থাকা উচিত নয়" বলতে পারে না। শ্রেণিকে যৌক্তিকভাবে গোষ্ঠীযুক্ত করা হয় এবং প্রকারের প্রসঙ্গের পরিমাণের উপর ভিত্তি করে তৈরি করা যায় না। তবে সি ও এর অপরিবর্তনীয়তা সমর্থনটি ভাল ওও ডিজাইনের নীতি লঙ্ঘন করার আগে নির্দিষ্ট সংখ্যক বৈশিষ্ট্যে সমস্যা তৈরি শুরু করে।
সেদাত কাপানোগলু

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

10

শুধু একটি থেকে আপনার পরামিতি ডাটা স্ট্রাকচার পরিবর্তন classএকটি থেকে structএবং আপনারা ভালো আছেন যান।

public struct DoSomeActionParameters 
{
   public string A;
   public string B;
   public DateTime C;
   public OtherEnum D;
   public string E;
   public string F;
}

public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code) 

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

পেশাদাররা:

  • কার্যকর করা সহজ
  • অন্তর্নিহিত যান্ত্রিকগুলিতে আচরণের সর্বনিম্ন পরিবর্তন

কনস:

  • অপরিচ্ছন্নতা স্পষ্ট নয়, বিকাশকারীদের মনোযোগ প্রয়োজন।
  • অপরিবর্তনীয়তা বজায় রাখার জন্য অযথা অনুলিপি করা
  • স্ট্যাক জায়গা দখল করে

+1 এটি সত্য তবে "ক্ষেত্র সরাসরি উন্মুক্ত করা খারাপ" সম্পর্কে অংশটি সমাধান করে না। আমি নিশ্চিত না যে কীভাবে খারাপ জিনিসগুলি খারাপ হতে পারে যদি আমি সেই এপিআইতে বৈশিষ্ট্যের পরিবর্তে ক্ষেত্রগুলি ব্যবহার করার পছন্দ করি।
সেদাত কাপানোগলু

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

ওহ সত্য অসাধারণ! ধন্যবাদ।
সেদাত কাপানোগলু

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

1
@ জেফ্রেএলউইটলিজ: উন্মুক্ত ক্ষেত্রের কাঠামোটি খারাপ, এই ধারণাটি আমি সত্যিই অপছন্দ করি। এই ধরনের দাবি আমাকে বলার সমতুল্য হিসাবে আঘাত করে যে স্ক্রু ড্রাইভারগুলি দুষ্ট এবং লোকেদের হাতুড়ি ব্যবহার করা উচিত কারণ স্ক্রু ড্রাইভারগুলির পয়েন্টগুলি নখের মাথাকে আবদ্ধ করে। যদি কোনও পেরেক চালানোর প্রয়োজন হয় তবে একজনকে হাতুড়ি ব্যবহার করা উচিত, তবে যদি কোনও স্ক্রু চালানোর প্রয়োজন হয় তবে একজনকে স্ক্রু ড্রাইভার ব্যবহার করা উচিত। অনেকগুলি পরিস্থিতি রয়েছে যেখানে একটি উন্মুক্ত ক্ষেত্র কাঠামো কাজের জন্য যথাযথভাবে সঠিক সরঞ্জাম tool উল্লেখ্য, সেখানে এ পর্যন্ত কম কোথায় পাব / সেট বৈশিষ্ট্য সঙ্গে একটি struct সত্যিই ডান টুল (অধিকাংশ ক্ষেত্রে যেখানে ... হয়
supercat

6

আপনার ডেটা ক্লাসের ভিতরে কোনও বিল্ডার শ্রেণি তৈরির বিষয়ে কীভাবে। ডেটা ক্লাসে সমস্ত সেটটারগুলি ব্যক্তিগত হিসাবে থাকবে এবং কেবল নির্মাতা সেগুলি সেট করতে সক্ষম হবেন।

public class DoSomeActionParameters
    {
        public string A { get; private set; }
        public string B  { get; private set; }
        public DateTime C { get; private set; }
        public OtherEnum D  { get; private set; }
        public string E  { get; private set; }
        public string F  { get; private set; }

        public class Builder
        {
            DoSomeActionParameters obj = new DoSomeActionParameters();

            public string A
            {
                set { obj.A = value; }
            }
            public string B
            {
                set { obj.B = value; }
            }
            public DateTime C
            {
                set { obj.C = value; }
            }
            public OtherEnum D
            {
                set { obj.D = value; }
            }
            public string E
            {
                set { obj.E = value; }
            }
            public string F
            {
                set { obj.F = value; }
            }

            public DoSomeActionParameters Build()
            {
                return obj;
            }
        }
    }

    public class Example
    {

        private void DoSth()
        {
            var data = new DoSomeActionParameters.Builder()
            {
                A = "",
                B = "",
                C = DateTime.Now,
                D = testc,
                E = "",
                F = ""
            }.Build();
        }
    }

1
+1 এটি পুরোপুরি বৈধ সমাধান তবে আমার মনে হয় এ জাতীয় কোনও সাধারণ নকশার সিদ্ধান্ত বজায় রাখতে এটি অনেক বেশি মজাদার। বিশেষত যখন "পঠনযোগ্য কাঠামো" সমাধানটি আদর্শের খুব কাছাকাছি হয়।
সেদাত কাপানোগলু

2
এটি কীভাবে "অত্যধিক পরামিতি" সমস্যার সমাধান করে? বাক্য গঠনটি ভিন্ন হতে পারে, তবে সমস্যাটি একই দেখায়। এটি কোনও সমালোচনা নয়, আমি কেবল কৌতূহলী কারণ আমি এই ধরণের সাথে পরিচিত নই।
অ্যালেক্সড

1
@alexD এটি অনেকগুলি ফাংশন পরামিতি থাকা এবং অবজেক্টটিকে অপরিবর্তনীয় রাখার সাথে সমস্যার সমাধান করে। কেবলমাত্র বিল্ডার শ্রেণিই ব্যক্তিগত বৈশিষ্ট্যগুলি সেট করতে পারে এবং প্যারামিটারগুলি একবার পেয়ে গেলে আপনি এটি পরিবর্তন করতে পারবেন না। সমস্যাটি হ'ল এর জন্য প্রচুর স্ক্যাফোল্ডিং কোড প্রয়োজন।
মার্টো

5
আপনার সমাধানের প্যারামিটার অবজেক্টটি পরিবর্তনযোগ্য নয়। যে কেউ বিল্ডারকে সংরক্ষণ করে সে বিল্ডিংয়ের পরেও প্যারামিটারগুলি সম্পাদনা করতে পারে
astef

1
@ Astef এর বক্তব্য হিসাবে, বর্তমানে এটি লিখিত হিসাবে একটি DoSomeActionParameters.Builderউদাহরণ তৈরি করতে এবং ঠিক একটি DoSomeActionParametersউদাহরণ কনফিগার করতে ব্যবহার করা যেতে পারে । এর বৈশিষ্ট্যগুলিতে Build()পরবর্তী পরিবর্তনগুলি কল করার পরে মূল উদাহরণের বৈশিষ্ট্যগুলি Builderসংশোধন করা অব্যাহত থাকবে , এবং পরবর্তী কলগুলি একই উদাহরণটি ফিরে আসতে থাকবে । এটা সত্যই হওয়া উচিত । DoSomeActionParametersBuild()DoSomeActionParameterspublic DoSomeActionParameters Build() { var oldObj = obj; obj = new DoSomeActionParameters(); return oldObj; }
বেকন

6

আমি কোনও সি # প্রোগ্রামার নই তবে আমি বিশ্বাস করি সি # নামযুক্ত আর্গুমেন্টকে সমর্থন করে: (এফ # দেয় এবং সি # মূলত এই ধরণের জিনিসটির জন্য তুলনামূলক বৈশিষ্ট্যযুক্ত) এটি করে: http://msdn.microsoft.com/en-us/library/dd264739 .aspx # Y342

সুতরাং আপনার মূল কোড কল করা হয়ে যায়:

public ResultEnum DoSomeAction( 
 e:"bar", 
 a: "foo", 
 c: today(), 
 b:"sad", 
 d: Red,
 f:"penguins")

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

সম্পাদনা করুন: এখানে আমি এটি সম্পর্কে একটি শৈল্পিক খুঁজে পেয়েছি। http://www.globalnerdy.com/2009/03/12/default-and- নাম-paraters-in-c-40-sith-lord-in-training / আমার সি # 4.0 নামক যুক্তি সমর্থন করা উচিত, 3.0 উল্লেখ করেনি


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

6

কেন কেবল এমন একটি ইন্টারফেস তৈরি করা যায় না যা অপরিবর্তনীয়তা প্রয়োগ করে (অর্থাত্ কেবল প্রাপ্তরা)?

এটি মূলত আপনার প্রথম সমাধান তবে আপনি প্যারামিটারটি অ্যাক্সেস করার জন্য ইন্টারফেসটি ব্যবহার করতে ফাংশনটিকে বাধ্য করেন।

public interface IDoSomeActionParameters
{
    string A { get; }
    string B { get; }
    DateTime C { get; }
    OtherEnum D { get; }
    string E { get; }
    string F { get; }              
}

public class DoSomeActionParameters: IDoSomeActionParameters
{
    public string A { get; set; }
    public string B { get; set; }
    public DateTime C { get; set; }
    public OtherEnum D { get; set; }
    public string E { get; set; }
    public string F { get; set; }        
}

এবং ফাংশন ঘোষণা হয়ে যায়:

public ResultEnum DoSomeAction(IDoSomeActionParameters parameters, out Guid code)

পেশাদাররা:

  • structসমাধানের মতো স্ট্যাকের সমস্যা নেই
  • ভাষা শব্দার্থক ব্যবহার করে প্রাকৃতিক সমাধান
  • অপরিচ্ছন্নতা সুস্পষ্ট
  • নমনীয় (ভোক্তা চাইলে ভিন্ন শ্রেণি ব্যবহার করতে পারেন)

কনস:

  • কিছু পুনরাবৃত্ত কাজ (দুটি পৃথক সত্তায় একই ঘোষণা)
  • বিকাশকারীকে অনুমান করতে DoSomeActionParametersহয় যে এটি এমন একটি শ্রেণি যা ম্যাপ করা যায়IDoSomeActionParameters

+1 আমি জানি না কেন আমি এটি ভেবে দেখিনি? :) আমি অনুমান করি আমি ভেবেছিলাম যে অবজেক্টটি এখনও অনেকগুলি পরামিতি সহ কোনও কনস্ট্রাক্টরের দ্বারা ক্ষতিগ্রস্থ হবে তবে এটি ঘটেনি। হ্যাঁ এটি খুব কার্যকর সমাধানও। কেবলমাত্র আমিই যে সমস্যাটি ভাবতে পারি তা হ'ল এটিআইপি ব্যবহারকারীর পক্ষে সঠিক শ্রেণীর নাম খুঁজে পাওয়া সত্যিকারের নয় যা প্রদত্ত ইন্টারফেসটিকে সমর্থন করে। কমপক্ষে ডকুমেন্টেশন প্রয়োজন এমন সমাধান আরও ভাল।
সেদাত কাপানোগলু

আমি এটিকে পছন্দ করি, মানচিত্রটির সদৃশতা এবং জ্ঞানটি পুনঃ ভাগ করে দেওয়া হয়, এবং আমি কংক্রিট শ্রেণীর ডিফল্ট নির্মাতা ব্যবহার করে ডিফল্ট মান সরবরাহ করতে পারি
অ্যান্টনি জনস্টন

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

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

3

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

    public class ExampleClass
    {
        //create properties like this...
        private readonly int _exampleProperty;
        public int ExampleProperty { get { return _exampleProperty; } }

        //Private constructor, prohibiting construction outside of this class
        private ExampleClass(ExampleClassParams parameters)
        {                
            _exampleProperty = parameters.ExampleProperty;
            //and so on... 
        }

        //The object returned from here will be immutable
        public ExampleClass GetFromDatabase(DBConnection conn, int id)
        {
            //do database stuff here (ommitted from example)
            ExampleClassParams parameters = new ExampleClassParams()
            {
                ExampleProperty = 1,
                ExampleProperty2 = 2
            };

            //Danger here as parameters object is mutable

            return new ExampleClass(parameters);    

            //Danger is now over ;)
        }

        //Private struct representing the parameters, nested within class that uses it.
        //This is mutable, but the fact that it is private means that all potential 
        //"damage" is limited to this class only.
        private struct ExampleClassParams
        {
            public int ExampleProperty { get; set; }
            public int AnotherExampleProperty { get; set; }
            public int ExampleProperty2 { get; set; }
            public int AnotherExampleProperty2 { get; set; }
            public int ExampleProperty3 { get; set; }
            public int AnotherExampleProperty3 { get; set; }
            public int ExampleProperty4 { get; set; }
            public int AnotherExampleProperty4 { get; set; } 
        }
    }

2

আপনি একটি বিল্ডার-শৈলীর পদ্ধতির ব্যবহার করতে পারেন, যদিও আপনার DoSomeActionপদ্ধতির জটিলতার উপর নির্ভর করে এটি একটি স্পর্শ ভারী ওজন হতে পারে। এই লাইন বরাবর কিছু:

public class DoSomeActionParametersBuilder
{
    public string A { get; set; }
    public string B { get; set; }
    public DateTime C { get; set; }
    public OtherEnum D { get; set; }
    public string E { get; set; }
    public string F { get; set; }

    public DoSomeActionParameters Build()
    {
        return new DoSomeActionParameters(A, B, C, D, E, F);
    }
}

public class DoSomeActionParameters
{
    public string A { get; private set; }
    public string B { get; private set; }
    public DateTime C { get; private set; }
    public OtherEnum D { get; private set; }
    public string E { get; private set; }
    public string F { get; private set; }

    public DoSomeActionParameters(string a, string b, DateTime c, OtherEnum d, string e, string f)
    {
        A = a;
        // etc.
    }
}

// usage
var actionParams = new DoSomeActionParametersBuilder
{
    A = "value for A",
    C = DateTime.Now,
    F = "I don't care for B, D and E"
}.Build();

result = foo.DoSomeAction(actionParams, out code);

আহ, মার্টো আমাকে বিল্ডারের পরামর্শে মারধর করলেন!
ক্রিস হোয়াইট

2

মানজি প্রতিক্রিয়া ছাড়াও - আপনি একটি অপারেশনকে আরও কয়েকটি ছোটতে ভাগ করতে চাইতে পারেন। তুলনা করা:

 BOOL WINAPI CreateProcess(
   __in_opt     LPCTSTR lpApplicationName,
   __inout_opt  LPTSTR lpCommandLine,
   __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
   __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
   __in         BOOL bInheritHandles,
   __in         DWORD dwCreationFlags,
   __in_opt     LPVOID lpEnvironment,
   __in_opt     LPCTSTR lpCurrentDirectory,
   __in         LPSTARTUPINFO lpStartupInfo,
   __out        LPPROCESS_INFORMATION lpProcessInformation
 );

এবং

 pid_t fork()
 int execvpe(const char *file, char *const argv[], char *const envp[])
 ...

যারা পসিক্স জানেন না তাদের পক্ষে সন্তানের সৃষ্টি এত সহজ হতে পারে:

pid_t child = fork();
if (child == 0) {
    execl("/bin/echo", "Hello world from child", NULL);
} else if (child != 0) {
    handle_error();
}

প্রতিটি নকশার পছন্দটি এটি কী কাজ করতে পারে তার উপর বাণিজ্য-উপস্থাপন করে।

পুনশ্চ. হ্যাঁ - এটি বিল্ডারের অনুরূপ - কেবল বিপরীতে (যেমন কলারের পরিবর্তে কলি দিকে)। সুনির্দিষ্ট ক্ষেত্রে এটির পরে নির্মাতা এটির চেয়ে ভাল বা নাও হতে পারেন।


এটি একটি ছোট অপারেশন তবে যে কেউ একক-দায়িত্বের নীতি লঙ্ঘন করছে তাদের জন্য এটি একটি ভাল সুপারিশ। অন্য সমস্ত ডিজাইনের উন্নতি সম্পন্ন হওয়ার পরে আমার প্রশ্নটি ঘটে।
সেদাত কাপানোগলু

ইউ। পি। এস. দুঃখিত - আমি আপনার সম্পাদনার আগে একটি প্রশ্ন প্রস্তুত করেছি এবং এটি পরে পোস্ট করেছি - তাই আমি এটি লক্ষ্য করি নি।
ম্যাকিয়েজ পাইচোটকা

2

এখানে মাইকিসের থেকে কিছুটা আলাদা তবে আমি যা করার চেষ্টা করছি তা সম্পূর্ণ বিষয়টি যতটা সম্ভব লেখাকে সামান্য করে তুলুন

public class DoSomeActionParameters
{
    readonly string _a;
    readonly int _b;

    public string A { get { return _a; } }

    public int B{ get { return _b; } }

    DoSomeActionParameters(Initializer data)
    {
        _a = data.A;
        _b = data.B;
    }

    public class Initializer
    {
        public Initializer()
        {
            A = "(unknown)";
            B = 88;
        }

        public string A { get; set; }
        public int B { get; set; }

        public DoSomeActionParameters Create()
        {
            return new DoSomeActionParameters(this);
        }
    }
}

ডোসমেকশনপ্যারামিটারগুলি অপরিবর্তনীয় যেমন এটি হতে পারে এবং এটির ডিফল্ট নির্মাতারা ব্যক্তিগত থাকায় সরাসরি তৈরি করা যায় না

ইনিশিয়ালাইজার পরিবর্তনযোগ্য নয়, কেবল একটি পরিবহন

ইনিশিয়ালাইজারটিতে ইনিশিয়ালাইজারের ব্যবহারটি গ্রহণ করে (আপনি যদি আমার ড্রিফ্ট পান) এবং আমি ইনিশিয়াল ডিফল্ট কনস্ট্রাক্টরে ডিফল্ট থাকতে পারি

DoSomeAction(new DoSomeActionParameters.Initializer
            {
                A = "Hello",
                B = 42
            }
            .Create());

প্যারামিটারগুলি এখানে alচ্ছিক হবে, আপনি যদি কিছুের প্রয়োজন চান তবে আপনি সেগুলি আরম্ভকারী ডিফল্ট কনস্ট্রাক্টরে রাখতে পারেন

এবং বৈধতা তৈরি পদ্ধতিতে যেতে পারে

public class Initializer
{
    public Initializer(int b)
    {
        A = "(unknown)";
        B = b;
    }

    public string A { get; set; }
    public int B { get; private set; }

    public DoSomeActionParameters Create()
    {
        if (B < 50) throw new ArgumentOutOfRangeException("B");

        return new DoSomeActionParameters(this);
    }
}

সুতরাং এখন এটি মত দেখাচ্ছে

DoSomeAction(new DoSomeActionParameters.Initializer
            (b: 42)
            {
                A = "Hello"
            }
            .Create());

তবুও একটু কুকি আমি জানি, তবে যাইহোক চেষ্টা করে যাচ্ছি

সম্পাদনা করুন: প্যারামিটার অবজেক্টে তৈরি পদ্ধতিটি একটি স্ট্যাটিকের দিকে সরানো এবং একটি ডেলিগেট যোগ করুন যা প্রারম্ভিকটি পাস করে কল থেকে কিছুটা কুকিনেস গ্রহণ করে

public class DoSomeActionParameters
{
    readonly string _a;
    readonly int _b;

    public string A { get { return _a; } }
    public int B{ get { return _b; } }

    DoSomeActionParameters(Initializer data)
    {
        _a = data.A;
        _b = data.B;
    }

    public class Initializer
    {
        public Initializer()
        {
            A = "(unknown)";
            B = 88;
        }

        public string A { get; set; }
        public int B { get; set; }
    }

    public static DoSomeActionParameters Create(Action<Initializer> assign)
    {
        var i = new Initializer();
        assign(i)

        return new DoSomeActionParameters(i);
    }
}

কলটি এখন এইরকম দেখাচ্ছে

DoSomeAction(
        DoSomeActionParameters.Create(
            i => {
                i.A = "Hello";
            })
        );

1

কাঠামোটি ব্যবহার করুন তবে পাবলিক ফিল্ডের পরিবর্তে সর্বজনীন বৈশিষ্ট্য রয়েছে:

। সকলেই (এফএক্সকপ এবং জন স্কিটি সহ) সম্মত হন যে সার্বজনীন ক্ষেত্রগুলি প্রকাশ করা খারাপ।

জোন এবং এফএক্সকপ সন্তুষ্ট হবে কারণ আপনি ক্ষেত্র নয়, প্রোপাইটগুলি প্রকাশ করছেন।

• এরিক লিপার্ট এট আল বলছেন অপরিবর্তনীয়তার জন্য কেবল পাঠযোগ্য ক্ষেত্রগুলিতে নির্ভর করা মিথ্যা।

এরিকটি সন্তুষ্ট হবে কারণ বৈশিষ্ট্যগুলি ব্যবহার করে, আপনি নিশ্চিত করতে পারেন যে মানটি একবারে সেট করা হয়েছে।

    private bool propC_set=false;
    private date pC;
    public date C {
        get{
            return pC;
        }
        set{
            if (!propC_set) {
               pC = value;
            }
            propC_set = true;
        }
    }

একটি আধা-অপরিবর্তনীয় বস্তু (মান সেট করা যেতে পারে তবে পরিবর্তন করা যায় না)। মান এবং রেফারেন্স ধরণের জন্য কাজ করে।


+1 হয়তো বেসিক পাঠ্য ক্ষেত্র এবং পাবলিক গেটর-কেবলমাত্র বৈশিষ্ট্যগুলিকে একটি কম কাঠামো সমাধানের অনুমতি দেওয়ার জন্য কোনও কাঠামোর মধ্যে একত্রিত করা যেতে পারে।
সেদাত কাপানোগলু

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

0

আমার সমস্যাটি যখন আমার একই সমস্যা ছিল তখন আমি আমার প্রকল্পে স্যামুয়েল এর উত্তরগুলির একটি বৈকল্পিক :

class MagicPerformer
{
    public int Param1 { get; set; }
    public string Param2 { get; set; }
    public DateTime Param3 { get; set; }

    public MagicPerformer SetParam1(int value) { this.Param1 = value; return this; }
    public MagicPerformer SetParam2(string value) { this.Param2 = value; return this; }
    public MagicPerformer SetParam4(DateTime value) { this.Param3 = value; return this; }

    public void DoMagic() // Uses all the parameters and does the magic
    {
    }
}

এবং ব্যবহার করতে:

new MagicPerformer().SeParam1(10).SetParam2("Yo!").DoMagic();

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


এটি নির্বিশেষে একটি পরিবর্তনীয় শ্রেণি।
সেদাত কাপানোগলু

@ এসএসজি - হ্যাঁ, ঠিক আছে DoMagicতার চুক্তি যদিও এটা বস্তুর সংশোধন করা হবে না যে হয়েছে। তবে আমার ধারণা এটি দুর্ঘটনাজনিত পরিবর্তন থেকে রক্ষা করে না।
ভিলেক্স-
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.