একাধিক পদ্ধতিতে স্যুইচ করার সুবিধা


12

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

এখানে আমাদের প্রতিযোগিতামূলক কোড প্রস্তাবনাগুলি (পিএইচপি উদাহরণ হিসাবে ব্যবহৃত হয়, তবে আরও সার্বজনীন প্রয়োগ করতে পারে):

class Switch {
   public function go($arg) {
      switch ($arg) {
         case "one":
            echo "one\n";
         break;
         case "two":
            echo "two\n";
         break;
         case "three":
            echo "three\n";
         break;
         default:
            throw new Exception("Unknown call: $arg");
         break;
      }
   }
}

class Oop {
   public function go_one() {
      echo "one\n";
   }
   public function go_two() {
      echo "two\n";
   }
   public function go_three() {
      echo "three\n";
   }
   public function __call($_, $__) {
      throw new Exception("Unknown call $_ with arguments: " . print_r($__, true));
   }
}

তার যুক্তির অংশটি ছিল "জেনেরিক __call () ম্যাজিক পদ্ধতিতে আপনার যা আছে তার তুলনায়" এটি (স্যুইচ পদ্ধতি) ডিফল্ট কেসগুলি হ্যান্ডেল করার অনেক ক্লিনার উপায়। "

আমি পরিষ্কার সম্পর্কে দ্বিমত পোষণ করি এবং প্রকৃতপক্ষে কলটি পছন্দ করি তবে অন্যরা কী বলবে তা আমি শুনতে চাই।

Oopপ্রকল্পের সমর্থনে আমি যুক্তিগুলি উপস্থিত করতে পারি :

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

Switchপ্রকল্পের সমর্থনে আমি যুক্তিগুলি উপস্থিত করতে পারি :

  • তর্কের খাতিরে, একটি ডিফল্ট (অজানা) অনুরোধের সাথে সাফ করার ক্লিনার পদ্ধতি
  • কম যাদুকর বলে মনে হচ্ছে এটি অপরিচিত বিকাশকারীদের আরও স্বাচ্ছন্দ্য বোধ করতে পারে

কারও পক্ষে দু'পক্ষের জন্য কিছু যোগ করার আছে? আমি তার জন্য একটি ভাল উত্তর পেতে চাই।


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

__ক্যাল খারাপ। এটি পুরোপুরি পারফরম্যান্সকে হত্যা করে এবং আপনি এটি এমন পদ্ধতিতে কল করতে ব্যবহার করতে পারেন যা বাইরের কলকারীদের কাছে ব্যক্তিগত বলে মনে করা হয়।

Oopপ্রতিটি পদ্ধতি বর্ণনা করার জন্য পিএইচপিডোক রাখতে দেয় যা কিছু আইডিই (যেমন, নেটবিয়ান) দ্বারা পার্স করা যায়।
বাইনারিএলভি

fluffycat.com/PHP- ডিজাইন- প্যাটার্নস / ......... .. স্পষ্টতই স্যুইচ সমস্ত দক্ষ নয়। -1

@ গর্ডনএম: যদি প্রশ্নে শ্রেণীর কোনও ব্যক্তিগত পদ্ধতি না থাকে তবে কী হবে?
জ্যাব

উত্তর:


10

একটি স্যুইচকে ওওপি হিসাবে বিবেচনা করা হয় না কারণ প্রায়শই পলিমারফিজম কৌশলটি করতে পারে।

আপনার ক্ষেত্রে, একটি ওওপি বাস্তবায়ন এটি হতে পারে:

class Oop 
{
  protected $goer;

  public function __construct($goer)
  {
    $this->goer = $goer;
  }

  public function go()
  {
    return $this->goer->go();
  }
}

class Goer
{
  public function go()
  {
    //...
  }
}

class GoerA extends Goer
{
  public function go()
  {
    //...
  }
}

class GoerB extends Goer
{
  public function go()
  {
    //...
  }
}

class GoerC extends Goer
{
  public function go()
  {
    //...
  }
}


$oop = new Oop(new GoerB());
$oop->go();

1
বহুবর্ষই সঠিক উত্তর the +1
রেন হেনরিচস

2
এটি ভাল, তবে ডাউনসাইডটি কোডের একটি অতিরিক্ত-বিস্তার is আপনার প্রতিটি পদ্ধতির জন্য একটি ক্লাস থাকতে হবে এবং এটি মোকাবেলায় আরও কোড .. এবং আরও মেমরি। খুশির মাধ্যম কি নেই?
বিস্ফোরণ পিল

8

এই উদাহরণের জন্য:

class Switch
{
    public function go($arg)
    {
        echo "$arg\n";
    }
}

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

স্যুইচ স্টেটমেন্টগুলি প্রায়শই অনুপস্থিত শ্রেণি বা শ্রেণিবিন্যাসের ইঙ্গিত, তবে অগত্যা নয়। কখনও কখনও একটি স্যুইচ স্টেটমেন্টটি কেবল একটি স্যুইচ স্টেটমেন্ট হয়


"যন্ত্রাংশ নয়, শব্দার্থবিজ্ঞানের জন্য" +1
জাভিয়র

1

সম্ভবত কোনও উত্তর নয়, তবে নন-স্যুইচ কোডের ক্ষেত্রে মনে হচ্ছে এটি আরও ভাল ম্যাচ হবে:

class Oop {
  /**
   * User calls $oop->go('one') then this function will determine if the class has a 
   * method 'go_one' and call that. If it doesn't, then you get your error.
   * 
   * Subclasses of Oop can either overwrite the existing methods or add new ones.
   */
  public function go($arg){

    if(is_callable(array($this, 'go_'. $arg))){
      return call_user_func(array($this, 'go_'. $arg));
    }

    throw new Exception("Unknown call: $arg");
  }

  public function go_one() {
    echo "one\n";
  }
  public function go_two() {
    echo "two\n";
  }
  public function go_three() {
    echo "three\n";
  }
}

ধাঁধা মূল্যায়ন করার একটি বড় অংশ কি যখন আপনি তৈরি করতে প্রয়োজন হয় NewSwitchবা NewOop। আপনার প্রোগ্রামারদের কি কোনও পদ্ধতি বা অন্য কোনও উপায়ে হুপ করে যেতে হবে? আপনার নিয়মগুলি পরিবর্তন হলে কী হয়


আমি আপনার উত্তরটি পছন্দ করি - একই পোস্ট করতে যাচ্ছিল তবে আপনার দ্বারা নিনজা হয়েছে। আমি মনে করি উত্তরাধিকারসূত্রে সুরক্ষিত পদ্ধতিতে সমস্যা এড়াতে আপনার পদ্ধতি_অস্তিত্বগুলিকে is_clalable () এ পরিবর্তন করা উচিত এবং আপনি আপনার কোডটি আরও পঠনযোগ্য করে তুলতে কল_উজার_ফুনকে $ এটি -> go 'go _' to আরগ} () এ পরিবর্তন করতে পারেন। আরেকটি জিনিস - ম্যাবি ম্যাজিক পদ্ধতিটি __call কেন খারাপ - একটি মন্তব্য যুক্ত করুন - এটি object বস্তু বা এর উদাহরণের কার্যকারিতাটি ধ্বংস করে দেয় কারণ এটি সর্বদা সত্য ফিরে আসবে।

আমি আপডেট হয়েছি is_callable, তবে কল_উজার_ফানক ছেড়েছি (এই প্রশ্নের অংশ নয়), পাশ করার জন্য অন্যান্য যুক্তি থাকতে পারে। তবে এখন এটি প্রোগ্রামারদের কাছে চলে গেছে, আমি অবশ্যই নিশ্চিত হয়েছি যে @ আন্দ্রেয়ার উত্তর আরও ভাল :)
রব

0

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


0

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

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


আপনি যদি ইন্টারফেসটি পরিবর্তন না করেন এবং কোনও সাবক্লাসের নিজস্ব প্রয়োগ রয়েছে তবে go()এটি সহজেই লিসকভ সাবস্টিটিউশন নীতিটি বেহাল করে দিতে পারে। আপনার কাছে বেশি কার্যকারিতা যোগ করছি যদি go(), আপনি না যতদূর আমি concerend আছি যেমন ইন্টারফেস পরিবর্তন করতে চান।
বিস্ফোরণ বড়ি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.