কীভাবে অতিরিক্ত পদ্ধতি বোঝা এড়ানো যায়?


16

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

এটি দীর্ঘ বিবর্তনের (উত্তরাধিকারের কোড) এবং এই চিন্তার (আমি বিশ্বাস করি) ফলাফল:

" একটি পদ্ধতি এম আছে যা এ। করে। আমার এ + বি করা দরকার OK ঠিক আছে, আমি জানি ... আমি এম তে একটি নতুন প্যারামিটার যুক্ত করব, তার জন্য একটি নতুন পদ্ধতি তৈরি করব, এম থেকে নতুন পদ্ধতিতে কোড সরান code আরও একটি প্যারামিটার সহ, সেখানে A + B করুন এবং নতুন প্যারামিটারের একটি ডিফল্ট মান সহ এম থেকে নতুন পদ্ধতিটি কল করুন ""

এখানে জাভা-জাতীয় ভাষায় একটি উদাহরণ দেওয়া হয়েছে:

class DocumentHome {

  (...)

  public Document createDocument(String name) {
    // just calls another method with default value of its parameter
    return createDocument(name, -1);
  }

  public Document createDocument(String name, int minPagesCount) {
    // just calls another method with default value of its parameter
    return createDocument(name, minPagesCount, false);
  }

  public Document createDocument(String name, int minPagesCount, boolean firstPageBlank) {
    // just calls another method with default value of its parameter
    return createDocument(name, minPagesCount, false, "");
  }

  public Document createDocument(String name, int minPagesCount, boolean firstPageBlank, String title) {
    // here the real work gets done
    (...)
  }

  (...)
}

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

এটি কীভাবে আরও ভাল করা যায় তা এখানে কয়েকটি উপায়:

  1. একটি প্যারামিটার অবজেক্ট পরিচয় করিয়ে দিন:

    class DocumentCreationParams {
    
      String name;
      int minPagesCount;
      boolean firstPageBlank;
      String title;
    
      (...)
    }
    
    class DokumentHome {
    
      public Document createDocument(DocumentCreationParams p) {
        // here the real work gets done
        (...)
      }
    }
    
  2. DocumentHomeআমরা কল করার আগে অবজেক্টটিতে পরামিতিগুলি সেট করুনcreateDocument()

      @In
      DocumentHome dh = null;
    
      (...)
    
      dh.setName(...);
      dh.setMinPagesCount(...);
      dh.setFirstPageBlank(...);
    
      Document newDocument = dh.createDocument();
    
  3. কাজটি বিভিন্ন পদ্ধতিতে পৃথক করুন এবং প্রয়োজনীয় হিসাবে তাদের কল করুন:

      @In
      DocumentHome dh = null;
    
      Document newDocument = dh.createDocument();
      dh.changeName(newDocument, "name");
      dh.addFirstBlankPage(newDocument);
      dh.changeMinPagesCount(new Document, 10);
    

আমার প্রশ্নগুলো:

  1. বর্ণিত সমস্যাটি কি আসলেই সমস্যা?
  2. প্রস্তাবিত সমাধানগুলি সম্পর্কে আপনার কী ধারণা? আপনি কোনটি পছন্দ করবেন (আপনার অভিজ্ঞতার ভিত্তিতে)?
  3. আপনি কি অন্য কোন সমাধান সম্পর্কে চিন্তা করতে পারেন?

1
আপনি কোন ভাষাটিকে টার্গেট করছেন বা এটি কেবল জেনারেল?
কিনার্ড

কোনও নির্দিষ্ট ভাষা নেই, কেবল সাধারণ। অন্যান্য ভাষার বৈশিষ্ট্যগুলি এতে কীভাবে সহায়তা করতে পারে তা নির্দ্বিধায় অনুভব করুন।
Ytus

যেমন আমি এখানে বলেছি প্রোগ্রামার্স.স্ট্যাকেক্সেঞ্জারভিউ / প্রশ্নগুলি / ২৩50০৯6/২ সি # এবং সি ++ এর কিছু বৈশিষ্ট্য রয়েছে।
কেনার্ড

এটি অত্যন্ত পরিষ্কার যে এই প্রশ্নটি এমন প্রতিটি ভাষার ক্ষেত্রে প্রযোজ্য যা এই জাতীয় পদ্ধতিতে ওভারলোডিংকে সমর্থন করে।
ডক ব্রাউন

1
@ ডকব্রাউন ঠিক আছে, তবে প্রতিটি ভাষা একই বিকল্পকে সমর্থন করে না;)
কেনার্ড

উত্তর:


20

সম্ভবত বিল্ডার প্যাটার্ন চেষ্টা করে দেখুন ? (দ্রষ্টব্য: মোটামুটি এলোমেলো গুগল ফলাফল :)

var document = new DocumentBuilder()
                   .FirstPageBlank()
                   .Name("doc1final(2).doc")
                   .MinimumNumberOfPages(4)
                   .Build();

আপনার দেওয়া বিকল্পগুলির তুলনায় আমি কেন বিল্ডারকে পছন্দ করি তার পুরো পালটা দিতে পারছি না, তবে আপনি প্রচুর কোড সহ একটি বড় সমস্যা চিহ্নিত করেছেন। যদি আপনি মনে করেন যে কোনও পদ্ধতির জন্য আপনার দুটি পরামিতির বেশি প্রয়োজন আপনার সম্ভবত আপনার কোডটি ভুলভাবে কাঠামোগত করা হয়েছে (এবং কিছুতে তর্ক হবে!)।

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

আপনার অন্যান্য চেষ্টাগুলি আমার দিকে তাকিয়ে আছে যেন কেউ বিল্ডার প্যাটার্নে পৌঁছায় তবে সেখানে না পৌঁছা :)


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

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

1

প্যারামিটার অবজেক্ট ব্যবহার করা পদ্ধতিগুলির অত্যধিক লোড এড়াতে ভাল উপায়:

  • এটি কোড সাফ করে
  • কার্যকারিতা থেকে ডেটা পৃথক করে
  • কোডটি আরও রক্ষণাবেক্ষণযোগ্য করে তোলে

আমি তবে এটিকে নিয়ে বেশি দূরে যাব না।

এখানে ওভারলোড থাকা এবং কোনও খারাপ জিনিস নেই। এটি প্রোগ্রামিং ভাষা দ্বারা সমর্থিত, সুতরাং এটি আপনার সুবিধার্থে ব্যবহার করুন।

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

শুধু আমার 2 সেন্ট।


0

আমি সতর্কতার সাথে কোডটি নিয়ে কোনও বড় সমস্যা দেখতে পাচ্ছি না। সি # এবং সি ++ এ আপনি alচ্ছিক প্যারামিটারগুলি ব্যবহার করতে পারেন, এটি বিকল্প হবে তবে যতদূর আমি জানি জাভা এই ধরণের পরামিতিগুলিকে সমর্থন করে না।

সি # তে আপনি সমস্ত ওভারলোডগুলি ব্যক্তিগত করতে পারেন এবং optionচ্ছিক পরামিতিগুলির সাথে একটি পদ্ধতি স্টাফকে কল করার জন্য সর্বজনীন।

আপনার প্রশ্নের দ্বিতীয় অংশের উত্তর দেওয়ার জন্য, আমি প্যারামিটার অবজেক্ট বা একটি অভিধান / হ্যাশম্যাপ নেব।

তাই ভালো:

class DokumentHome {

  public Document createDocument(Map<string, object> params) {
    if (params.containsKey("yourkey")) {
       // do that
    }
    // here the real work gets done
    (...)
  }
}

দাবি অস্বীকার হিসাবে, আমি প্রথমে একটি সি # এবং জাভাস্ক্রিপ্ট প্রোগ্রামার এবং তারপরে একটি জাভা প্রোগ্রামার।


4
এটি একটি সমাধান, তবে আমি এটির একটি ভাল সমাধান মনে করি না (কমপক্ষে, এমন প্রসঙ্গে নয় যেখানে টাইপসফটি আশা করা যায়)।
ডক ব্রাউন

সেটা ঠিক. এই জাতীয় ক্ষেত্রে, আমি ওভারলোডেড পদ্ধতি বা alচ্ছিক পরামিতি পছন্দ করি।
কেনার্ড

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

অভিধানটি কেবল সত্যিকারের al চ্ছিক পরামিতিগুলির জন্য ব্যবহার করুন সুতরাং বেসিক ব্যবহারের ক্ষেত্রে খুব বেশি ডকুমেন্টেশন পড়ার দরকার নেই।
user949300

0

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

আপনার ক্ষেত্রে, আমার নিম্নলিখিত পদ্ধতিগুলির সাথে একজন নির্মাতা থাকবেন:

SetTitle (Document document) { ... }
SetFirstPageBlank (Document document) { ... }
SetMinimumPageCount (Document document) { ... }

তারপরে আপনি নির্মাতাকে নিম্নলিখিত উপায়ে ব্যবহার করতে পারেন:

_builder.SetTitle(document);
_builder.SetFirstPageBlank(document);

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


0

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

আপনি যদি কোনও ডকুমেন্ট তৈরির জন্য কোনও সাধারণ নির্মাতা তৈরি করেন এবং অ্যাপ্লিকেশনের বিভিন্ন অংশে (শ্রেণি) এই কোডটি ছড়িয়ে দেন তবে তা কঠিন হবে:

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

তবে এটি ওপি প্রশ্নের উত্তর দেয় না।

ওভারলোডের বিকল্প

কিছু বিকল্প:

  • পদ্ধতি নাম পুনঃনামকরণ : একই পদ্ধতি নাম কিছু বিভ্রান্তির সৃষ্টি করছে, তাহলে একটি অর্থপূর্ণ নাম টা ভাল তৈরি করতে চেয়ে পদ্ধতি নামান্তর করতে চেষ্টা createDocument: মত, createLicenseDriveDocument, createDocumentWithOptionalFields,, ইত্যাদি অবশ্যই, এই আপনি দৈত্য পদ্ধতি নাম হতে পারে তাই এই নয় সব ক্ষেত্রে একটি সমাধান।
  • স্থির পদ্ধতি ব্যবহার করুন । উপরোক্ত প্রথম বিকল্পের সাথে তুলনা করা গেলে এই পদ্ধতির ধরণ একই রকম। আপনি প্রতিটি ক্ষেত্রে একটি অর্থপূর্ণ নাম ব্যবহার এবং এর একটি স্ট্যাটিক পদ্ধতি থেকে দস্তাবেজ instantiate করতে Documentমত: Document.createLicenseDriveDocument()
  • একটি সাধারণ ইন্টারফেস তৈরী : আপনি একক পদ্ধতি নামক তৈরি করতে পারেন createDocument(InterfaceDocument interfaceDocument)এবং বিভিন্ন তৈরি বাস্তবায়নের জন্য InterfaceDocument। উদাহরণস্বরূপ প্রতি: createDocument(new DocumentMinPagesCount("name"))। অবশ্যই প্রতিটি ক্ষেত্রে আপনার একক প্রয়োগের প্রয়োজন নেই, কারণ আপনি প্রতিটি বাস্তবায়নের জন্য একাধিক কনস্ট্রাক্টর তৈরি করতে পারেন, এমন কয়েকটি ক্ষেত্রকে গোষ্ঠীভুক্ত করতে পারেন যা সেই বাস্তবায়নটি বোঝায়। এই নিদর্শনটিকে দূরবীন নির্মাণকারী বলা হয় ।

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

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