মার্কার ইন্টারফেসের উদ্দেশ্য কী?
উত্তর:
এটি "মিচ হুইট" এর প্রতিক্রিয়ার ভিত্তিতে কিছুটা স্পর্শকাতর।
সাধারণত, যে কোনও সময় আমি লোককে ফ্রেমওয়ার্ক ডিজাইনের নির্দেশিকা উদ্ধৃত করে দেখি, আমি সর্বদা এটি উল্লেখ করতে চাই:
আপনার বেশিরভাগ সময় ফ্রেমওয়ার্ক ডিজাইনের গাইডলাইনগুলি সাধারণত উপেক্ষা করা উচিত।
এটি ফ্রেমওয়ার্ক ডিজাইন নির্দেশিকাগুলির কোনও সমস্যার কারণে নয়। আমি NET ফ্রেমওয়ার্ক একটি চমত্কার বর্গ গ্রন্থাগার মনে করি। ফ্রেমওয়ার্ক ডিজাইনের গাইডলাইন থেকে সেই চমকপ্রদতা প্রবাহিত হয়।
তবে বেশিরভাগ প্রোগ্রামার দ্বারা লিখিত বেশিরভাগ কোডে নকশার নির্দেশিকা প্রযোজ্য নয়। তাদের উদ্দেশ্য হ'ল গ্রন্থাগার রচনাকে আরও দক্ষ করে তুলতে নয়, লক্ষ লক্ষ বিকাশকারী দ্বারা ব্যবহৃত একটি বৃহত কাঠামো তৈরি করা সক্ষম করা।
এতে থাকা প্রচুর পরামর্শ আপনাকে সেই কাজগুলি করতে গাইড করতে পারে যা:
। নেট ফ্রেমওয়ার্কটি বড়, সত্যই বড়। এটি এতটাই বড় যে এটি অনুমান করা একেবারেই অযৌক্তিক হবে যে এর প্রত্যেকটি দিক সম্পর্কে যে কেউ বিশদ জ্ঞান আছে। প্রকৃতপক্ষে, এটি ধরে নেওয়া আরও নিরাপদ যে বেশিরভাগ প্রোগ্রামাররা প্রায়শই আগে কখনও ব্যবহার করেন না এমন কাঠামোর অংশগুলির মুখোমুখি হন।
সেক্ষেত্রে কোনও এপিআই ডিজাইনারের প্রাথমিক লক্ষ্যগুলি হ'ল:
ফ্রেমওয়ার্ক ডিজাইনের গাইডলাইনগুলি বিকাশকারীদের কোড তৈরি করতে চাপ দেয় যা এই লক্ষ্যগুলি সম্পাদন করে।
এর অর্থ হ'ল উত্তরাধিকারের স্তরগুলি এড়ানোর মতো জিনিসগুলি করা, এমনকি যদি এটি সদৃশ কোডের অর্থও হয়, বা অংশীদারি সাহায্যকারীদের ব্যবহারের পরিবর্তে সমস্ত ব্যতিক্রম কোডকে "এন্ট্রি পয়েন্টগুলিতে" ফেলে দেওয়া হয় (যাতে স্ট্যাকের চিহ্নগুলি ডিবাগারে আরও বোঝা যায়), এবং আরও অনেক কিছু অন্যান্য অনুরূপ জিনিস।
এই নির্দেশিকাগুলি চিহ্নিতকারী ইন্টারফেসের পরিবর্তে বৈশিষ্ট্যগুলি ব্যবহার করার পরামর্শ দেয় এমন প্রাথমিক কারণ হ'ল মার্কার ইন্টারফেসগুলি অপসারণ করা বর্গ লাইব্রেরির উত্তরাধিকার কাঠামোকে আরও বেশি অ্যাক্সেসযোগ্য করে তোলে। 30 ধরণের এবং উত্তরাধিকারের স্তরক্রমের 6 স্তর সহ একটি বর্গের চিত্রটি 15 ধরণের এবং হায়ারার্কির 2 স্তরগুলির সাথে একের তুলনায় খুব বিরক্তিকর।
যদি আপনার এপিআইগুলি ব্যবহার করে লক্ষ লক্ষ বিকাশকারী হয় বা আপনার কোড বেসটি সত্যিই বড় (100 কে এলওসি-র উপরে বলুন) তবে সেই নির্দেশিকাগুলি অনুসরণ করা আপনাকে অনেক সহায়তা করতে পারে।
যদি 5 মিলিয়ন বিকাশকারীরা 60 মিনিট এটি শেখার পরিবর্তে একটি এআইপি শিখতে 15 মিনিট ব্যয় করে তবে ফলাফলটি 428 বছর বয়সের নিট সঞ্চয়। এটাই অনেক সময়।
তবে বেশিরভাগ প্রকল্পে লক্ষ লক্ষ বিকাশকারী বা 100 কে + এলওসি জড়িত না। একটি সাধারণ প্রকল্পে, 4 বিকাশকারী এবং প্রায় 50K লোকের সহ, অনুমানের সেটটি অনেক আলাদা। টিমের বিকাশকারীদের কোড কীভাবে কাজ করে সে সম্পর্কে আরও ভাল ধারণা থাকবে। এর অর্থ এটি যে উচ্চ মানের কোডটি দ্রুত তৈরি করার জন্য, এবং বাগের পরিমাণ হ্রাস করার জন্য এবং পরিবর্তনগুলি করার জন্য প্রয়োজনীয় প্রচেষ্টাটি আরও বেশি বোধগম্য করে।
। নেট ফ্রেমওয়ার্কের সাথে সামঞ্জস্যপূর্ণ 1 সপ্তাহের বিকাশকারী কোড ব্যয় করা, বনাম 8 ঘন্টা রাইটিং কোড যা পরিবর্তন করা সহজ এবং এতে কম বাগ রয়েছে তার ফলস্বরূপ:
4,999,999 ছাড়া অন্য বিকাশকারীদের ব্যয়গুলি শোষণ করার জন্য এটি সাধারণত মূল্য হয় না।
উদাহরণস্বরূপ, চিহ্নিতকারী ইন্টারফেসের জন্য পরীক্ষা করা একটি একক "is" এক্সপ্রেশনতে নেমে আসে এবং এর ফলে কম কোড পাওয়া যায় যা গুণাবলীর সন্ধান করে।
সুতরাং আমার পরামর্শটি হ'ল:
virtual protected
টেম্পলেট পদ্ধতির নামকরণ করা তেমন অতিরিক্ত কাজ নয় এবং আপনি স্পষ্টভাবে যোগাযোগ করেন যে এটি একটি টেম্পলেট পদ্ধতি ... আইএমএনএসএইচও, এপিআই ( ) বিবেচনা না করে অ্যাপ্লিকেশন লেখার লোকেরা হুবহু সেই লোকেরা যারা প্রচুর নকল লেখেন ( এবং অপ্রকাশিত এবং সাধারণত অপঠনযোগ্য) কোডটি অন্যদিকে নয়। DoSomethingCore
DoSomething
But.. I'm not a framework developer, I don't care about my API!
মার্কার ইন্টারফেসগুলি রান-টাইমে একটি নির্দিষ্ট ইন্টারফেস বাস্তবায়ন হিসাবে শ্রেণীর সক্ষমতা চিহ্নিত করতে ব্যবহৃত হয়।
ইন্টারফেস ডিজাইন এবং .NET টাইপ নকশা নির্দেশিকা - ইন্টারফেস ডিজাইন C # বৈশিষ্ট্যাবলী ব্যবহারের পক্ষে মার্কার ইন্টারফেস ব্যবহার নিরুত্সাহিত, কিন্তু @Jay Bazuzi তুলে ধরে, এটা বৈশিষ্ট্যাবলী চেয়ে মার্কার ইন্টারফেসের জন্য চেক করতে সহজ হয়:o is I
সুতরাং এর পরিবর্তে:
public interface IFooAssignable {}
public class FooAssignableAttribute : IFooAssignable
{
...
}
.NET নির্দেশিকাগুলি আপনাকে এটি করার পরামর্শ দেয়:
public class FooAssignableAttribute : Attribute
{
...
}
[FooAssignable]
public class Foo
{
...
}
যেহেতু অন্য প্রতিটি উত্তরে "তাদের এড়ানো উচিত" বলে উল্লেখ করা হয়েছে, তাই এর কারণ ব্যাখ্যা করা কার্যকর হবে।
প্রথমত, কেন মার্কার ইন্টারফেস ব্যবহার করা হয়: তারা যে ইন্টারফেসটি প্রয়োগ করে এটি ব্যবহার করে এমন কোডটি মঞ্জুরি দেওয়ার জন্য উপস্থিত রয়েছে যা তারা বলেছে যে ইন্টারফেস প্রয়োগ করেছে কিনা তা পরীক্ষা করতে এবং যদি এটি ব্যবহার করে তবে বস্তুটিকে অন্যরকম আচরণ করবে।
এই পদ্ধতির সাথে সমস্যা হ'ল এটি এনকেপসুলেশনটি ভেঙে দেয়। কীভাবে এটি বাহ্যিকভাবে ব্যবহৃত হবে তার উপরে এখন অবজেক্টেরই পরোক্ষ নিয়ন্ত্রণ রয়েছে। তদুপরি, এটিতে ব্যবহৃত সিস্টেমটি সম্পর্কে এটি জ্ঞান রয়েছে the মার্কার ইন্টারফেস প্রয়োগ করে শ্রেণি সংজ্ঞাটি প্রস্তাব করছে যে এটি কোথাও ব্যবহার করা হবে যা চিহ্নিতকারীটির অস্তিত্বের জন্য যাচাই করে। এটি যে পরিবেশে ব্যবহৃত তা সম্পর্কে নিহিত জ্ঞান রয়েছে এবং এটি কীভাবে ব্যবহার করা উচিত তা নির্ধারণের চেষ্টা করছে। এটি এনক্যাপসুলেশনের ধারণার বিপরীতে যায় কারণ এতে সিস্টেমের এমন একটি অংশের বাস্তবায়ন সম্পর্কে জ্ঞান রয়েছে যা সম্পূর্ণভাবে তার নিজস্ব ক্ষেত্রের বাইরে থাকে।
ব্যবহারিক স্তরে এটি বহনযোগ্যতা এবং পুনঃব্যবহারযোগ্যতা হ্রাস করে। যদি ক্লাসটি অন্য কোনও অ্যাপ্লিকেশনটিতে পুনরায় ব্যবহার করা হয়, তবে ইন্টারফেসটি খুব বেশি অনুলিপি করা দরকার এবং এটি নতুন পরিবেশে সম্পূর্ণ অর্থহীন হয়ে ওঠার কোনও অর্থ নাও থাকতে পারে।
যেমন, "চিহ্নিতকারী" ক্লাস সম্পর্কে মেটাডেটা। এই মেটাডেটা ক্লাস নিজেই ব্যবহার করে না এবং কেবলমাত্র (কিছু!) বহিরাগত ক্লায়েন্ট কোডের জন্য অর্থবহ যাতে এটি কোনও নির্দিষ্ট উপায়ে আচরণ করতে পারে। যেহেতু এটির কেবল ক্লায়েন্ট কোডের অর্থ রয়েছে, মেটাডেটা ক্লায়েন্ট কোডে থাকা উচিত, ক্লাস এপিআইতে নয়।
একটি "মার্কার ইন্টারফেস" এবং একটি স্বাভাবিক ইন্টারফেস মধ্যে পার্থক্য হচ্ছে পদ্ধতি সঙ্গে একটি ইন্টারফেস বহির্বিশ্বের কিভাবে এটি বলে হয় পারেন যেহেতু একটি খালি ইন্টারফেস বোঝা এটা বহির্বিশ্বের বলছে এটা কিভাবে ব্যবহার করা যেতে উচিত ব্যবহৃত হবে না।
IConstructableFromString<T>
নির্দিষ্ট করা হয় যে কোনও শ্রেণীর যদি স্থির সদস্য থাকে তবেই এটি T
প্রয়োগ করতে পারে IConstructableFromString<T>
...
public static T ProduceFromString(String params);
, ইন্টারফেসের সহচর শ্রেণি কোনও পদ্ধতি প্রস্তাব করতে পারে public static T ProduceFromString<T>(String params) where T:IConstructableFromString<T>
; যদি ক্লায়েন্ট কোডের মতো কোনও পদ্ধতি থাকে T[] MakeManyThings<T>() where T:IConstructableFromString<T>
তবে কোনও নতুন ধরণের সংজ্ঞা দিতে পারে যা তাদের সাথে ডিল করার জন্য ক্লায়েন্ট কোডটি পরিবর্তন না করে ক্লায়েন্ট কোডের সাথে কাজ করতে পারে। যদি মেটাডেটা ক্লায়েন্ট কোডে থাকে তবে বিদ্যমান ক্লায়েন্টের দ্বারা ব্যবহারের জন্য নতুন ধরণের তৈরি করা সম্ভব হবে না।
T
এটির ব্যবহারকারীর এবং শ্রেণীর মধ্যে চুক্তিটি হ'ল IConstructableFromString<T>
ইন্টারফেসে আপনার এমন একটি পদ্ধতি রয়েছে যা কিছু আচরণের বর্ণনা দেয় যাতে এটি কোনও মার্কার ইন্টারফেস নয়।
ProduceFromString
উপরের উদাহরণে স্থির পদ্ধতিটি অনুসন্ধান এবং কার্যকর করার প্রকৃত প্রক্রিয়া জড়িত না ইন্টারফেসটি কোনও উপায়েই, ইন্টারফেসটিকে চিহ্নিতকারী হিসাবে কোন শ্রেণীর দ্বারা প্রয়োজনীয় ফাংশনটি বাস্তবায়নের আশা করা উচিত তা চিহ্নিত করার জন্য ব্যবহৃত হবে।
যখন কোনও ভাষা বৈষম্যমূলক ইউনিয়নের ধরণগুলিকে সমর্থন না করে তখন मार्कर ইন্টারফেসগুলি কখনও কখনও প্রয়োজনীয় অশুভ হতে পারে ।
মনে করুন আপনি এমন একটি পদ্ধতি নির্ধারণ করতে চান যিনি এমন আর্গুমেন্টের প্রত্যাশা করেন যার প্রকারটি অবশ্যই A, B বা C. এর মধ্যে একটি হতে হবে, অনেকগুলি কার্যকরী-প্রথম ভাষায় (যেমন F # ), এই জাতীয় প্রকারটি পরিষ্কারভাবে সংজ্ঞায়িত করা যেতে পারে:
type Arg =
| AArg of A
| BArg of B
| CArg of C
তবে সিওয়ের মতো ওও-প্রথম ভাষায়, এটি সম্ভব নয়। এখানে অনুরূপ কিছু অর্জনের একমাত্র উপায় হ'ল ইন্টারফেস IArg সংজ্ঞায়িত করা এবং এটির সাথে "চিহ্ন" এ, বি এবং সি।
অবশ্যই, আপনি কেবল "বস্তু" টাইপটিকে আর্গুমেন্ট হিসাবে গ্রহণ করে মার্কার ইন্টারফেসটি ব্যবহার এড়াতে পারবেন, তবে তারপরে আপনি ভাব প্রকাশ এবং কিছুটা ধরণের সুরক্ষা হারাবেন।
বৈষম্যমূলক ইউনিয়নের প্রকারগুলি অত্যন্ত কার্যকর এবং কমপক্ষে 30 বছর ধরে কার্যকরী ভাষায় বিদ্যমান। আশ্চর্যের বিষয় হল, আজ অবধি, সমস্ত মূলধারার ওও ভাষাগুলি এই বৈশিষ্ট্যটিকে উপেক্ষা করেছে - যদিও এটির প্রতি কার্যকরী প্রোগ্রামিংয়ের সাথে আসলে কিছুই করার নেই, তবে এটি টাইপ সিস্টেমের সাথে সম্পর্কিত।
Foo<T>
প্রতিটি ধরণের জন্য স্ট্যাটিক ক্ষেত্রগুলির একটি পৃথক সেট T
থাকবে, জেনেরিক শ্রেণিতে একটি প্রসেসের জন্য প্রতিনিধি সমন্বিত স্ট্যাটিক ফিল্ড থাকা T
এবং ক্লাসটি প্রতিটি ধরণের পরিচালনা করার জন্য ফাংশনগুলি সহ সেই ক্ষেত্রগুলিকে প্রাক-জনবসতি করা শক্ত নয় not সঙ্গে কাজ করার কথা। জেনেরিক ইন্টারফেস সীমাবদ্ধতা টাইপ ব্যবহার T
করে সংকলক সময়ে পরীক্ষা করা হবে যে সরবরাহকৃত টাইপটি অন্তত বৈধ বলে দাবি করেছে, যদিও এটি এটি যে এটি সত্য তা নিশ্চিত করতে সক্ষম হবে না।
একটি চিহ্নিতকারী ইন্টারফেসটি কেবল একটি ইন্টারফেস যা খালি। কোনও শ্রেণি কোনও কারণে এই ইন্টারফেসটি মেটাডেটা হিসাবে প্রয়োগ করবে। সি # তে আপনি আরও সাধারণভাবে একই কারণে ক্লাসটি চিহ্নিত করার জন্য বৈশিষ্ট্যগুলি ব্যবহার করবেন আপনি অন্যান্য ভাষায় মার্কার ইন্টারফেসটি ব্যবহার করবেন।
একটি চিহ্নিতকারী ইন্টারফেসটি কোনও বর্গকে এমনভাবে ট্যাগ করার অনুমতি দেয় যা সমস্ত বংশধর শ্রেণিতে প্রয়োগ করা হবে। একটি "খাঁটি" চিহ্নিতকারী ইন্টারফেসটি কোনও কিছুর সংজ্ঞা দেয় বা উত্তরাধিকারসূত্রে থাকে না; আরও কার্যকর ধরণের মার্কার ইন্টারফেস হতে পারে যা অন্য ইন্টারফেসটির "উত্তরাধিকার সূত্রে প্রাপ্ত" তবে নতুন সদস্যদের সংজ্ঞা দেয় না। উদাহরণস্বরূপ, যদি একটি ইন্টারফেস "IReadableFoo" থাকে, কেউ একটি ইন্টারফেস "IImmutableFoo" সংজ্ঞায়িত করতে পারে, এটি একটি "Foo" এর মতো আচরণ করবে তবে যে কেউ এটি ব্যবহার করবে তাকে প্রতিশ্রুতি দেবে যে কিছুই তার মান পরিবর্তন করবে না। একটি রুটিন যা IImmutableFoo গ্রহণ করে এটি এটি IReadableFoo হিসাবে ব্যবহার করতে সক্ষম হবে, তবে রুটিন কেবল IImmutableFoo বাস্তবায়ন হিসাবে ঘোষিত শ্রেণিগুলিকে গ্রহণ করবে।
আমি "খাঁটি" চিহ্নিতকারী ইন্টারফেসের জন্য পুরো প্রচুর ব্যবহারের কথা ভাবতে পারি না। কেবলমাত্র আমিই ভাবতে পারি যদি ইক্যুয়ালিটি কম্পিউটার (টি এর) থাকে। ডিফল্টটি অবজেক্টটি প্রত্যাবর্তন করে ID IDoNotUseEqualityComparer প্রয়োগকারী যে কোনও প্রকারের জন্য, যদি প্রকারটি আইকোয়ালিটি কম্পিউটারকেও প্রয়োগ করে, তবে প্রযোজ্য। এটি একজনকে লিসকভ সাবস্টিটিউশন নীতি লঙ্ঘন না করে একটি অনিবন্ধিত অপরিবর্তনীয় প্রকারের অনুমতি দেবে: প্রকারটি যদি সাম্যতা-পরীক্ষার সাথে সম্পর্কিত সমস্ত পদ্ধতি সিল করে তবে একটি উত্পন্ন ধরণের অতিরিক্ত ক্ষেত্র যুক্ত হতে পারে এবং সেগুলি পরিবর্তনযোগ্য হতে পারে, তবে এই ধরনের ক্ষেত্রগুলির পরিব্যক্তি ' টি কোনও বেস-টাইপ পদ্ধতি ব্যবহার করে দৃশ্যমান হবে। অপরিবর্তিত অপরিবর্তনীয় শ্রেণি থাকা এবং আইক্যুয়ালিটি কম্পিউটারের বাস্তবায়ন না করার জন্য ইক্যুয়ালিটি কম্পিউটারের ডিফল্ট বা বিশ্বাসের উত্সযুক্ত শ্রেণীর কোনও ব্যবহার এড়ানো উচিত নয়, এটি ভয়ঙ্কর হতে পারে না,
এই দুটি এক্সটেনশন পদ্ধতি বেশিরভাগ সমস্যার সমাধান করবে স্কট বৈশিষ্ট্যের চেয়ে মার্কার ইন্টারফেসের পক্ষে বলে:
public static bool HasAttribute<T>(this ICustomAttributeProvider self)
where T : Attribute
{
return self.GetCustomAttributes(true).Any(o => o is T);
}
public static bool HasAttribute<T>(this object self)
where T : Attribute
{
return self != null && self.GetType().HasAttribute<T>()
}
এখন তোমার আছে:
if (o.HasAttribute<FooAssignableAttribute>())
{
//...
}
বনাম:
if (o is IFooAssignable)
{
//...
}
স্কটের দাবি অনুসারে, প্রথম প্যাটার্নের সাথে কীভাবে এপিআই তৈরি করতে 5 গুণ বেশি সময় লাগবে তা আমি দেখতে ব্যর্থ হয়েছি।
চিহ্নিতকারী খালি ইন্টারফেস হয়। একটি চিহ্নিতকারী হয় হয় বা না হয়।
ক্লাস ফু: আইকনফেসিয়াল
এখানে আমরা ফুকে গোপনীয় হিসাবে চিহ্নিত করি। কোন প্রকৃত অতিরিক্ত বৈশিষ্ট্য বা বৈশিষ্ট্য প্রয়োজন।
চিহ্নিতকারী ইন্টারফেস একটি মোট ফাঁকা ইন্টারফেস যা এর কোনও বডি / ডেটা-সদস্য / বাস্তবায়ন নেই।
কোনও শ্রেণি যখন প্রয়োজন হয় তখন চিহ্নিতকারী ইন্টারফেস প্রয়োগ করে , এটি কেবল " চিহ্নিত " করা যায়; এর অর্থ এটি জেভিএমকে বলে যে নির্দিষ্ট শ্রেণি ক্লোনিংয়ের উদ্দেশ্যে তাই এটি ক্লোন করার অনুমতি দিন। এই নির্দিষ্ট বর্গটি তার অবজেক্টগুলিকে সিরিয়ালাইজ করার জন্য তাই দয়া করে এর বিষয়গুলি সিরিয়ালীকৃত হওয়ার অনুমতি দিন।
চিহ্নিতকারী ইন্টারফেসটি সত্যিই ওও ভাষায় কেবলমাত্র একটি প্রক্রিয়াজাতীয় প্রোগ্রামিং। একটি ইন্টারফেস প্রয়োগকারী এবং গ্রাহকদের মধ্যে একটি চুক্তি সংজ্ঞায়িত করে, একটি মার্কার ইন্টারফেস ব্যতীত, কারণ একটি মার্কার ইন্টারফেস নিজেই ব্যতীত অন্য কিছুই নির্ধারণ করে না। সুতরাং, গেটের ঠিক বাইরে, ইন্টারফেস হওয়ার মূল উদ্দেশ্যটিতে চিহ্নিতকারী ইন্টারফেস ব্যর্থ।