টাইপ টেস্টিং ঠিক আছে কখন?


53

কিছু অন্তর্নিহিত ধরণের সুরক্ষা (যেমন, জাভাস্ক্রিপ্ট নয়) সহ একটি ভাষা ধরে নেওয়া:

একটি গ্রহণ করে এমন একটি পদ্ধতি দেওয়া SuperType, আমরা জানি যে বেশিরভাগ ক্ষেত্রে আমাদের কোনও ক্রিয়া বাছাই করার জন্য টাইপ টেস্টিং করতে প্ররোচিত করা যেতে পারে:

public void DoSomethingTo(SuperType o) {
  if (o isa SubTypeA) {
    o.doSomethingA()
  } else {
    o.doSomethingB();
  }
}

আমাদের সাধারণত, যদি সর্বদা না হয় তবে একটি একক, ওভারডেয়েবল পদ্ধতি তৈরি করা উচিত SuperTypeএবং এটি করা উচিত:

public void DoSomethingTo(SuperType o) {
  o.doSomething();
}

... যার মধ্যে প্রতিটি উপ-টাইপকে নিজস্ব doSomething()বাস্তবায়ন দেওয়া হয় । আমাদের বাকি অ্যাপ্লিকেশনগুলি তখন প্রদত্ত যে কোনওটি SuperTypeআসলে একটি SubTypeAবা একটি কিনা তা সম্পর্কে যথাযথভাবে অজ্ঞ থাকতে পারে SubTypeB

ওয়ান্ডারফুল।

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

সুতরাং, কি পরিস্থিতিতে, যদি থাকে, উচিত আমরা বা উচিত নয় আমরা স্পষ্ট টাইপ পরীক্ষামূলক সঞ্চালন?

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



4
এটি উল্লেখ করার মতো যে জাভা বা সি # উভয়েরই প্রথম সংস্করণে জেনারিক ছিল না। ধারকগুলি ব্যবহার করতে আপনাকে অবজেক্টে এবং যেতে হয়েছিল।
ডোভাল

6
"টাইপ চেকিং" প্রায়শই কোড ভাষাটির স্থিতিশীল টাইপিং বিধিগুলি পালন করে কিনা তা পরীক্ষা করে বোঝায় refers আপনি যা বলতে চাইছেন তা সাধারণত টাইপ টেস্টিং বলে


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

উত্তর:


48

"টাইপ টেস্টিং ঠিক আছে কখন?" এর প্রামাণিক উত্তর "কখনই নয়"? এটি প্রমাণ বা অস্বীকার করার কোনও উপায় নেই; এটি "ভাল নকশা" বা "ভাল অবজেক্ট-ওরিয়েন্টেড ডিজাইন" কী করে তোলে তা সম্পর্কে বিশ্বাসের একটি সিস্টেমের অংশ। এটিও হোকুম।

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

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

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

প্রচলিত জ্ঞান এবং কিছু উত্তর। কিছু ক্ষেত্রে যেখানে সুস্পষ্ট প্রকারের পরীক্ষাটি বোঝায়:

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

  2. আপনি ক্লাস সামঞ্জস্য করতে পারবেন না। আপনি সাবক্লাসিং সম্পর্কে ভাবেন - তবে আপনি পারবেন না। উদাহরণস্বরূপ জাভাতে অনেক ক্লাস মনোনীত করা হয় final। আপনি একটি নিক্ষেপ করার চেষ্টা করলেন public class ExtendedSubTypeA extends SubTypeA {...} এবং সংকলকটি আপনাকে কোনও অনিশ্চিত শর্তে বলবে যে আপনি যা করছেন তা সম্ভব নয়। দুঃখিত, অবজেক্ট ওরিয়েন্টেড মডেলটির অনুগ্রহ এবং পরিশীলন! কেউ সিদ্ধান্ত নিয়েছে আপনি তাদের ধরণের প্রসারিত করতে পারবেন না! দুর্ভাগ্যক্রমে, অনেকগুলি স্ট্যান্ডার্ড লাইব্রেরি হয় finalএবং ক্লাস তৈরি finalকরা সাধারণ নকশার দিকনির্দেশনা। একটি ফাংশন শেষ রান যা আপনার কাছে উপলব্ধ।

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

  3. আপনার কোডটি বাহ্যিক। আপনি এমন ক্লাস এবং অবজেক্টের সাথে বিকাশ করছেন যা বিভিন্ন সংখ্যক ডাটাবেস সার্ভার, মিডলওয়্যার ইঞ্জিন এবং আপনি নিয়ন্ত্রণ বা সামঞ্জস্য করতে পারবেন না এমন অন্যান্য কোডবেস থেকে আসে। আপনার কোডটি অন্য কোথাও উত্পন্ন জিনিসগুলির একটি নিচু ভোক্তা। এমনকি আপনি যদি সাবক্লাস করতে পারতেন তবে আপনি SuperTypeসেই লাইব্রেরিগুলি পেতে সক্ষম হবেন না যার উপর নির্ভর করে আপনি আপনার সাবক্লাসে অবজেক্ট তৈরি করতে নির্ভর করে। তারা আপনাকে জানায় যে প্রকারগুলি তারা জানায়, আপনার বৈকল্পগুলি নয়। এটি সর্বদা ক্ষেত্রে হয় না ... কখনও কখনও সেগুলি নমনীয়তার জন্য নির্মিত হয় এবং আপনি যে ক্লাসগুলি তাদের খাওয়ান সেগুলি গতিশীলভাবে ইনস্ট্যান্ট করে তোলে classes অথবা তারা সাব-ক্লাসগুলি নিবন্ধ করার জন্য একটি প্রক্রিয়া সরবরাহ করে যাতে আপনি তাদের কারখানাগুলি নির্মাণ করতে চান। এক্সএমএল পার্সারগুলি এ জাতীয় প্রবেশ পয়েন্টগুলি সরবরাহ করতে বিশেষত ভাল বলে মনে হয়; যেমন দেখুন বা পাইথনে lxML । কিন্তু কোড ঘাঁটি না না ধরনের এক্সটেনশন প্রদান। তারা আপনাকে নির্মিত ক্লাসগুলি আপনাকে ফিরিয়ে দিতে চলেছে এবং সেগুলি সম্পর্কে জানতে পারবে। এটি কেবল আপনার কাস্টম ফলাফলগুলিতে তাদের ফলাফলগুলি প্রক্সি করাতে বোধগম্য হবে না যাতে আপনি খাঁটি অবজেক্ট-ভিত্তিক ধরণের নির্বাচক ব্যবহার করতে পারেন। যদি আপনি ধরণের বৈষম্য করতে চলেছেন তবে আপনাকে এটি অপেক্ষাকৃত অপ্রয়োজনীয়ভাবে করতে হবে। আপনার টাইপ পরীক্ষার কোডটি তখন বেশ উপযুক্ত মনে হচ্ছে।

  4. দরিদ্র ব্যক্তির জেনেরিক / একাধিক প্রেরণ। আপনি আপনার কোডটিতে বিভিন্ন ধরণের বিভিন্ন গ্রহণ করতে চান এবং মনে করেন যে খুব ধরণের-নির্দিষ্ট পদ্ধতির অ্যারে থাকা কৃপণ নয়। public void add(Object x)লজিক্যাল মনে হলেও এর একটি অ্যারের না addByte, addShort, addInt, addLong, addFloat, addDouble, addBoolean, addChar, এবং addStringরূপগুলো (কয়েক নাম)। একটি উচ্চতর সুপার টাইপ গ্রহণ করে এমন ফাংশন বা পদ্ধতিগুলি রয়েছে এবং তারপরে টাইপ-টাইপ ভিত্তিতে কী করবেন তা নির্ধারণ করে - তারা আপনাকে বার্ষিক বুচ-লিসকোভ ডিজাইন সিম্পোজিয়ামে বিশুদ্ধতা পুরষ্কার জিততে পারবে না, তবে বাদ দিচ্ছে হাঙ্গেরিয়ান নামকরণ আপনাকে একটি সহজ এপিআই দেবে। এক অর্থে, আপনার is-aবাis-instance-of টেস্টিং এমন ভাষা প্রসঙ্গে জেনেরিক বা মাল্টি-প্রেরণকে অনুকরণ করে যা এটিকে স্থানীয়ভাবে সমর্থন করে না।

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

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


যদি কোনও নির্দিষ্ট ধরণের উপর কোনও ক্রিয়াকলাপ সম্পাদন করা না যায় তবে দুটি পৃথক ধরণের ক্ষেত্রে এটি সম্পাদন করা যেতে পারে যা এটি স্পষ্টত রূপান্তরযোগ্য হতে পারে, উভয় রূপান্তরটি অভিন্ন ফলাফল আনতে পারে তবেই ওভারলোডিং উপযুক্ত। অন্যথায় একটি। Cr। এর মতো কুটিল আচরণের সাথে সমাপ্ত হয়: নেট: (1.0).Equals(1.0f)সত্য উপস্থাপন করা [যুক্তি প্রচার করে double], তবে (1.0f).Equals(1.0)মিথ্যা ফল দেওয়া [যুক্তি প্রচার করে object]; জাভাতে, Math.round(123456789*1.0)123456789 ফলন হয় তবে Math.round(123456789*1.0)123456792 ফলন করে [যুক্তি তার floatপরিবর্তে উন্নীত হয় double]।
সুপারক্যাট

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

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

2
@ সুপের্যাট আমার দুর্বল দৃষ্টিকে দোষ দিচ্ছেন, তবে দুটি অভিব্যক্তি Math.roundআমার কাছে একরকম দেখাচ্ছে look পার্থক্য কি?
লিলি চুং

2
@IstvanChung: ওহো ... আধুনিক হয়েছে উচিত ছিল Math.round(123456789)[ঘটতে পারে কি কেউ নতুন করে লেখা হয় যদি পরিচায়ক Math.round(thing.getPosition() * COUNTS_PER_MIL)একটি unscaled অবস্থান মান ফেরত পাঠাতে, নিরূপক না যে getPositionএকটি ফেরৎ intবা long।]
supercat

25

দুটি পরিস্থিতি যেমন, কোনও equals(other)পদ্ধতির সাথে তুলনা করার সময় আমার যে প্রধান পরিস্থিতিটির প্রয়োজন ছিল তা হ'ল সঠিক ধরণের উপর নির্ভর করে বিভিন্ন অ্যালগরিদমের প্রয়োজন হতে পারে other। তারপরেও, এটি মোটামুটি বিরল।

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

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


1
Deserialization কেস দ্বারা আমি মুহূর্তের জন্য আনন্দিত হয়েছিল, সেখানে এটি ব্যবহার করে ভ্রান্তভাবে স্মরণ করা হয়েছে; কিন্তু, এখন আমি কীভাবে ভাবতে পারি না! আমি জানি যে এর জন্য আমি কিছু অদ্ভুত টাইপ-লুকআপ করেছি; তবে আমি নিশ্চিত নই যে এটি টাইপ টেস্টিং গঠন করে । হয়তো সিরিয়ালাইজেশন একটি আরও সমান্তরাল: তাদের কংক্রিটের ধরণের জন্য বস্তুগুলি জিজ্ঞাসাবাদ করতে হবে।
এসভিডজেন

1
পলিমারফিজম ব্যবহার করে সিরিয়ালাইজিং সাধারণত করণীয়। ডিসিরিয়ালাইজ করার সময়, আপনি প্রায়শই এমন কিছু করেন BaseClass base = deserialize(input)কারণ আপনি এখনও টাইপটি জানেন না, তবে আপনি if (base instanceof Derived) derived = (Derived)baseএটির সঠিক উত্কৃষ্ট প্রকার হিসাবে সংরক্ষণ করার জন্য এটি করেন।
কার্ল বিলেফেল্ট

1
সমতা বোধগম্য হয়। আমার অভিজ্ঞতায়, এই জাতীয় পদ্ধতিগুলির প্রায়শই একটি ফর্ম থাকে "যদি এই দুটি বস্তুর একই কংক্রিটের ধরণ থাকে তবে তাদের সমস্ত ক্ষেত্র সমান কিনা তা ফিরিয়ে দিন; অন্যথায়, মিথ্যা (বা অবিচ্ছেদ্য) ফিরিয়ে দিন ”
জন পুরি

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

12

মানক (তবে আশাকরি দুর্লভ) কেসটি দেখতে এরকম দেখাচ্ছে: যদি নিম্নলিখিত পরিস্থিতিতে থাকে

public void DoSomethingTo(SuperType o) {
  if (o isa SubTypeA) {
    DoSomethingA((SubTypeA) o )
  } else {
    DoSomethingB((SubTypeB) o );
  }
}

ফাংশনগুলি DoSomethingAবা / / DoSomethingBএর উত্তরাধিকার গাছের সদস্য ফাংশন হিসাবে সহজেই প্রয়োগ করা যায় না । উদাহরণস্বরূপ, যদিSuperTypeSubTypeASubTypeB

  • উপপ্রকারগুলি একটি লাইব্রেরির অংশ যা আপনি পরিবর্তন করতে পারবেন না, বা
  • যদি DoSomethingXXXসেই লাইব্রেরিতে কোড যুক্ত করার অর্থ একটি নিষিদ্ধ নির্ভরতা প্রবর্তন করা।

নোট করুন প্রায়শই এমন পরিস্থিতি রয়েছে যেখানে আপনি এই সমস্যাটি নিরসন করতে পারেন (উদাহরণস্বরূপ, এর জন্য একটি মোড়ক বা অ্যাডাপ্টার তৈরি করে SubTypeAএবং SubTypeB, বা DoSomethingএর মৌলিক ক্রিয়াকলাপগুলির ক্ষেত্রে পুরোপুরি পুনরায় বাস্তবায়নের চেষ্টা করার মাধ্যমে SuperType) তবে কখনও কখনও এই সমাধানগুলি ঝামেলা বা তৈরি করার পক্ষে উপযুক্ত নয় make সুস্পষ্ট ধরণের পরীক্ষা করার চেয়ে জিনিসগুলি আরও জটিল এবং কম এক্সটেনসিবল।

আমার গতকালের কাজের একটি উদাহরণ: আমার এমন একটি পরিস্থিতি ছিল যেখানে আমি বস্তুর তালিকার প্রক্রিয়াকরণের সাথে সমান্তরাল করতে যাচ্ছিলাম (টাইপের SuperType, ঠিক দুটি ভিন্ন সাব টাইপের সাথে, যেখানে এর বেশি হওয়ার সম্ভাবনা খুব কম)। উপপ্রকার A -এর বস্তু, কলিং জন্য এক লুপ: unparallelized সংস্করণ দুটি loops অন্তর্ভুক্ত DoSomethingA, এবং উপপ্রকার বি এর অবজেক্টের জন্য একটি দ্বিতীয় লুপ, কলিং DoSomethingB

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


2
আমার কুয়াশাচ্ছন্ন মস্তিষ্ককে বোঝানোর জন্য আপনি কোনও ছোট, কংক্রিটের উদাহরণ যুক্ত করতে পারেন এই পরিস্থিতিটি সংকুচিত নয়?
এসভিডজেন

পরিষ্কার করা, আমি বলছি না এটা হয় কল্পিত। আমি সন্দেহ করি যে আমি আজ কেবলমাত্র চরম কুয়াশাচ্ছন্ন।
এসভিডজেন

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

আমি মনে করি আপনার সম্পাদনা, যা আমি উপেক্ষা করেছি, একটি ভাল উদাহরণ দেয়। ... সেখানে দৃষ্টান্ত হয় যেখানে এই ঠিক আছে এমনকি যখন আপনি কি নিয়ন্ত্রণ SuperTypeএবং এটি উপশ্রেণী কি?
এসভিডজেন

6
এটি একটি কংক্রিটের উদাহরণ: একটি ওয়েব পরিষেবা থেকে জেএসএন প্রতিক্রিয়ার শীর্ষ স্তরের ধারক হয় একটি অভিধান বা অ্যারে হতে পারে। সাধারণত, আপনার কাছে এমন কিছু সরঞ্জাম রয়েছে যা NSJSONSerializationজাসনকে বাস্তব বস্তুতে পরিণত করে (যেমন ওবজ-সি), তবে আপনি কেবল বিশ্বাস করতে চান না যে প্রতিক্রিয়াটি আপনার প্রত্যাশিত ধরণের রয়েছে, সুতরাং এটি ব্যবহারের আগে এটি পরীক্ষা করে দেখুন (উদাঃ if ([theResponse isKindOfClass:[NSArray class]])...) ।
কালেব

5

চাচা বব যেমন কল করেছেন:

When your compiler forgets about the type.

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

উদাহরণ স্বরূপ:

var manager = employeeRepository.getEmployeeById(empId);
if (!(manager is Manager))
   throw new Exception("Invalid Id specified.");
manager.summon();

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

সেরা উদাহরণ নয়, তবে এটি মামার বব সর্বোপরি।

হালনাগাদ

আমি স্মৃতি থেকে যতটুকু মনে রাখতে পারি উদাহরণটি আপডেট করেছি।


1
কেন এই উদাহরণটিতে কেবল Managerপ্রয়োগ বাস্তবায়ন হয় না summon()?
এসভিডজেন

@ এসভিডজেন সম্ভবত এসকে CEOডেকে আনতে পারেন Manager
ব্যবহারকারী 253751

@ সুইডজেন, এটি তখন পরিষ্কার হবে না যে কর্মচারী রিপোসিটরি.গেট এমপ্লয়ইবিআইডি (এমপিআইডি) একজন পরিচালককে প্রত্যাশা করবে
ইয়ান

@ ইয়ান আমি এটিকে সমস্যা হিসাবে দেখছি না। যদি কলিং কোডটি কোনওটির জন্য জিজ্ঞাসা করে Employee, তবে এটির কেবল যত্ন নেওয়া উচিত যে এটি এমন কিছু পায় যা একটি জাতীয় আচরণ করে Employee। যদি বিভিন্ন সাবক্লাসের Employeeবিভিন্ন অনুমতি, দায়িত্ব ইত্যাদি থাকে, তবে টাইপ-টেস্টিং কি সত্যিকারের অনুমতি সিস্টেমের চেয়ে ভাল বিকল্প করে?
এসভিডজেন

3

টাইপ চেক ঠিক আছে কখন?

কখনও।

  1. অন্য কোনও ফাংশনে এই ধরণের সাথে সম্পর্কিত আচরণ করে, আপনি ওপেন ক্লোজড নীতি লঙ্ঘন করছেন , কারণ আপনি এই isধারাটির বিদ্যমান আচরণটি ক্লজ পরিবর্তন করে , বা (কিছু ভাষায়, বা তার উপর নির্ভর করে পরিবর্তন করতে পারেন) দৃশ্য) কারণ আপনি ফাংশনটির অভ্যন্তরীণ পরিবর্তনগুলি isপরীক্ষা না করে প্রকারটি প্রসারিত করতে পারবেন না ।
  2. আরও গুরুত্বপূর্ণ, isচেকগুলি একটি শক্তিশালী লক্ষণ যে আপনি লিসকভ সাবস্টিটিউশন নীতি লঙ্ঘন করছেন । যে কোনও জিনিসের সাথে কাজ করে SuperTypeসেগুলি কি সাব ধরণের হতে পারে তা সম্পর্কে সম্পূর্ণ অজ্ঞ হওয়া উচিত ।
  3. আপনি স্পষ্টভাবে টাইপের নামের সাথে কিছু আচরণ জড়িত করছেন । এটি আপনার কোডটি বজায় রাখা আরও শক্ত করে তোলে কারণ এই অন্তর্নিহিত চুক্তিগুলি কোডের সর্বত্র ছড়িয়ে পড়ে এবং সর্বজনীন এবং ধারাবাহিকভাবে বাস্তব শ্রেণীর সদস্যদের মতো প্রয়োগ করার নিশ্চয়তা দেয় না।

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

সংক্ষেপে, আপনার সর্বদা টাইপ চেকগুলিকে একটি শক্ত কোড গন্ধ হিসাবে বিবেচনা করা উচিত। তবে সমস্ত গাইডলাইনগুলির মতোই, এমন সময় আসবে যখন কোন নির্দেশিকা লঙ্ঘন সবচেয়ে কম আপত্তিজনক তার মধ্যে নির্বাচন করতে বাধ্য হবেন।


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

17
"কখনই নয়" এমন একটি শব্দ যা আমি সত্যিই এ জাতীয় প্রসঙ্গে পছন্দ করি না, বিশেষত যখন এটি নীচে আপনি লেখেন তা বিরোধী হয়।
ডক ব্রাউন

10
যদি "কখনই" না হয়ে আপনি আসলে "কখনও কখনও" অর্থ করেন তবে আপনি ঠিক বলেছেন।
কালেব

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

2
@ সুপের্যাট: একটি পদ্ধতির পক্ষে কমপক্ষে সুনির্দিষ্ট নির্দিষ্ট ধরণের দাবি করা উচিত যা এর প্রয়োজনীয়তাগুলি পূরণ করেIEnumerable<T>কোন "শেষ" উপাদান উপস্থিত থাকার প্রতিশ্রুতি দেয় না। আপনার পদ্ধতিতে যদি এই জাতীয় উপাদানগুলির প্রয়োজন হয় তবে এর জন্য এমন ধরণের প্রয়োজন হওয়া উচিত যা একটির অস্তিত্বের নিশ্চয়তা দেয়। এবং সেই ধরণের সাব টাইপগুলি তারপরে "শেষ" পদ্ধতির দক্ষ প্রয়োগকরণ সরবরাহ করতে পারে।
সিএওও

2

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

তারপরে আপনার মাঝে মাঝে সিস্টেমের একটি বৃহত প্রতিরোধকের বিকল্প বা কিছু সাধারণ স্থানীয় "টাইপ টেস্টিং" থাকে। এটি এমন একটি প্রযুক্তিগত debtণ তৈরি করে যা যত তাড়াতাড়ি সম্ভব পরিশোধ করা উচিত, তবে প্রায়শই তা হয় না।

(উদাহরণস্বরূপ উপস্থিত হওয়া অসম্ভব, উদাহরণস্বরূপ ব্যবহারের জন্য যথেষ্ট ছোট যে কোনও কোড, আরও ভাল ডিজাইনের জন্য পরিষ্কারভাবে দৃশ্যমান হওয়ার পক্ষে যথেষ্ট ছোট))

বা অন্য কথায়, যখন লক্ষ্যটি হয় আপনার নকশার বিশুদ্ধতার জন্য "ভোট আপ" না দিয়ে আপনার মজুরি প্রদান করা।


অন্যান্য সাধারণ কেসটি হ'ল ইউআই কোড, যখন উদাহরণস্বরূপ আপনি কিছু ধরণের কর্মচারীদের জন্য আলাদা UI দেখান, তবে স্পষ্টতই আপনি চান না যে UI ধারণাটি আপনার সমস্ত "ডোমেন" শ্রেণিতে পালিয়ে যায়।

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

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


আপনার ইউআই কেস সমাধান করার জন্য দর্শনার্থীর প্যাটার্নটি প্রায়শই ভাল উপায়।
আয়ান গোল্ডবাই

@ ইয়ান গোল্ডবি, এমন সময়ে একমত হয়েছিলেন, যদিও আপনি এখনও "টাইপ টেস্টিং" করছেন, কিছুটা লুকিয়ে রেখেছেন।
ইয়ান

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

@ ইয়ান গোল্ডবি, আমার অর্থ এই অর্থে লুকানো ছিল যে এটি ডাব্লুপিএফ বা উইনফোর্ডস কোডটি বোঝা আরও শক্ত করে তুলতে পারে। আমি আশা করি যে কোনও ওয়েব বেস ইউআই-এর জন্য এটি খুব ভালভাবে কাজ করবে।
ইয়ান

2

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

সর্বাধিক সুস্পষ্ট উদাহরণ সম্ভবত এলিমেন্টআট পদ্ধতি (। নেট 5.5 উত্সের ক্ষুদ্র অংশ):

public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, int index) { 
    IList<TSource> list = source as IList<TSource>;

    if (list != null) return list[index];
    // ... and then an enumerator is created and MoveNext is called index times

তবে এনিউমারেবল ক্লাসে প্রচুর জায়গা রয়েছে যেখানে একই ধরণের প্যাটার্ন ব্যবহৃত হয়।

সুতরাং সম্ভবত একটি সাধারণ ব্যবহৃত সাব টাইপের জন্য পারফরম্যান্সের জন্য অনুকূলকরণ একটি বৈধ ব্যবহার। আমি কীভাবে এটি আরও ভাল ডিজাইন করা যেতে পারে তা নিশ্চিত নই।


ইন্টারফেসগুলি ডিফল্ট বাস্তবায়ন সরবরাহ করতে পারে এমন কোনও সুবিধাজনক উপায় সরবরাহ করে এটি আরও ভালভাবে ডিজাইন করা যেতে পারে, এবং তারপরে IEnumerable<T>এমন একটি পদ্ধতির List<T>পাশাপাশি এমন পদ্ধতিগুলি অন্তর্ভুক্ত Featuresকরে যা কোনও পদ্ধতিগুলি ভাল, ধীরে ধীরে বা একেবারে না থেকে কাজ করার আশা করা যায়, তা নির্দেশ করে, পাশাপাশি গ্রাহকরা সংগ্রহ সম্পর্কে নিরাপদে করতে পারেন এমন বিভিন্ন অনুমান (যেমন এর আকার এবং / অথবা এর বিদ্যমান সামগ্রীগুলি কখনই পরিবর্তন না করার গ্যারান্টিযুক্ত [একটি প্রকার Addএখনও সমর্থন করতে পারে যে বিদ্যমান সামগ্রীগুলি অপরিবর্তনীয় হবে))।
সুপারক্যাট

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

1

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

ধরে নিন যে সমস্ত গেমের অবজেক্টগুলি একটি সাধারণ বেস শ্রেণি থেকে প্রাপ্ত GameObject। প্রতিটি বস্তুর একটি অনমনীয় শরীর সংঘর্ষের আকৃতি আছে CollisionShapeযা একটি সাধারণ ইন্টারফেস প্রদান করতে পারে তবে প্রকৃত সংঘর্ষের আকার সব যেমন কংক্রিট উপশ্রেণী হতে হবে (কোয়েরি অবস্থান, অভিযোজন, ইত্যাদি বলতে) Sphere, Box, ConvexHull, ইত্যাদি সংরক্ষণ জ্যামিতিক বস্তুর যে ধরনের সুনির্দিষ্ট তথ্য ( বাস্তব উদাহরণের জন্য এখানে দেখুন )

এখন, সংঘর্ষের জন্য পরীক্ষা করার জন্য আমার প্রতিটি জোড়া সংঘর্ষের আকারের জন্য একটি ফাংশন লিখতে হবে:

detectCollision(Sphere, Sphere)
detectCollision(Sphere, Box)
detectCollision(Sphere, ConvexHull)
detectCollision(Box, ConvexHull)
...

এই দুটি জ্যামিতিক ধরণের ছেদটি সম্পাদনের জন্য প্রয়োজনীয় গণিত রয়েছে।

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

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

আমি এটি বলছি না যে এটি অগত্যা একটি ভাল সমাধান, এটি এই সমস্যাটির সম্ভাব্য সমাধানগুলির সংখ্যক সমাধানের মধ্যে সেরা হতে পারে just

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


1

কখনও কখনও আপনি সমস্ত ক্লাসে একটি সাধারণ পদ্ধতি যুক্ত করতে চান না কারণ এই নির্দিষ্ট কাজটি সম্পাদন করা তাদের দায়বদ্ধতা নয়।

উদাহরণস্বরূপ আপনি কিছু সত্ত্বা আঁকতে চান তবে সরাসরি অঙ্কন কোড তাদের সাথে যুক্ত করতে চান না (যা বোঝায়)। একাধিক প্রেরণকে সমর্থন করে না এমন ভাষায় আপনি নিম্নলিখিত কোডটি দিয়ে শেষ করতে পারেন:

void DrawEntity(Entity entity) {
    if (entity instanceof Circle) {
        DrawCircle((Circle) entity));
    else if (entity instanceof Rectangle) {
        DrawRectangle((Rectangle) entity));
    } ...
}

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


0

আমি কেবলমাত্র সময়টি প্রতিবিম্বের সাথে একত্রে ব্যবহার করি। তবে তারপরেও বেশিরভাগ গতিশীল চেকিং হয়, নির্দিষ্ট শ্রেণিতে হার্ড কোডিং হয় না (বা কেবলমাত্র বিশেষ কোড যেমন Stringবা এর মতো হার্ড-কোডিং থাকে List)।

ডায়নামিক চেকিং দ্বারা আমি বলতে চাইছি:

boolean checkType(Type type, Object object) {
    if (object.isOfType(type)) {

    }
}

এবং হার্ড কোডেড নয়

boolean checkIsManaer(Object object) {
    if (object instanceof Manager) {

    }
}

0

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

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

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

টাইপ টেস্টিংও প্রায়শই প্রতিবিম্বিত হয়। প্রায়শই আপনার কাছে এমন পদ্ধতি থাকে যাগুলি ফিরে আসে Object[]বা অন্য কোনও জেনেরিক অ্যারে থাকে এবং আপনি যে Fooকোনও কারণেই সমস্ত বস্তু টেনে আনতে চান । এটি টাইপ টেস্টিং এবং ingালাইয়ের পুরোপুরি বৈধ ব্যবহার।

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


1
ArrayListsরানটাইমে ক্লাসটি সংরক্ষণ করা হচ্ছে তা জানেন না কারণ জাভাতে জেনেরিকস ছিল না এবং অবশেষে যখন তাদের সাথে পরিচয় করা হয়েছিল তখন জেরিক্স-কম কোডের সাথে পিছনে-সামঞ্জস্যের পক্ষে ওরেकल বেছে নেওয়া হয়েছিল। equalsএকই সমস্যা আছে, এবং এটি যাইহোক প্রশ্নোত্তর নকশা সিদ্ধান্ত; সমতার তুলনা প্রতিটি ধরণের জন্য অর্থপূর্ণ নয়।
ডোভাল

1
প্রযুক্তিগতভাবে, জাভা সংগ্রহগুলি তাদের বিষয়বস্তুগুলিকে কোনও কিছুতেই ফেলে দেয় না । সংকলক প্রতিটি অ্যাক্সেসের স্থানে টাইপকাস্টগুলি ইনজেকশন দেয়: যেমনString x = (String) myListOfStrings.get(0)

শেষবার আমি জাভা উত্সের দিকে তাকালাম (যা হতে পারে 1.6 বা 1.5) হতে পারে অ্যারেলিস্ট উত্সে একটি স্পষ্ট কাস্ট ছিল। এটি ভাল কারণে একটি (চাপা) সংকলক সতর্কতা উত্পন্ন করে তবে যাইহোক অনুমতি দেওয়া হয়। আমি মনে করি আপনি বলতে পারেন যে জেনেরিকগুলি কীভাবে প্রয়োগ করা হয়, এটি Objectযেভাবেই অ্যাক্সেস না করা পর্যন্ত এটি সর্বদা ছিল; জাভাতে জেনেরিকগুলি কেবল সংকলক বিধি দ্বারা সুরক্ষিত অন্তর্নিহিত castালাই সরবরাহ করে।
meustrus

0

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

abstract class Vehicle
{
    abstract void Process();
}

class Car : Vehicle { ... }
class Boat : Vehicle { ... }
class Truck : Vehicle { ... }

এখন বলা যাক আমাদের ব্যবসায়ের যুক্তিটি আক্ষরিক অর্থে "সমস্ত গাড়ি নৌকা ও ট্রাকের চেয়ে অগ্রাধিকার পায়"। Priorityশ্রেণিতে একটি সম্পত্তি যুক্ত করা আপনাকে এই ব্যবসার যুক্তিটি পরিষ্কারভাবে প্রকাশ করতে দেয় না কারণ আপনি এটি দিয়ে শেষ করবেন:

abstract class Vehicle
{
    abstract void Process();
    abstract int Priority { get }
}

class Car : Vehicle { public Priority { get { return 1; } } ... }
class Boat : Vehicle { public Priority { get { return 2; } } ... }
class Truck : Vehicle { public Priority { get { return 2; } } ... }

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

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

static class Priorities
{
    public const int CAR_PRIORITY = 1;
    public const int BOAT_PRIORITY = 2;
    public const int TRUCK_PRIORITY = 2;
}

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

class VehicleScheduler : IScheduleVehicles
{
    public Vehicle WhichVehicleGoesFirst(Vehicle vehicle1, Vehicle vehicle2)
    {
        if(vehicle1 is Car) return vehicle1;
        if(vehicle2 is Car) return vehicle2;
        return vehicle1;
    }
}

এটি ব্যবসায়ের যুক্তি বাস্তবায়নের সবচেয়ে সোজা উপায় এবং ভবিষ্যতের পরিবর্তনের জন্য এখনও সবচেয়ে নমনীয়।


আমি আপনার বিশেষ উদাহরণের সাথে একমত নই, তবে একটি ব্যক্তিগত রেফারেন্স থাকার নীতিতে একমত হব যা বিভিন্ন অর্থ সহ বিভিন্ন ধরণের ধারণ করতে পারে। আমি এর চেয়ে ভাল উদাহরণ হিসাবে যা পরামর্শ দেব তা হ'ল এমন ক্ষেত্র যা হ'ল null, ক String, বা এটিকে ধরে রাখতে পারে String[]। যদি 99% অবজেক্টের ঠিক একটি স্ট্রিং প্রয়োজন হয়, পৃথকভাবে নির্মিত প্রতিটি স্ট্রিংকে encapসুলেটেড String[]স্টোরেজ ওভারহেড যুক্ত করতে পারে। একটিতে সরাসরি রেফারেন্স ব্যবহার করে সিঙ্গল-স্ট্রিং কেস পরিচালনা করার Stringজন্য আরও কোডের প্রয়োজন হবে তবে স্টোরেজ সংরক্ষণ করবে এবং জিনিসগুলি আরও দ্রুত তৈরি করতে পারে।
সুপারক্যাট

0

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

আমাদের সফ্টওয়্যারটিতে আমরা অনুরোধের প্রতিক্রিয়া হিসাবে নেটওয়ার্কের মাধ্যমে বার্তা পেয়েছি। সমস্ত deserialized বার্তাগুলি একটি সাধারণ বেস শ্রেণি ভাগ করে Message

ক্লাসগুলি নিজেরাই খুব সাধারণ ছিল, কেবল টাইপড সি # বৈশিষ্ট্য হিসাবে পেলোড এবং মার্শেলিং এবং আনমারশিলিংয়ের রুটিনগুলি (আসলে আমি বার্তার বিন্যাসের এক্সএমএল বিবরণ থেকে টি 4 টেমপ্লেট ব্যবহার করে বেশিরভাগ ক্লাস তৈরি করেছি)

কোড কিছু হবে:

Message response = await PerformSomeRequest(requestParameter);

// Server (out of our control) would send one message as response, but 
// the actual message type is not known ahead of time (it depended on 
// the exact request and the state of the server etc.)
if (response is ErrorMessage)
{ 
    // Extract error message and pass along (for example using exceptions)
}
else if (response is StuffHappenedMessage)
{
    // Extract results
}
else if (response is AnotherThingHappenedMessage)
{
    // Extract another type of result
}
// Half a dozen other possible checks for messages

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

লক্ষণীয় যে সি # 7.0 প্যাটার্ন ম্যাচিং পাচ্ছে (যা অনেক দিক থেকে স্টেরয়েডগুলিতে টাইপ টেস্টিং) এটি সমস্ত খারাপ হতে পারে না ...


0

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


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