কোডে স্যুইচ দূর করার উপায় [বন্ধ]


175

কোডে স্যুইচ ব্যবহার বাদ দেওয়ার উপায়গুলি কী কী?


18
আপনি যথাযথভাবে ব্যবহার করার সময় কেন স্যুইচগুলি অপসারণ করতে চান? আপনার প্রশ্নটি বিস্তারিতভাবে বর্ণনা করতে পারেন।
আরবি।

আমি এই প্রশ্নটিকে সম্প্রদায়কে সম্পাদনযোগ্য করে তোলার পক্ষে ভোট দিচ্ছি কারণ প্রত্যেকে একই কথা বলছে এবং সমস্ত মতামত একীভূত করা ভাল লাগবে;)
জোশ

2
স্যুইচ অন্যান্য নির্দেশাবলীর মতো আদর্শ নয়। উদাহরণস্বরূপ, সি ++ এ আপনি সম্ভবত 'ব্রেক' ভুলে যাবেন এবং তারপরে আপনার অপ্রত্যাশিত ফলাফল হবে। তদ্ব্যতীত, এই 'বিরতি' একটি GOTO এর সাথে খুব মিল। আমি কখনও সুইচগুলি অপসারণ করার চেষ্টা করি নি, তবে নিশ্চিতভাবে সেগুলি আমার প্রিয় নির্দেশ নয়। ;)

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

2
আপনি বিস্মিত হতে পারেন: চৌকস সম্প্রদায়ের প্রচুর উল্লেখযোগ্য প্রোগ্রামার রয়েছে আইএফ-বিরোধী প্রচারণায় যোগদান
মাইক এ

উত্তর:


267

সুইচ-বিবৃতি একটি antipattern কোনটাই না, কিন্তু আপনি কোডিং করছি অবজেক্ট ওরিয়েন্টেড যদি আপনি একটি সুইচ ব্যবহার ভাল সমাধান হয় বিবেচনা করা উচিত পলিমরফিজম একটি সুইচ বিবৃতি ব্যবহারের পরিবর্তে।

বহুকর্ম সহ, এটি:

foreach (var animal in zoo) {
    switch (typeof(animal)) {
        case "dog":
            echo animal.bark();
            break;

        case "cat":
            echo animal.meow();
            break;
    }
}

এটি হয়ে:

foreach (var animal in zoo) {
    echo animal.speak();
}

2
স্ট্যাকওভারফ্লো / প্রশ্ন / 7474৪৩৩৯ / তে একই জাতীয় পরামর্শের কারণে আমাকে ভিত্তিযুক্ত করা হচ্ছে তাই অনেক পিপিএল বহুবর্ষে বিশ্বাস করে না :) খুব ভাল উদাহরণ।
নাজগোব

30
-1: আমি কখনই এর সাথে স্যুইচ স্টেটমেন্ট ব্যবহার করি নি typeofএবং এই উত্তরটি অন্য পরিস্থিতিতে স্যুইচ স্টেটমেন্টগুলির আশেপাশে কাজ করার উপায় বা কারণগুলি নির্দেশ করে না।
কেভিন

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

আমি ভাবছিলাম যে আপনি কীভাবে নির্দিষ্ট বাস্তবায়নের উপর নির্ভর করতে পারবেন, অর্থাত্ কোনও কারখানায় কীভাবে এটি নির্মূল করবেন। আর আমি এখানে একটি বড় উদাহরণ পাওয়া stackoverflow.com/a/3434505/711855
juanmf

1
খুব তুচ্ছ উদাহরণ।
গার্ডিয়ানএক্স

239

দেখুন সুইচ বিবৃতি গন্ধ :

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

রেফ্যাক্টরিং এবং প্যাটার্নগুলিতে রিফ্যাক্টরিং উভয়েরই এটি সমাধানের জন্য পন্থা রয়েছে।

যদি আপনার (সিউডো) কোডটি এমন দেখাচ্ছে:

class RequestHandler {

    public void handleRequest(int action) {
        switch(action) {
            case LOGIN:
                doLogin();
                break;
            case LOGOUT:
                doLogout();
                break;
            case QUERY:
               doQuery();
               break;
        }
    }
}

এই কোডটি ওপেন ক্লোজড নীতি লঙ্ঘন করে এবং প্রতিটি নতুন ধরণের অ্যাকশন কোডের সাথে ভঙ্গুর হয় along এর প্রতিকারের জন্য আপনি একটি 'কমান্ড' অবজেক্টটি চালু করতে পারেন:

interface Command {
    public void execute();
}

class LoginCommand implements Command {
    public void execute() {
        // do what doLogin() used to do
    }
}

class RequestHandler {
    private Map<Integer, Command> commandMap; // injected in, or obtained from a factory
    public void handleRequest(int action) {
        Command command = commandMap.get(action);
        command.execute();
    }
}

যদি আপনার (সিউডো) কোডটি এমন দেখাচ্ছে:

class House {
    private int state;

    public void enter() {
        switch (state) {
            case INSIDE:
                throw new Exception("Cannot enter. Already inside");
            case OUTSIDE:
                 state = INSIDE;
                 ...
                 break;
         }
    }
    public void exit() {
        switch (state) {
            case INSIDE:
                state = OUTSIDE;
                ...
                break;
            case OUTSIDE:
                throw new Exception("Cannot leave. Already outside");
        }
    }

তারপরে আপনি একটি 'স্টেট' অবজেক্টটি প্রবর্তন করতে পারেন।

// Throw exceptions unless the behavior is overriden by subclasses
abstract class HouseState {
    public HouseState enter() {
        throw new Exception("Cannot enter");
    }
    public HouseState leave() {
        throw new Exception("Cannot leave");
    }
}

class Inside extends HouseState {
    public HouseState leave() {
        return new Outside();
    }
}

class Outside extends HouseState {
    public HouseState enter() {
        return new Inside();
    }
}

class House {
    private HouseState state;
    public void enter() {
        this.state = this.state.enter();
    }
    public void leave() {
        this.state = this.state.leave();
    }
}

আশাকরি এটা সাহায্য করবে.


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

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

1
এটি সম্পূর্ণ / অসম্পূর্ণ অপারেশন এবং অবশ্যই ওওপিতে পুনরায় কাঠামো কোড সম্পর্কে দুর্দান্ত উদাহরণ a অসংখ্য ধন্যবাদ. আমি মনে করি এটি কার্যকর হবে যদি ওওপি / ডিজাইন প্যাটার্নস প্রবক্তারা ধারণাগুলির চেয়ে অপারেটরগুলির মতো ওওপি ধারণাগুলি চিকিত্সার পরামর্শ দেয় । আমি বোঝাতে চাইছি যে "প্রসারিত", "কারখানা", "সরঞ্জাম" ইত্যাদি খুব সহজেই ফাইল, শ্রেণি, শাখা জুড়ে ব্যবহৃত হয়। এগুলি "+", "-", "+ =", "?:", "==", "->" ইত্যাদির মতো অপারেটর হিসাবে সহজ হওয়া উচিত যখন কোনও প্রোগ্রামার তার মনে কেবল অপারেটর হিসাবে এগুলি ব্যবহার করে, কেবল তারপরে তিনি প্রোগ্রামের স্থিতি সম্পর্কে এবং (সম্পূর্ণ) সম্পূর্ণ ক্রিয়াকলাপ সম্পর্কে পুরো শ্রেণীর পাঠাগার জুড়ে ভাবতে পারেন।
নেমস্পেসফর্ম

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

1
কমান্ড অবজেক্টের সাথে, কোডটি উত্পন্ন Map<Integer, Command>করতে কি একটি সুইচের দরকার পড়বে না?
আতাউলম

41

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

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

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

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

বিবৃতি পরিবর্তন করার জন্য এখানে কিছু বিকল্প রয়েছে:


1
অন্য বিকল্পগুলির তুলনায় স্যুইচ ব্যবহার করে কেউ মেসেজ প্রসেসিংয়ের তুলনা দিতে পারে?
মাইক এ

37

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


অবশ্যই ধরে নেওয়া যায় যে সে সি তে লিখছে না :)
বার্নার্ড

1
সি তে, তিনি (আব?) বস্তুর মতো কিছু তৈরি করতে ফাংশন পয়েন্টার এবং
স্ট্র্যাট

আপনি যে কোনও ভাষায় ফরট ^ এইচ ^ এইচ ^ এইচ জাভা লিখতে পারেন। ; পি
বার্নার্ড

সম্পূর্ণরূপে সম্মত হন - কোড লাইনগুলি হ্রাস করার দুর্দান্ত উপায় স্যুইচ, তবে এটি খুব ম্যাচ দিয়ে খেলবেন না।
হটজার্ড

21

আমি মনে করি একটি ভাল মানচিত্র ব্যবহার করা সবচেয়ে ভাল উপায়। অভিধান ব্যবহার করে আপনি অন্য কোনও মান / অবজেক্ট / ফাংশনে প্রায় কোনও ইনপুট মানচিত্র করতে পারেন।

আপনার কোডটি এর মতো কিছু (প্যাকেজযুক্ত) দেখবে:

void InitMap(){
    Map[key1] = Object/Action;
    Map[key2] = Object/Action;
}

Object/Action DoStuff(Object key){
    return Map[key];
}

4
ভাষার উপর নির্ভর করে। এটি একটি স্যুইচ থেকে অনেক কম পঠনযোগ্য পেতে পারে
ভিঙ্কো ভার্সালভিক

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

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

কিছু পরিস্থিতিতে ক্লিনার হতে পারে। এছাড়াও ধীর গতির, কারণ এটির জন্য ফাংশন কল প্রয়োজন requires
নিক জনসন

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

12

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

আমার মনে হয় ভাষা এখানেও একটি গুরুত্বপূর্ণ বিষয়।


13
আমি ধরে নিচ্ছি যে এটি ব্যঙ্গাত্মক ছিল :)
ক্রেগ দিবস

6

আমি মনে করি আপনি যা খুঁজছেন তা কৌশল কৌশল tern

এটি বেশ কয়েকটি উপায়ে প্রয়োগ করা যেতে পারে, যা এই প্রশ্নের অন্যান্য উত্তরে যেমন উল্লেখ করা হয়েছে, যেমন:

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

5

switch আপনি যদি বিবৃতিগুলিতে নিজেকে নতুন রাজ্য বা নতুন আচরণ যুক্ত করে দেখেন তবে বিবৃতিগুলি প্রতিস্থাপন করা ভাল:

int state;

স্ট্রিং গেটস্ট্রিং () {
   স্যুইচ (রাষ্ট্র) {
     কেস 0: // স্টেট 0 এর জন্য আচরণ
           "শূন্য" প্রত্যাবর্তন;
     কেস 1: // স্টেট 1 এর জন্য আচরণ
           "এক" ফেরত;
   }
   নতুন ইলিজেলস্টেট এক্সেকশন () নিক্ষেপ করুন;
}

ডাবল getDouble () {

   স্যুইচ (এই স্টেট) {
     কেস 0: // স্টেট 0 এর জন্য আচরণ
           0 ডি ফিরে;
     কেস 1: // স্টেট 1 এর জন্য আচরণ
           1 ডি ফিরে;
   }
   নতুন ইলিজেলস্টেট এক্সেকশন () নিক্ষেপ করুন;
}

নতুন আচরণ যোগ করার পদ্ধতি অনুলিপি প্রয়োজন switch, এবং অন্য যোগ নতুন রাজ্যের মানে যোগ caseকরার যে switch বিবৃতি।

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

প্যাটার্ন মিল এবং একাধিক if - elseব্লক ব্যবহার করা যেতে পারে, যদিও নতুন আচরণ এবং নতুন রাজ্য যুক্ত করার সময় সত্যই একই সমস্যা রয়েছে।

"পলিমারফিজম" হিসাবে অন্যরা যে সমাধানটির পরামর্শ দিয়েছে তা রাষ্ট্রীয় প্যাটার্নের উদাহরণ :

রাজ্যের প্রত্যেককে তার নিজস্ব বর্গ দ্বারা প্রতিস্থাপন করুন। প্রতিটি আচরণের ক্লাসে নিজস্ব পদ্ধতি রয়েছে:

তাত্ত্বিক অবস্থা;

স্ট্রিং গেটস্ট্রিং () {
   state.getString ();
}

ডাবল getDouble () {
   state.getDouble () রিটার্ন করুন;
}

প্রতিবার আপনি একটি নতুন রাষ্ট্র যুক্ত করার সময় আপনাকে IStateইন্টারফেসের একটি নতুন বাস্তবায়ন যুক্ত করতে হবে । একটি switchবিশ্বে, আপনি caseপ্রত্যেকের সাথে একটি যোগ করতে চাই switch

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

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


4

অন্যথায় যদি

আমি এই ভিত্তিটি খণ্ডন করি যে স্যুইচ যদিও অন্তর্নিহিত খারাপ।


3

ভাল, এক জন্য, আমি জানতাম না সুইচ ব্যবহার করা একটি অ্যান্টি প্যাটার্ন ছিল।

দ্বিতীয়ত, স্যুইচ সর্বদা যদি / অন্যথায় বিবৃতি দিয়ে প্রতিস্থাপন করা যায়।


ঠিক - সুইচ হ'ল / এলসিফের একগুচ্ছ জন্য সিনথেটিক মেথডোন one
মাইক এ

3

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


2
আপনি এই মুহুর্তে সংকলকটি দ্বিতীয়-অনুমান করছেন এবং সংকলক ইন্টার্নালের ভিত্তিতে আপনার নকশায় পরিবর্তন আনছেন। ডিজাইনের সমস্যার প্রকৃতি অনুসরণ করা উচিত, সংকলকটির প্রকৃতি নয়।
মাইক এ

3

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

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

এটি অবশ্যই ধরে নেওয়া উচিত যে কোড রক্ষণ করা বা পর্যালোচনা করা যে কেউই মূল লেখকের মতো কমপক্ষে দক্ষ, যাতে কোনও নির্মাণ নিরাপদে ব্যবহার করা যায়।


ঠিক আছে, তবে কেন আমাদের একই জিনিস করার 5 টি ভিন্ন এবং নিরর্থক পদ্ধতিগুলির দরকার - শর্তাধীন কার্যকর?
মাইক এ

@ মাইক.আমাই: কারণ প্রতিটি পদ্ধতির বিভিন্ন সুবিধা এবং ব্যয় রয়েছে এবং এটি সর্বনিম্ন ব্যয় সহ সর্বাধিক সুবিধা অর্জন সম্পর্কে।
স্কিজ

1

যদি স্যুইচটি বিভিন্ন ধরণের অবজেক্টের মধ্যে পার্থক্য করার জন্য উপস্থিত থাকে তবে আপনি সম্ভবত সেই সমস্ত অবজেক্টগুলি বা কিছু ভার্চুয়াল পদ্ধতিগুলি সঠিকভাবে বর্ণনা করতে কিছু ক্লাস মিস করছেন ...


1

সি ++ এর জন্য

আপনি যদি একটি অ্যাবস্ট্রাক্ট ফ্যাক্টরির উল্লেখ করছেন তবে আমি মনে করি যে একটি রেজিস্ট্রক্রিটারফাঙ্ক (..) পদ্ধতি সাধারণত প্রতিটি "নতুন" বিবৃতি যা প্রয়োজন তার জন্য একটি কেস যুক্ত করার চেয়ে ভাল। তারপরে সমস্ত শ্রেণিকে একটি ক্রিয়েটর ফাংশন (..) তৈরি এবং রেজিস্টার করতে দেওয়া যা ম্যাক্রো দিয়ে সহজেই প্রয়োগ করা যেতে পারে (যদি আমি উল্লেখ করার সাহস করি)। আমি বিশ্বাস করি এটি অনেকগুলি কাঠামোর মতো একটি সাধারণ পদ্ধতি। আমি এটি প্রথম ET++ এ দেখেছি এবং আমি মনে করি যে অনেকগুলি ফ্রেমওয়ার্কগুলির জন্য এটির একটি ডিসিএল এবং আইএমপিএল ম্যাক্রোর প্রয়োজন।


1

সি এর মতো একটি পদ্ধতিগত ভাষায়, তারপরে বিকল্পের যে কোনওটির চেয়ে স্যুইচ করা ভাল।

কোনও বস্তু-কেন্দ্রিক ভাষায়, তারপরে প্রায়শই অন্যান্য বিকল্প পাওয়া যায় যা অবজেক্ট কাঠামো, বিশেষত বহুকর্মকে আরও ভালভাবে ব্যবহার করে।

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

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

যেখানে কোনও সুস্পষ্ট পলিমারফিজম চলছে না, কৌশল কৌশলটি কার্যকর করার পক্ষে এটি উপযুক্ত হতে পারে ।

তবে যদি আপনার বিকল্পটি যদি বড় হয় ... তবে ... ইএলএসই ব্লক হয়, তবে এটি ভুলে যান।


1

একটি ভাষা ব্যবহার করুন যা অন্তর্নির্মিত সুইচ বিবৃতিতে আসে না। পার্ল 5 মনে আসে।

গুরুতরভাবে যদিও, আপনি কেন এড়াতে চান? এবং যদি এটিকে এড়াতে আপনার কাছে যুক্তিসঙ্গত কারণ থাকে তবে তা কেবল এড়াতে হবে না কেন?


1

ফাংশন পয়েন্টারগুলি একটি বিশাল চুনকি সুইচ বিবৃতিটি প্রতিস্থাপনের এক উপায়, এগুলি বিশেষত ভাষাগুলিতে ভাল যেখানে আপনি তাদের নাম অনুসারে ফাংশন ক্যাপচার করতে পারেন এবং তাদের সাথে স্টাফ তৈরি করতে পারেন।

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

এটি একটি দুর্দান্ত বিভাজন এবং বিজয়ী উদাহরণ:

বলুন আপনার কাছে কোনও ধরণের দোভাষী রয়েছে।

switch(*IP) {
    case OPCODE_ADD:
        ...
        break;
    case OPCODE_NOT_ZERO:
        ...
        break;
    case OPCODE_JUMP:
        ...
        break;
    default:
        fixme(*IP);
}

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

opcode_table[*IP](*IP, vm);

... // in somewhere else:
void opcode_add(byte_opcode op, Vm* vm) { ... };
void opcode_not_zero(byte_opcode op, Vm* vm) { ... };
void opcode_jump(byte_opcode op, Vm* vm) { ... };
void opcode_default(byte_opcode op, Vm* vm) { /* fixme */ };

OpcodeFuncPtr opcode_table[256] = {
    ...
    opcode_add,
    opcode_not_zero,
    opcode_jump,
    opcode_default,
    opcode_default,
    ... // etc.
};

দ্রষ্টব্য যে আমি সি তে অপকড_ট্যাবিলের অপ্রয়োজনীয়তা অপসারণ করতে জানি না সম্ভবত এটি সম্পর্কে আমার একটি প্রশ্ন করা উচিত। :)


0

সর্বাধিক সুস্পষ্ট, ভাষা স্বাধীন, উত্তরটি 'যদি' এর একটি সিরিজ ব্যবহার করা হয়।

আপনি যে ভাষাটি ব্যবহার করছেন তাতে ফাংশন পয়েন্টার (সি) থাকে বা এমন ফাংশন থাকে যা প্রথম শ্রেণির মান (লুয়া) থাকে তবে আপনি "পয়েন্টার টু" ফাংশনের অ্যারে (বা একটি তালিকা) ব্যবহার করে "স্যুইচ" এর অনুরূপ ফলাফল অর্জন করতে পারেন।

আপনি আরও ভাল উত্তর চাইলে আপনার ভাষার বিষয়ে আরও সুনির্দিষ্ট হওয়া উচিত।


0

স্যুইচ স্টেটমেন্টগুলি প্রায়শই একটি ভাল ওও ডিজাইন দ্বারা প্রতিস্থাপন করা যেতে পারে।

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

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

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


0

নির্ভর করে আপনি এটি প্রতিস্থাপন করতে চান কেন!

অনেক দোভাষী অনুবাদকৃত অপকড সম্পাদনের জন্য স্যুইচ স্টেটমেন্টের পরিবর্তে 'গণিত গোটোস' ব্যবহার করেন।

আমি সি / সি ++ স্যুইচ সম্পর্কে যা মিস করি তা হ'ল পাস্কাল 'ইন' এবং ব্যাপ্তি। আমিও চাই যে আমি স্ট্রিংগুলি স্যুইচ করতে পারি। কিন্তু এগুলি, কম্পাইলারের খাওয়ার জন্য তুচ্ছ, কাঠামোগত এবং পুনরাবৃত্তিকারী এবং জিনিসগুলি ব্যবহার করার পরে কঠোর পরিশ্রম। সুতরাং, বিপরীতে, প্রচুর জিনিস রয়েছে যা আমি চাই আমি একটি স্যুইচ দিয়ে প্রতিস্থাপন করতে পারতাম, যদি কেবল সি এর স্যুইচ () আরও নমনীয় হত!


0

ওপেন ক্লোজ প্রিন্সিপালকে ভেঙে যাওয়ার কারণে স্যুইচটি যাওয়া ভাল উপায় নয়। এইভাবেই আমি এটি করি।

public class Animal
{
       public abstract void Speak();
}


public class Dog : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Hao Hao");
   }
}

public class Cat : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Meauuuu");
   }
}

এবং এটি কীভাবে ব্যবহার করবেন তা এখানে (আপনার কোড নেওয়া):

foreach (var animal in zoo) 
{
    echo animal.speak();
}

মূলত আমরা যা করছি তা হ'ল বাবা-মাকে বাচ্চাদের নিয়ে কী করা উচিত তা স্থির না করে শিশু শ্রেণীর কাছে দায়িত্ব অর্পণ করা।

আপনি "লিসকভ সাবস্টিটিউশন নীতিমালা" পড়তে চাইতে পারেন।


0

জাভাস্ক্রিপ্টে সহযোগী অ্যারে ব্যবহার করে:
এটি:

function getItemPricing(customer, item) {
    switch (customer.type) {
        // VIPs are awesome. Give them 50% off.
        case 'VIP':
            return item.price * item.quantity * 0.50;

            // Preferred customers are no VIPs, but they still get 25% off.
        case 'Preferred':
            return item.price * item.quantity * 0.75;

            // No discount for other customers.
        case 'Regular':
        case
        default:
            return item.price * item.quantity;
    }
}

এটি হয়ে:

function getItemPricing(customer, item) {
var pricing = {
    'VIP': function(item) {
        return item.price * item.quantity * 0.50;
    },
    'Preferred': function(item) {
        if (item.price <= 100.0)
            return item.price * item.quantity * 0.75;

        // Else
        return item.price * item.quantity;
    },
    'Regular': function(item) {
        return item.price * item.quantity;
    }
};

    if (pricing[customer.type])
        return pricing[customer.type](item);
    else
        return pricing.Regular(item);
}

শ্লীলতা


-12

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

একই জিনিস অবজেক্ট কারখানার জন্য।

যদি / অন্য ব্লকগুলি এমন একটি সাধারণ নির্মাণ যা প্রত্যেকটি পায় are আপনার সমস্যার কারণ না হয় তা নিশ্চিত করতে আপনি করতে পারেন এমন কয়েকটি জিনিস।

প্রথমত - দু'বারের বেশি বিবৃতি দেওয়া থাকলে চেষ্টা করুন এবং ইনডেন্ট করবেন না। যদি আপনি নিজেকে ইনডেন্টিং সন্ধান করে থাকেন তবে আপনি এটি ভুল করছেন।

 if a = 1 then 
     do something else 
     if a = 2 then 
         do something else
     else 
         if a = 3 then 
             do the last thing
         endif
     endif 
  endif

সত্যিই খারাপ - পরিবর্তে এটি করুন।

if a = 1 then 
   do something
endif 
if a = 2 then 
   do something else
endif 
if a = 3 then 
   do something more
endif 

অপটিমাইজেশন নিন্দিত করা হবে। এটি আপনার কোডের গতির সাথে তেমন কোনও পার্থক্য করে না।

দ্বিতীয়ত, আমি যতক্ষণ না নির্দিষ্ট কোড ব্লকের মাধ্যমে স্পষ্ট করে দেওয়ার জন্য পর্যাপ্ত ব্রেক স্টেটমেন্ট রয়েছে ততক্ষণ কোনও আইফ ব্লক ভেঙে ফেলার পক্ষে বাধা দিচ্ছি না

procedure processA(a:int)
    if a = 1 then 
       do something
       procedure_return
    endif 
    if a = 2 then 
       do something else
       procedure_return
    endif 
    if a = 3 then 
       do something more
       procedure_return
    endif 
end_procedure

সম্পাদনা : স্যুইচ অন এবং কেন আমি মনে করি এটি আঁকাবাঁকা করা কঠিন:

এখানে একটি স্যুইচ স্টেটমেন্টের একটি উদাহরণ ...

private void doLog(LogLevel logLevel, String msg) {
   String prefix;
   switch (logLevel) {
     case INFO:
       prefix = "INFO";
       break;
     case WARN:
       prefix = "WARN";
       break;
     case ERROR:
       prefix = "ERROR";
       break;
     default:
       throw new RuntimeException("Oops, forgot to add stuff on new enum constant");
   }
   System.out.println(String.format("%s: %s", prefix, msg));
 }

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

যেমন

for i from 1 to 1000 {statement1; statement2}
if something=false then {statement1; statement2}
while isOKtoLoop {statement1; statement2}

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

আশা করি যে আপনার প্রশ্নের উত্তর।


বাহ - স্পষ্টতই একটি বিতর্কিত উত্তর। আমি কী ভুল করেছি তা জানতে আগ্রহী।
seanyboy

খুব, জটিল হিসাবে সুইচ? আমি জানি না ... আমার কাছে মনে হয় আপনি ব্যবহার করতে পারেন এমন অনেক ভাষা বৈশিষ্ট্য থাকবে না। :) এছাড়াও, আপনার কেন্দ্রীয় উদাহরণে, (a == 1 || a == 2 || a == 3) কিছু করলে কী করা চতুর হবে না?
লার্স ওয়েস্টারগ্রেন

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

4
"অপ্টিমাইজেশানকে অভিশাপ দেওয়া হবে It এটি আপনার কোডের গতির সাথে তেমন কোনও পার্থক্য করে না।" আমার কোডটি একটি মোবাইল প্ল্যাটফর্মে চলে। অপ্টিমাইজেশন বিষয়। তদ্ব্যতীত, স্যুইচগুলি কোডটি সঠিকভাবে ব্যবহার করা থাকলে (if..elseif..elseif..elseif ... এর সাথে তুলনা করে) খুব পরিষ্কার দেখাতে পারে। এগুলি কখনও দেখেনি? সেগুলি শিখুন।
সোয়াতি

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