এখানে কি ব্যতিক্রম ছোঁড়া একটি বিরোধী প্যাটার্ন?


33

কোড পর্যালোচনার পরে আমি কেবল একটি নকশা পছন্দ নিয়ে আলোচনা করেছি। আমি আপনার মতামত কি অবাক।

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

আলোচনা সমাধান নিম্নলিখিত প্যাটার্ন ব্যবহৃত (উল্লেখ্য: এই হল না প্রকৃত কোড, স্পষ্টত - এটা অর্থবোধক উদ্দেশ্যে সরলীকৃত করা হয়েছে):

public class Preferences {
    // null values are legal
    private Map<String, String> valuesFromDatabase;

    private static Map<String, String> defaultValues;

    class KeyNotFoundException extends Exception {
    }

    public String getByKey(String key) {
        try {
            return getValueByKey(key);
        } catch (KeyNotFoundException e) {
            String defaultValue = defaultValues.get(key);
            valuesFromDatabase.put(key, defaultvalue);
            return defaultValue;
        }
    }

    private String getValueByKey(String key) throws KeyNotFoundException {
        if (valuesFromDatabase.containsKey(key)) {
            return valuesFromDatabase.get(key);
        } else {
            throw new KeyNotFoundException();
        }
    }
}

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

একে অপরের সাথে কিছু যোগাযোগ করার জন্য এটি আনতে মূলত দুটি পদ্ধতি এটি নিয়ে আসে।

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

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

প্রত্যাবর্তনটি nullদ্ব্যর্থহীন হবে, যেহেতু nullএকটি নিখুঁত আইনী মূল্য, তাই কীটি কী ছিল না তা বোঝা যাচ্ছে না বা ছিল কিনা তা বলার অপেক্ষা রাখে না null

getValueByKeyকোনও ধরণের একটি ফেরত দিতে হবে Tuple<Boolean, String>, কীটি ইতিমধ্যে উপস্থিত থাকলে বুল সেট হয়ে যায়, যাতে আমরা (true, null)এবং এর মধ্যে পার্থক্য করতে পারি (false, null)। (একটি outপরামিতি সি # তে ব্যবহার করা যেতে পারে তবে এটি জাভা))

এটি কি সুন্দর বিকল্প? হ্যাঁ, আপনাকে এর প্রভাবের জন্য কিছু একক-ব্যবহারের শ্রেণি সংজ্ঞায়িত করতে হবে Tuple<Boolean, String>তবে তারপরে আমরা মুক্তি পাচ্ছি KeyNotFoundException, যাতে এই ধরণের ভারসাম্য থাকে। আমরা একটি ব্যতিক্রম পরিচালনা করার ওভারহেডও এড়িয়ে চলেছি, যদিও এটি ব্যবহারিক দিক থেকে তাৎপর্যপূর্ণ নয় - কথা বলার জন্য কোনও কার্যকারিতা বিবেচনা নেই, এটি একটি ক্লায়েন্ট অ্যাপ্লিকেশন এবং এটি পছন্দ নয় যে ব্যবহারকারীর পছন্দগুলি প্রতি সেকেন্ডে কয়েক মিলিয়ন বার পুনরুদ্ধার হবে।

এই পদ্ধতির বিভিন্নতা Optional<String>কিছু কাস্টমের পরিবর্তে পেয়ারা ব্যবহার করতে পারে (পেয়ারা পুরো প্রকল্পে ইতিমধ্যে ব্যবহৃত হয়ে থাকে) Tuple<Boolean, String>এবং তারপরে আমরা Optional.<String>absent()"যথাযথ" এর মধ্যে পার্থক্য করতে পারি null। এটি এখনও হ্যাকশ বোধ করে, যদিও সহজে দেখা যায় - দুটি স্তরের "নালীনতা" প্রবর্তন করা ধারণাটিকে অপব্যবহার করে বলে মনে হয় যে এটি তৈরির পিছনে দাঁড়িয়েছিল Optional

অন্য বিকল্পটি হ'ল কীটি উপস্থিত রয়েছে কিনা তা স্পষ্টভাবে যাচাই করা হবে (একটি boolean containsKey(String key)পদ্ধতি যুক্ত করুন এবং getValueByKeyকেবলমাত্র যদি আমরা ইতিমধ্যে এটি বিদ্যমান বলে ধরে রেখেছি তবেই কল করুন )।

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

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

কোড নমুনার মতো ব্যতিক্রমগুলি কী কোনও বিরোধী-প্যাটার্ন হিসাবে ব্যবহার করা হচ্ছে, বা বিকল্পগুলি খুব পরিষ্কার নয়, তা যদি দেওয়া হয় তবে তা গ্রহণযোগ্য? যদি তা হয় তবে কোন পরিস্থিতিতে তা ঠিক থাকবে? এবং বিপরীতভাবে?


1
@ গ্লেনএইচ 7 স্বীকৃত (এবং সর্বাধিক ভোট প্রাপ্ত) উত্তরের যোগফলের যোগান দেয় যে "যখন তারা কম কোড বিশৃঙ্খলা নিয়ে ত্রুটি পরিচালনা করতে সহজতর হয় তখন ক্ষেত্রে তাদের [ব্যতিক্রমগুলি] ব্যবহার করা উচিত"। আমি অনুমান করি যে আমি এখানে জিজ্ঞাসা করছি যে বিকল্পগুলি আমি তালিকাভুক্ত করেছি সেগুলি "কম কোড বিশৃঙ্খলা" হিসাবে বিবেচিত হবে কিনা।
কনরাড মোরাউস্কি

1
আমি আমার ভিটিসি প্রত্যাহার করে নিয়েছি - আপনি সম্পর্কিত কিছু জিজ্ঞাসা করেছেন, তবে আমার প্রস্তাবিত সদৃশ থেকে আলাদা।

3
আমি মনে করি যখন প্রশ্নটি getValueByKeyপ্রকাশ্য হয় তখন আরও আকর্ষণীয় হয়ে ওঠে ।
ডক ব্রাউন

2
ভবিষ্যতের রেফারেন্সের জন্য, আপনি সঠিক কাজটি করেছেন। কোড রিভিউতে এটি বিষয়বস্তু হতে পারে কারণ এটি উদাহরণ কোড।
রাবারডাক

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

উত্তর:


75

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

এটি আপনার সংস্করণ ( getValueByKey()পদ্ধতিটি মুছে ফেলা হয়েছে) এর পরে অনেক পরিষ্কার is

public String getByKey(String key) {
    if (valuesFromDatabase.containsKey(key)) {
        return valuesFromDatabase.get(key);
    } else {
        String defaultValue = defaultValues.get(key);
        valuesFromDatabase.put(key, defaultvalue);
        return defaultValue;
    }
}

আপনি যদি স্থানীয়ভাবে ত্রুটিটি সমাধান করতে না জানেন তবেই একটি ব্যতিক্রম ছুঁড়ে ফেলা উচিত।


14
উত্তর করার জন্য ধন্যবাদ. রেকর্ডের জন্য, আমি এই সহকর্মী (আমি মূল কোডটি পছন্দ করি না), আমি কেবল প্রশ্নটি নিরপেক্ষভাবে বাক্যযুক্ত করেছিলাম যাতে এটি লোড করা হয়নি :)
কনরাড মোরাউসকি

59
উন্মাদতার প্রথম লক্ষণ: আপনি নিজের সাথে কথা বলা শুরু করেন।
রবার্ট হার্ভে

1
@ বিউ: ভাল, সেক্ষেত্রে আমি মনে করি এটি ঠিক আছে, তবে আপনার যদি দুটি রূপের প্রয়োজন হয় - একটি পদ্ধতি অনুপস্থিত কীগুলির স্বতঃসংশোধন না করে মান পুনরুদ্ধার করা, এবং এর সাথে একটি? আপনি কী ভাবেন তার পরে সবচেয়ে পরিষ্কার (এবং ডিআরওয়াই) বিকল্প?
ডক ব্রাউন

3
@ রবার্টহারভে :) অন্য কেউ এই কোডের টুকরোটি লিখেছিলেন, একজন প্রকৃত পৃথক ব্যক্তি, আমি পর্যালোচক ছিলাম
কনরাড মোরাওস্কি

1
@ আলভারো, প্রায়শই ব্যতিক্রমগুলি ব্যবহার করা কোনও সমস্যা নয়। ভাষা নির্বিশেষে ব্যতিক্রমকে খারাপভাবে ব্যবহার করা একটি সমস্যা।
kdbanman

11

আমি ব্যতিক্রমগুলির এই ব্যবহারটিকে একটি বিরোধী-প্যাটার্ন বলব না, কোনও জটিল ফলাফলের কথা বলার সমস্যাটির সর্বোত্তম সমাধান নয়।

সেরা সমাধান (আপনি এখনও জাভা 7 তে ধরে নিচ্ছেন) ধরে নেওয়া হবে পেয়ারা ptionচ্ছিক ব্যবহার করা; আমি একমত নই যে এটির ক্ষেত্রে এটি ব্যবহার হ্যাকিশ হবে। আমার কাছে মনে হয়, পেয়ারা Oচ্ছিকের বর্ধিত ব্যাখ্যার ভিত্তিতে , এটি কখন ব্যবহার করবেন এটির এটি একটি নিখুঁত উদাহরণ। আপনি "কোনও মূল্য খুঁজে পাওয়া যায় নি" এবং "নাল পাওয়া যায় না" এর মধ্যে পার্থক্য করছেন।


1
আমি মনে করি Optionalনা যে নাল ধরে রাখতে পারে। Optional.of()কেবল একটি নল-নাল রেফারেন্স নেয় এবং Optional.fromNullable()নালটিকে "মান উপস্থিত নেই" হিসাবে বিবেচনা করে।
নবীন

1
@ নবীন এটি শূন্য রাখতে পারে না, তবে আপনার নিজের হাতে রয়েছে Optional.absent()। এবং তাই, Optional.fromNullable(string)সমান হবে Optional.<String>absent()যদি stringনাল ছিল, অথবা Optional.of(string)যদি এটা ছিল না।
কনরাড মোরাউস্কি

@ কনরাডমোরাউস্কি আমি ভেবেছিলাম যে ওপিতে সমস্যাটি হ'ল আপনি ব্যতিক্রম না ছোঁড়াতে নাল স্ট্রিং এবং একটি অযৌক্তিক স্ট্রিংয়ের মধ্যে পার্থক্য করতে পারবেন না। Optional.absent()এই দৃশ্যের একটি জুড়ে। আপনি অন্য একজনকে কীভাবে উপস্থাপন করবেন?
নবীন

প্রকৃত সঙ্গে @Navin null
কনরাড মোরাওস্কি

4
@ কনরাডমোরাউস্কি: এটিকে সত্যিই খারাপ ধারণা বলে মনে হচ্ছে। "এই পদ্ধতিটি আর ফিরে আসে না null!" বলার জন্য আমি আরও পরিষ্কার উপায়টি খুব কমই ভাবতে পারি ! রিটার্ন হিসাবে ঘোষণা করার চেয়ে Optional<...>। । ।
রুখ

8

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

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

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

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


1
ঠিক আছে, বাস্তবে এটি কেবল Map<String, String>ডাটাবেস টেবিল স্তরের, কারণ valuesকলামটি এক ধরণের হতে হবে। যদিও একটি মোড়ক ডিএও স্তর রয়েছে যা প্রতিটি কী-মান জোড়াকে শক্তিশালী করে। তবে আমি স্বচ্ছতার জন্য এটি বাদ দিয়েছি। (অবশ্যই আপনার পরিবর্তে এন কলামগুলির সাথে একটি এক-সারি টেবিল থাকতে পারে, তবে তারপরে প্রতিটি নতুন মান যুক্ত করার জন্য টেবিলের স্কিমাকে আপডেট করতে হবে, সুতরাং তাদের পার্স করার সাথে যুক্ত জটিলতা অপসারণ অন্য কোথাও অন্য জটিলতা প্রবর্তনের ব্যয়েই আসে))।
কনরাড মোরাউস্কি

টিপল সম্পর্কে ভাল পয়েন্ট। আসলে, (false, "foo")মানে কি হবে ?
কনরাড মোরাওস্কি

কমপক্ষে পেয়ারা Oচ্ছিকর সাথে, ব্যাতিক্রমের ফলাফলগুলিকে বাতিল করার চেষ্টা করা। আপনাকে অপশনাল.অবসেন্ট () ব্যবহার করতে হবে।
মাইক পার্টরিজ

@ মাইকপার্টরিজ ভাল পয়েন্ট। একটি কুরুচিপূর্ণ কাজ হ'ল মানচিত্র পরিবর্তন করতে হবে Map<String, Optional<String>>এবং তারপরে আপনি শেষ করতে চান Optional<Optional<String>>। একটি কম বিভ্রান্তিকর সমাধান হ'ল আপনার নিজস্ব ptionচ্ছিক যা মঞ্জুরি দেয় null, বা অনুরূপ বীজগণিত ডেটা টাইপ যা অনুমোদন দেয় না nullতবে 3 টি রাজ্য রয়েছে - অনুপস্থিত, নাল, বা উপস্থিত। উভয়ই প্রয়োগ করা সহজ, যদিও এর সাথে জড়িত বয়লারপ্লেটের পরিমাণ বেশি যা কেবল অভ্যন্তরীণভাবে ব্যবহৃত হবে।
ডোভাল

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

5

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

সমস্যাটি হ'ল এই। তবে আপনি ইতিমধ্যে সমাধানটি নিজেরাই পোস্ট করেছেন:

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

তবে, ব্যবহার করবেন না null বা Optional । আপনি Optionalকেবল এবং ব্যবহার করতে পারেন । আপনার "হ্যাকিশ" অনুভূতির জন্য, কেবল এটি নেস্টেড ব্যবহার করুন, যাতে আপনি এটি শেষ করেন Optional<Optional<String>>যা ডাটাবেসে কোনও কী (প্রথম বিকল্প স্তর) থাকতে পারে এবং এটিতে একটি পূর্বনির্ধারিত মান (দ্বিতীয় বিকল্প স্তর) থাকতে পারে।

এই পদ্ধতির ব্যতিক্রমগুলি ব্যবহার করার চেয়ে ভাল এবং এটি আপনার পক্ষে যতক্ষণ Optionalনতুন নয় ততক্ষণ তা বোঝা সহজ ।

এছাড়াও দয়া করে নোট করুন যে Optionalএতে কিছু আরামের কাজ রয়েছে যাতে আপনাকে সমস্ত কাজ নিজেই করতে না হয়। এর মধ্যে রয়েছে:

  • static static <T> Optional<T> fromNullable(T nullableReference)আপনার ডাটাবেস ইনপুটকে Optionalধরণের রূপান্তর করতে
  • abstract T or(T defaultValue) অভ্যন্তরীণ বিকল্প স্তরটির মূল মান পেতে বা (উপস্থিত না থাকলে) আপনার ডিফল্ট কী মানটি পেতে

1
Optional<Optional<String>>অশুভ দেখায়, যদিও এর কিছুটা আকর্ষণ আছে আমাকে স্বীকার করতে হবে:)
কনরাড মোরাউসকি

এটিকে কেন খারাপ দেখাচ্ছে বলে আপনি আরও ব্যাখ্যা করতে পারেন? এটি আসলে একই প্যাটার্ন List<List<String>>। আপনি অবশ্যই (যদি ভাষাটি অনুমতি দেয়) একটি নতুন ধরণের তৈরি করতে পারে DBConfigKeyযা কোনটি জড়িয়ে দেয় Optional<Optional<String>>এবং যদি আপনি এটি পছন্দ করেন তবে এটি আরও পাঠযোগ্য।
ভ্যালেন্ট্রি

2
@ ভ্যালেনটারি এটি অনেক আলাদা তালিকার একটি তালিকা হ'ল কিছু ধরণের ডেটা সঞ্চয় করার বৈধ উপায়; optionচ্ছিকের একটি alচ্ছিক হ'ল ডেটাতে যে দুটি ধরণের সমস্যা হতে পারে সেগুলি চিহ্নিত করার একটি সাধারণ উপায়।
Ypnypn

বিকল্পের একটি বিকল্প তালিকার তালিকার মতো যেখানে প্রতিটি তালিকার একটি বা কোনও উপাদান নেই। এটি মূলত একই। জাভাতে এটি প্রায়শই ব্যবহৃত হয় না তার অর্থ এটি সহজাত খারাপ নয়।
ভ্যালেনটারি

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

5

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

Properties.getProperty(String)(জাভা 7 থেকে) এর জন্য বাস্তবায়ন কীভাবে করা হচ্ছে তা দেখে :

Object oval = super.get(key);
String sval = (oval instanceof String) ? (String)oval : null;
return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval;

আপনার উদ্ধৃতি হিসাবে সত্যই "প্রবাহ নিয়ন্ত্রণ করতে ব্যতিক্রমগুলির অপব্যবহার" করার দরকার নেই।

@ BЈовић- এর উত্তরের অনুরূপ, তবে কিছুটা পরিশ্রমী, এছাড়াও হতে পারে:

public String getByKey(String key) {
    if (!valuesFromDatabase.containsKey(key)) {
        valuesFromDatabase.put(key, defaultValues.get(key));
    }
    return valuesFromDatabase.get(key);
}

4

যদিও আমি মনে করি @ BЈовић- এর উত্তর ঠিক আছে তবে getValueByKeyঅন্য কোথাও প্রয়োজন নেই, আপনার প্রোগ্রামের উভয় ব্যবহারের ক্ষেত্রে আপনার সমাধানটি খারাপ বলে আমি মনে করি না:

  • কীটি আগে থেকে উপস্থিত না থাকলে এবং স্বয়ংক্রিয়ভাবে তৈরির মাধ্যমে কী দ্বারা পুনরুদ্ধার

  • ডাটাবেস, সংগ্রহশালা বা মূল মানচিত্রের কোনও পরিবর্তন না করে স্বয়ংক্রিয়তা ব্যতীত পুনরুদ্ধার ( getValueByKeyজনসাধারণকে মৌমাছি দেওয়ার কথা ভাবেন , ব্যক্তিগত নয়)

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

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

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

"আপনার কোডটি সহজ করার সাথে সাথে ব্যতিক্রমগুলি ব্যবহার করা আপনার খারাপ লাগবে না"।


3

Optionalসঠিক সমাধান। তবে, আপনি যদি পছন্দ করেন তবে এমন একটি বিকল্প আছে যা "দু'টি নল" কম অনুভব করে, একটি সেন্ডিনেল বিবেচনা করুন।

keyNotFoundSentinelএকটি মান সহ একটি ব্যক্তিগত স্ট্যাটিক স্ট্রিং সংজ্ঞায়িত করুনnew String("") *

এখন বেসরকারী পদ্ধতি return keyNotFoundSentinelপরিবর্তে পারেন throw new KeyNotFoundException()। সর্বজনীন পদ্ধতিটি সেই মানটির জন্য পরীক্ষা করতে পারে

String rval = getValueByKey(key);
if (rval == keyNotFoundSentinel) { // reference equality, not string.equals
    ... // generate default value
} else {
    return rval;
}

বাস্তবে, nullএটি একটি সেন্ডিনেলের একটি বিশেষ ক্ষেত্রে। এটি কয়েকটি বিশেষ আচরণের সাথে ভাষা দ্বারা সংজ্ঞায়িত একটি সেন্ডিনেল মান (যদি আপনি কোনও পদ্ধতিতে কল করেন তবে ভাল সংজ্ঞায়িত আচরণ)null ) । এটি ঠিক এরকম একটি সেন্ডিনেল রাখতে এতটাই কার্যকর হতে পারে যে প্রায় এটিই ভাষা ব্যবহার করে।

* আমরা জাভাটিকে স্ট্রিংটিকে "ইন্টার্নিং" করা থেকে বিরত করার new String("")পরিবর্তে ইচ্ছাকৃতভাবে ব্যবহার করি ""যা এটি অন্য কোনও ফাঁকা স্ট্রিংয়ের মতোই রেফারেন্স দেয়। কারণ এই অতিরিক্ত পদক্ষেপটি করেছে, আমরা গ্যারান্টিযুক্ত যে উল্লেখ করা স্ট্রিং keyNotFoundSentinelএকটি অনন্য উদাহরণ, যা আমাদের নিশ্চিত করতে হবে এটি কখনই মানচিত্রে প্রদর্শিত না হতে পারে।


এটি, আইএমএইচও, সেরা উত্তর।
fgp

2

জাভার সমস্ত ব্যথা পয়েন্টগুলি থেকে শিখেছে এমন কাঠামো থেকে শিখুন:

.NET এই সমস্যাটির জন্য আরও দুটি মার্জিত সমাধান সরবরাহ করে, যার উদাহরণস্বরূপ:

আধুনিক জাভাতে লিখতে খুব সহজ, প্রাক্তনটির জন্য কেবল "শক্তিশালী রেফারেন্স" সহায়ক শ্রেণীর প্রয়োজন।


Dictionaryপ্যাটার্নের জন্য একটি সমবায়-বান্ধব বিকল্প হবে T TryGetValue(TKey, out bool)
সুপারক্যাট 16'15
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.