অনেকগুলি (6+) পরামিতি রয়েছে এমন কোনও পদ্ধতির রিফ্যাক্টর করার সর্বোত্তম উপায় কী?


102

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

return new Shniz(foo, bar, baz, quux, fred, wilma, barney, dino, donkey)

আমি পরামিতিগুলির তালিকার প্রতিনিধিত্ব করতে স্ট্রাক্টগুলি ব্যবহার করার কথা ভেবেছি, তবে এটি কেবল সমস্যাটিকে এক জায়গা থেকে অন্য জায়গায় স্থানান্তরিত করবে এবং প্রক্রিয়াটিতে অন্য ধরণের তৈরি করবে বলে মনে হচ্ছে।

ShnizArgs args = new ShnizArgs(foo, bar, baz, quux, fred, wilma, barney, dino, donkey)
return new Shniz(args);

সুতরাং এটি কোনও উন্নতির মতো বলে মনে হচ্ছে না। তাহলে সেরা পন্থাটি কী?


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

1
যদি আপনি কোনও বিশেষ ভাষা নিখরচায় করার জন্য সন্ধান করেন তবে সি # দিয়ে যান। তবে মূলত, কেবল একটি সাধারণ সম্পত্তি ব্যাগ। এটির বিভিন্ন ধরণের বিভিন্ন নামযুক্ত বৈশিষ্ট্য রয়েছে। শ্রেণি, হ্যাশ টেবিল, কাঠামো বা যা কিছু হিসাবে সংজ্ঞায়িত করা যায়।
পুনরাবৃত্তি

এই নিবন্ধটি বিষয়ে কিছু ভাল অন্তর্দৃষ্টি আছে। জাভাস্ক্রিপ্ট নির্দিষ্ট, তবে নীতিগুলি অন্য ভাষায় প্রয়োগ করা যেতে পারে।
লালা

উত্তর:


94

সবচেয়ে ভাল উপায় হ'ল যুক্তিগুলিকে একসাথে গ্রুপ করার উপায়গুলি খুঁজে পাওয়া। এটি ধরে নেওয়া হয়, এবং সত্যিকার অর্থে কেবল তখনই কাজ করে যদি আপনি একাধিক যুক্তি "গ্রুপিং" দিয়ে শেষ করেন।

উদাহরণস্বরূপ, আপনি যদি কোনও আয়তক্ষেত্রের জন্য স্পেসিফিকেশনটি অতিক্রম করে থাকেন তবে আপনি x, y, প্রস্থ এবং উচ্চতা পার করতে পারেন বা আপনি কেবল একটি আয়তক্ষেত্রটি পেরিয়ে যেতে পারেন যার মধ্যে x, y, প্রস্থ এবং উচ্চতা রয়েছে।

এটিকে কিছুটা পরিষ্কার করার জন্য রিফ্যাক্টর করার সময় এই জাতীয় জিনিসগুলির সন্ধান করুন। যদি যুক্তিগুলি সত্যই একত্রিত না করা যায় তবে আপনার একক দায়িত্বের নীতি লঙ্ঘন হয়েছে কিনা তা সন্ধান শুরু করুন।


4
ভাল ধারণা কিন্তু খারাপ উদাহরণ; আয়তক্ষেত্রের জন্য নির্মাণকারীর 4 টি যুক্তি থাকতে হবে। পদ্ধতিটি 2 টি আয়তক্ষেত্রের স্থানাঙ্ক / মাত্রার 2 সেট আশা করে যদি এটি আরও অর্থবোধ করে। তারপরে আপনি x1, x2, y1, y2 এর পরিবর্তে 2 টি আয়তক্ষেত্র পাস করতে পারেন ...
প্রোগ্রামার

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

23
+1: একক দায়িত্বের জন্য, এটি সত্যই সত্যিকারের সমস্যাটিকে সম্বোধন করছে এমন সমস্ত উত্তরের কয়েকটি মন্তব্যগুলির মধ্যে একটি। কোন জিনিসটির সত্যতা গঠনের জন্য 7 টি স্বতন্ত্র মান প্রয়োজন।
অ্যান্থনিডাব্লু জোন্স

6
পছন্দ করেছেন বর্তমান আবহাওয়ার অবস্থার ডেটাতে এর পরিচয় তৈরি করতে আরও অনেক স্বতন্ত্র মান থাকতে পারে।
funct7

107

আমি ধরে নিচ্ছি আপনার সি সি মানে । এর মধ্যে কিছু জিনিস অন্যান্য ভাষায়ও প্রযোজ্য।

আপনার কাছে বেশ কয়েকটি বিকল্প রয়েছে:

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

class C
{
    public string S { get; set; }
    public int I { get; set; }
}

new C { S = "hi", I = 3 };

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

নির্মাতা প্যাটার্ন

মধ্যে সম্পর্ক সম্পর্কে চিন্তা করুন stringএবং StringBuilder। আপনি নিজের ক্লাসের জন্য এটি পেতে পারেন। আমি এটিকে নেস্টেড ক্লাস হিসাবে বাস্তবায়ন করতে পছন্দ করি, সুতরাং ক্লাসের Cসম্পর্কিত ক্লাস থাকে C.Builder। আমি নির্মাতাদের একটি সাবলীল ইন্টারফেসও পছন্দ করি। ঠিক হয়ে গেছে, আপনি সিনট্যাক্স এর মতো পেতে পারেন:

C c = new C.Builder()
    .SetX(4)    // SetX is the fluent equivalent to a property setter
    .SetY("hello")
    .ToC();     // ToC is the builder pattern analog to ToString()

// Modify without breaking immutability
c = c.ToBuilder().SetX(2).ToC();

// Still useful to have a traditional ctor:
c = new C(1, "...");

// And object initializer syntax is still available:
c = new C.Builder { X = 4, Y = "boing" }.ToC();

আমার কাছে পাওয়ারশেল স্ক্রিপ্ট রয়েছে যা আমাকে এই সমস্ত কাজ করতে বিল্ডার কোডটি তৈরি করতে দেয়, যেখানে ইনপুটটিকে দেখে মনে হচ্ছে:

class C {
    field I X
    field string Y
}

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

"প্যারামিটার অবজেক্ট পরিচিত করুন" রিফ্যাক্টরিং । দেখুন refactoring ক্যাটালগ । ধারণাটি হ'ল আপনি যে প্যারামিটারগুলি দিয়ে যাচ্ছেন তার কয়েকটি গ্রহণ করে একটি নতুন টাইপ করে রাখুন এবং তার পরিবর্তে সেই ধরণের একটি উদাহরণ পাস করুন। আপনি যদি চিন্তা না করেই এটি করেন তবে আপনি যেখানে শুরু করেছিলেন সেখানে ফিরে আসবেন:

new C(a, b, c, d);

হয়ে

new C(new D(a, b, c, d));

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

  1. পরামিতিগুলির সাবসেটগুলি সন্ধান করুন যা একসাথে বোঝায়। কেবল নির্বোধভাবে কোনও ফাংশনের সমস্ত পরামিতি একসাথে ভাগ করে নেওয়া আপনাকে বেশি কিছু দেয় না; লক্ষ্যটি বোঝার মতো গ্রুপিং করা sense আপনি জানতে পারবেন যখন নতুন ধরণের নামটি স্পষ্টভাবে প্রকাশিত হবে তখন আপনি তা পেয়েছেন।

  2. এই মানগুলি একসাথে ব্যবহৃত হয় এমন অন্যান্য জায়গাগুলি সন্ধান করুন এবং সেখানেও নতুন প্রকারটি ব্যবহার করুন। সম্ভাবনাগুলি হ'ল, যখন আপনি ইতিমধ্যে পুরো জায়গা জুড়ে ব্যবহার করা মানগুলির একটি সেটের জন্য একটি ভাল নতুন টাইপ পেয়েছেন, তখন সেই নতুন ধরণের সমস্ত জায়গাগুলিতেও তা উপলব্ধি ঘটবে।

  3. বিদ্যমান কোডে থাকা কার্যকারিতাটি অনুসন্ধান করুন তবে এটি নতুন ধরণের on

উদাহরণস্বরূপ, হতে পারে আপনি এমন কিছু কোড দেখতে পেল যা দেখে মনে হচ্ছে:

bool SpeedIsAcceptable(int minSpeed, int maxSpeed, int currentSpeed)
{
    return currentSpeed >= minSpeed & currentSpeed < maxSpeed;
}

আপনি minSpeedএবং maxSpeedপরামিতিগুলি নিতে এবং এগুলিকে একটি নতুন ধরণে রাখতে পারেন:

class SpeedRange
{
   public int Min;
   public int Max;
}

bool SpeedIsAcceptable(SpeedRange sr, int currentSpeed)
{
    return currentSpeed >= sr.Min & currentSpeed < sr.Max;
}

এটি আরও ভাল তবে সত্যই নতুন ধরণের সুবিধা নিতে তুলনাগুলিকে নতুন ধরণের স্থানান্তর করুন:

class SpeedRange
{
   public int Min;
   public int Max;

   bool Contains(int speed)
   {
       return speed >= min & speed < Max;
   }
}

bool SpeedIsAcceptable(SpeedRange sr, int currentSpeed)
{
    return sr.Contains(currentSpeed);
}

এবং এখন আমরা কোথাও পাচ্ছি: SpeedIsAcceptable()এখনকার বাস্তবায়ন বলতে কী বোঝায় তা বোঝায় এবং আপনার একটি দরকারী, পুনরায় ব্যবহারযোগ্য বর্গ রয়েছে। (পরবর্তী সুস্পষ্ট পদক্ষেপ করা হয় SpeedRangeকরার জন্য Range<Speed>।)

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


4
আমি প্রথমে "প্যারামিটার অবজেক্টটি উপস্থাপন" করার চেষ্টা করার পরামর্শ দিচ্ছি, এবং যদি আপনি কোনও ভাল প্যারামিটার অবজেক্ট তৈরি করতে না পান তবে অন্যান্য বিকল্পগুলিতে কেবল ফলব্যাক।
ডগলাস লিডার

4
চমৎকার উত্তর। আপনি যদি সি # সিনট্যাকটিক সুগারের পূর্বে রিফ্যাক্টরিংয়ের ব্যাখ্যাটি উল্লেখ করেছেন, তবে এটি উচ্চতর আইএমএইচও ভোট দেওয়া হত।
আরপট্টবী

10
ওহ! "1 এর জন্য" নতুন টাইপের নামটি সুস্পষ্ট হলে আপনি জানবেন যে ঠিকই আপনি এটি পেয়েছেন ""
শান ম্যাকমিলান

20

যদি এটি কোনও নির্মাণকারী, বিশেষত যদি একাধিক ওভারলোডেড ভেরিয়েন্ট থাকে তবে আপনার বিল্ডার প্যাটার্নটি দেখতে হবে:

Foo foo = new Foo()
          .configBar(anything)
          .configBaz(something, somethingElse)
          // and so on

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


দুর্দান্ত উত্তর। "(ক্লাসে প্যারামিটারগুলি রাখুন") প্রত্যেকে (আমাকে সহ) প্রত্যুত্তর দেওয়ার চেয়ে সম্ভবত আরও প্রাসঙ্গিক।
ওয়াউটার লাইভেন্স

1
আপনার বর্গকে কেবল কনস্ট্রাক্টরের কাছে খুব বেশি প্যারামিটারে যেতে না পারার জন্য পরিবর্তন করা সম্ভবত খারাপ ধারণা।
আউটলা প্রোগ্রামার 16

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

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

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

10

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

যেমন পরিবর্তে:

driver.connect(host, user, pass)

আপনি ব্যবহার করতে পারেন

config = new Configuration()
config.setHost(host)
config.setUser(user)
config.setPass(pass)
driver.connect(config)

YMMV


5
আমি অবশ্যই কোডের প্রথম অংশটি আরও পছন্দ করব like আমি সম্মত হই, এখানে একটি নির্দিষ্ট সীমা রয়েছে, যার উপরে নম্বর ছাঁটি পরামিতিগুলি কুৎসিত হয়ে যায়, তবে আমার স্বাদে, 3 গ্রহণযোগ্য হবে।
blabla999

10

এটি ফোলার এবং বেক বই থেকে উদ্ধৃত হয়েছে: "রিফ্যাক্টরিং"

দীর্ঘ পরামিতি তালিকা

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


7

আমি কোনও বুদ্ধিমান-ক্র্যাকের মতো শব্দ করতে চাই না, তবে আপনি যে তথ্যটি প্রায় কাছাকাছি চলেছেন তা সত্যই চারপাশে পাস করা উচিত তা নিশ্চিত করার জন্য আপনারও পরীক্ষা করা উচিত: কোনও কনস্ট্রাক্টরের কাছে স্টাফ পাস করা (বা সেই বিষয়ে পদ্ধতিতে) কিছুটা গন্ধ লাগে একটি বস্তুর আচরণের উপর সামান্য জোর দেওয়া ।

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

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


7

আমি যখন দীর্ঘ প্যারামিটারের তালিকা দেখি, আমার প্রথম প্রশ্নটি এই ফাংশন বা অবজেক্টটি খুব বেশি করছে কিনা। বিবেচনা:

EverythingInTheWorld earth=new EverythingInTheWorld(firstCustomerId,
  lastCustomerId,
  orderNumber, productCode, lastFileUpdateDate,
  employeeOfTheMonthWinnerForLastMarch,
  yearMyHometownWasIncorporated, greatGrandmothersBloodType,
  planetName, planetSize, percentWater, ... etc ...);

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

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

 Order order=new Order(customerName, customerAddress, customerCity,
   customerState, customerZip,
   orderNumber, orderType, orderDate, deliveryDate);

আমাদের থাকতে পারত:

Customer customer=new Customer(customerName, customerAddress,
  customerCity, customerState, customerZip);
Order order=new Order(customer, orderNumber, orderType, orderDate, deliveryDate);

অবশ্যই আমি ফাংশনগুলিকে পছন্দ করি যা কেবল 1 বা 2 বা 3 পরামিতি নেয়, কখনও কখনও আমাদের তা গ্রহণ করতে হয়, বাস্তবিকভাবে, এই ফাংশনটি একগুচ্ছ লাগে এবং এটির সংখ্যাটি সত্যই জটিলতা তৈরি করে না। উদাহরণ স্বরূপ:

Employee employee=new Employee(employeeId, firstName, lastName,
  socialSecurityNumber,
  address, city, state, zip);

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

যখন আমার প্যারামিটারের তালিকাগুলি দীর্ঘতর হয়, আমি ক্ষেত্রগুলিকে বিভিন্ন ডেটা ধরণের দিতে পারলে আমি বেশি পছন্দ করি। আমি যখন কোনও ফাংশন দেখতে পাই তখন পছন্দ করুন:

void updateCustomer(String type, String status,
  int lastOrderNumber, int pastDue, int deliveryCode, int birthYear,
  int addressCode,
  boolean newCustomer, boolean taxExempt, boolean creditWatch,
  boolean foo, boolean bar);

এবং তারপরে আমি দেখতে পাচ্ছি এটি দিয়ে:

updateCustomer("A", "M", 42, 3, 1492, 1969, -7, true, false, false, true, false);

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


5

যদি কিছু কনস্ট্রাক্টর প্যারামিটারগুলি alচ্ছিক হয় তবে এটি কোনও বিল্ডার ব্যবহার করা বোধগম্য হয়, যা কনস্ট্রাক্টরে প্রয়োজনীয় প্যারামিটারগুলি পেতে পারে এবং বিল্ডারকে ফেরত দেওয়ার জন্য এই জাতীয় ব্যবহারের পদ্ধতি রয়েছে:

return new Shniz.Builder(foo, bar).baz(baz).quux(quux).build();

এর বিস্তারিত বিবরণ কার্যকর জাভাতে বর্ণিত হয়েছে, দ্বিতীয় সংস্করণ, পি। ১১. পদ্ধতির যুক্তিগুলির জন্য, একই বই (পৃষ্ঠা 189) প্যারামিটার তালিকা সংক্ষিপ্ত করার জন্য তিনটি পদ্ধতির বর্ণনা দিয়েছে:

  • একাধিক পদ্ধতিতে পদ্ধতিটি ভাঙ্গুন যা কম যুক্তি গ্রহণ করে
  • পরামিতিগুলির গোষ্ঠী উপস্থাপনের জন্য স্থিতিশীল সহায়ক সদস্য শ্রেণি তৈরি করুন DinoDonkey, dinoএবং এর পরিবর্তে একটি পাস করুনdonkey
  • যদি প্যারামিটারগুলি alচ্ছিক হয় তবে উপরের বিল্ডারটি সমস্ত প্যারামিটারের জন্য কোনও বস্তুর সংজ্ঞা প্রদান করে, প্রয়োজনীয়গুলি সেট করে এবং তারপরে এটিতে কিছু নির্বাহের পদ্ধতি কল করে পদ্ধতিগুলির জন্য গ্রহণ করা যেতে পারে

4

আমি ডিফল্ট কনস্ট্রাক্টর এবং সম্পত্তি সেটেটর ব্যবহার করব। এটি স্বয়ংক্রিয়ভাবে করতে সি # 3.0 এর কিছু সুন্দর বাক্য গঠন রয়েছে।

return new Shniz { Foo = foo,
                   Bar = bar,
                   Baz = baz,
                   Quuz = quux,
                   Fred = fred,
                   Wilma = wilma,
                   Barney = barney,
                   Dino = dino,
                   Donkey = donkey
                 };

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


2
এটি নতুন কোনও শ্নিজ () -র কোনও অস্তিত্বের অনুমতি দেবে। একটি ভাল ওও বাস্তবায়ন অসম্পূর্ণ অবস্থায় থাকা অবজেক্টগুলির সম্ভাবনা হ্রাস করার চেষ্টা করবে।
অ্যান্থনিডব্লু জোন্স 13:25

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

4

আপনি একটি উত্তরের উত্তরের জন্য পর্যাপ্ত তথ্য সরবরাহ করেন নি। একটি দীর্ঘ প্যারামিটার তালিকা অন্তর্নিহিত খারাপ নয়।

শ্নিজ (ফু, বার, বাজ, কোয়াক্স, ফ্রেড, উইলমা, বার্নি, দিনো, গাধা)

হিসাবে ব্যাখ্যা করা যেতে পারে:

void Shniz(int foo, int bar, int baz, int quux, int fred, 
           int wilma, int barney, int dino, int donkey) { ...

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

// old way
Shniz(1,2,3,2,3,2,1,2);
Shniz(1,2,2,3,3,2,1,2); 

//versus
ShnizParam p = new ShnizParam { Foo = 1, Bar = 2, Baz = 3 };
Shniz(p);

বিকল্পভাবে যদি আপনার কাছে থাকে:

void Shniz(Foo foo, Bar bar, Baz baz, Quux quux, Fred fred, 
           Wilma wilma, Barney barney, Dino dino, Donkey donkey) { ...

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

অতিরিক্তভাবে, কিছু পরামিতিগুলি alচ্ছিক? পদ্ধতিতে ওভাররাইডের কী রয়েছে (একই পদ্ধতির নাম, তবে বিভিন্ন পদ্ধতির স্বাক্ষর?) এই ধরণের বিশদ বিবরণে সর্বোত্তম উত্তরটি কী তা বোঝায়।

* একটি সম্পত্তি ব্যাগ পাশাপাশি দরকারী হতে পারে, কিন্তু নির্দিষ্টভাবে দেওয়া ভাল নেই যে সেখানে কোনও ব্যাকগ্রাউন্ড দেওয়া হয়নি।

আপনি দেখতে পাচ্ছেন, এই প্রশ্নের 1 টিরও বেশি সঠিক উত্তর রয়েছে। তোমারটা নাও.


3

আপনি আপনার প্যারামিটারকে গুণিতক অর্থপূর্ণ কাঠামো / শ্রেণিতে (যদি সম্ভব হয়) তে গ্রুপ করার চেষ্টা করতে পারেন।


2

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

যদি প্যারামিটারগুলির সেটটি কোনও অর্থবহ অবজেক্টে তৈরি করা না যায় তবে এটি সম্ভবত একটি চিহ্ন যা Shnizখুব বেশি করে চলেছে এবং রিফ্যাক্টরিংটিতে পৃথক উদ্বেগের মধ্যে পদ্ধতিটি ভেঙে দেওয়া উচিত।


2

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


2

যদি আপনার ভাষা এটি সমর্থন করে, নামযুক্ত প্যারামিটারগুলি ব্যবহার করুন এবং যতগুলি সম্ভব optionচ্ছিক (যুক্তিসঙ্গত ডিফল্ট সহ) তৈরি করুন make


1

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


1

কনস্ট্রাক্টরগুলিতে একবারে সেট না করে সম্পত্তি / সেটটারের মাধ্যমে এটি করা সম্পর্কে কীভাবে ? আমি কিছু .NET ক্লাস দেখেছি যা এই পদ্ধতিকে Processশ্রেণীর মতো ব্যবহার করে :

        Process p = new Process();

        p.StartInfo.UseShellExecute = false;
        p.StartInfo.CreateNoWindow = true;
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.FileName = "cmd";
        p.StartInfo.Arguments = "/c dir";
        p.Start();

3
সহজেই সহজেই এটি করার জন্য সি # 3 এর একটি বাক্য গঠন রয়েছে: অবজেক্ট ইনিশিয়ালাইজার্স।
ডেরেন টমাস

1

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


1

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

বৃহত্তর চেয়ে ছোট ক্লাস / পদ্ধতি পছন্দ করুন। একক দায়িত্বের নীতিটি মনে রাখবেন।


উদাহরণস্বরূপ সদস্য এবং বৈশিষ্ট্যগুলির সাথে সমস্যাটি হ'ল তারা 1) লিখিত হতে হবে, 2) সেট করা নাও যেতে পারে। কোন কনস্ট্রাক্টরের ক্ষেত্রে, কিছু ক্ষেত্র রয়েছে যা আমি নিশ্চিত করতে চাই যে কোনও দৃষ্টান্ত উপস্থিত হওয়ার আগে তা পূরণ করা হবে।
পুনরাবৃত্তি

@ রিসার্সিভ - আমি অসম্মতি জানাই যে ক্ষেত্র / বৈশিষ্ট্যগুলি সর্বদা লিখনযোগ্য হবে। ছোট ক্লাসের জন্য প্রচুর সময় পাওয়া যায় যেখানে কেবলমাত্র পাঠ্য সদস্যরা তা বোঝায়।
ব্রায়ান রাসমুসেন

1

দীর্ঘ যুক্ত (বা এমনকি সংক্ষিপ্ত!) পরামিতি তালিকাগুলি নিষ্ক্রিয় করার জন্য নামযুক্ত যুক্তিগুলি একটি ভাল বিকল্প (তাদের নির্মাণের ক্ষেত্রে একটি ভাষা অনুমান করা) পাশাপাশি শ্রেণিবদ্ধের বৈশিষ্ট্যগুলি অস্তিত্ব বজায় রাখার জন্য প্রয়োজনীয়তা চাপিয়ে না দিয়ে অবিচ্ছিন্ন হতে দেয় আংশিক-নির্মিত অবস্থায় state

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


0

এটি আপনার কী ধরণের আর্গুমেন্টের উপর নির্ভর করে, তবে সেগুলি যদি বুলিয়ান মান / বিকল্পগুলি থেকে থাকে তবে আপনি একটি পতাকা এনুম ব্যবহার করতে পারেন?


0

আমি মনে করি যে সমস্যাটি আপনি শ্রেণীর সাথে সমাধান করার চেষ্টা করছেন তার ডোমেনটির সাথে গভীরভাবে আবদ্ধ।

কিছু ক্ষেত্রে, 7-প্যারামিটার নির্মাতা একটি খারাপ শ্রেণির শ্রেণিবিন্যাসের ইঙ্গিত দিতে পারে: সেক্ষেত্রে উপরে প্রস্তাবিত সাহায্যকারী কাঠামো / শ্রেণিটি সাধারণত একটি ভাল পদ্ধতির হয় তবে তারপরে আপনিও প্রচুর স্ট্রাক্ট দিয়ে শেষ করতে চান যা কেবল সম্পত্তি ব্যাগ are এবং দরকারী কিছু করবেন না। 8-টি আর্গুমেন্ট কনস্ট্রাক্টর এটিও ইঙ্গিত করতে পারে যে আপনার ক্লাসটি খুব জেনেরিক / খুব বেশি উদ্দেশ্যমূলক তাই এটি সত্যই কার্যকর হওয়ার জন্য প্রচুর বিকল্পের প্রয়োজন। সেক্ষেত্রে আপনি হয় ক্লাস রিফেক্টর করতে পারেন বা স্ট্যাটিক কনস্ট্রাক্টর বাস্তবায়ন করতে পারেন যা প্রকৃত জটিল নির্মাণকারীদের গোপন করে: যেমন। Shniz.NewBaz (foo, bar) প্রকৃত নির্মাণকারীকে ডান পরামিতিগুলি দিয়ে যেতে পারে actually


0

একটি বিবেচনাটি হ'ল অবজেক্টটি তৈরি হওয়ার পরে কোনটি মানটি কেবল পঠনযোগ্য?

পাবলিকলি রাইটেবল প্রপার্টি সম্ভবত নির্মাণের পরে নির্ধারিত হতে পারে।

শেষ পর্যন্ত মানগুলি কোথা থেকে আসে? সম্ভবত কিছু মান সত্যই বাহ্যিক যেখানে অন্যরা সত্যই কিছু কনফিগারেশন বা বৈশ্বিক ডেটা থেকে থাকে যা গ্রন্থাগার দ্বারা রক্ষণাবেক্ষণ করা হয়।

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

অবজেক্টটিকে একটি সম্পূর্ণ রাষ্ট্র এবং সমস্ত প্রকৃতপক্ষে প্রকৃতির বাহ্যিক হওয়ার জন্য 7 বা ততোধিক পরামিতিগুলির প্রয়োজন এমন কোনও অবজেক্ট থাকা সত্যিই আশ্চর্যজনক হবে।


0

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

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

নিচে দেখ :

public class Toto {
    private final String state0;
    private final String state1;
    private final String state2;
    private final String state3;

    public Toto(String arg0, String arg1, String arg2, String arg3) {
        this.state0 = arg0;
        this.state1 = arg1;
        this.state2 = arg2;
        this.state3 = arg3;
    }

    public static class TotoBuilder {
        private String arg0;
        private String arg1;
        private String arg2;
        private String arg3;

        public TotoBuilder addArg0(String arg) {
            this.arg0 = arg;
            return this;
        }
        public TotoBuilder addArg1(String arg) {
            this.arg1 = arg;
            return this;
        }
        public TotoBuilder addArg2(String arg) {
            this.arg2 = arg;
            return this;
        }
        public TotoBuilder addArg3(String arg) {
            this.arg3 = arg;
            return this;
        }

        public Toto newInstance() {
            // maybe add some validation ...
            return new Toto(this.arg0, this.arg1, this.arg2, this.arg3);
        }
    }

    public static void main(String[] args) {
        Toto toto = new TotoBuilder()
            .addArg0("0")
            .addArg1("1")
            .addArg2("2")
            .addArg3("3")
            .newInstance();
    }

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