ইন্টারফেস বিভাজন নীতি: ইন্টারফেসের উল্লেখযোগ্য ওভারল্যাপ থাকলে কী করবেন?


9

থেকে পিয়ারসন নিউ আন্তর্জাতিক সংস্করণ: এজাইল সফটওয়ার ডেভেলপমেন্ট, নীতি, প্যাটার্নস ও পদ্ধতি :

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

চাচা বব, যখন ছোটখাটো ওভারল্যাপ হয় তখন মামলাটি নিয়ে কথা বলেন।

উল্লেখযোগ্য ওভারল্যাপ থাকলে আমাদের কী করা উচিত?

বলুন আমাদের আছে

Class UiInterface1;
Class UiInterface2;
Class UiInterface3;

Class UiIterface : public UiInterface1, public UiInterface2, public UiInterface3{};

UiInterface1এবং এর মধ্যে উল্লেখযোগ্য ওভারল্যাপ থাকলে আমাদের কী করা উচিত UiInterface2?


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

প্রশ্নটি আমার কাছে কিছুটা অস্পষ্ট, কেসের উপর নির্ভর করে অনেকগুলি বিভিন্ন সমাধান দিয়ে উত্তর দিতে পারে। ওভারল্যাপটি কেন বাড়ল?
আর্থার হাভলিসেক

উত্তর:


1

ঢালাই

এটি প্রায় অবশ্যই উদ্ধৃত বইয়ের পদ্ধতির সম্পূর্ণ স্পর্শকাতর হতে চলেছে, তবে আইএসপি-র সাথে আরও ভালভাবে মানিয়ে নেওয়ার একটি উপায় হল একটি QueryInterfaceসিওএম-শৈলীর পদ্ধতির সাহায্যে আপনার কোডবেসের একটি কেন্দ্রীয় অঞ্চলে একটি কাস্টিং মানসিকতা আলিঙ্গন করা ।

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

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

// Returns the absolute position of an entity as the sum
// of its own position and the position of its ancestors.
// `position` and `parenting` parameters should point to the 
// same object.
Vec2i abs_position(IPosition* position, IParenting* parenting)
{
     const Vec2i xy = position->xy();
     auto parent = parenting->parent();
     if (parent)
     {
         // If the entity has a parent, return the sum of the
         // parent position and the entity's local position.
         return xy + abs_position(dynamic_cast<IPosition*>(parent),
                                  dynamic_cast<IParenting*>(parent));
     }
     return xy;
}

... পাশাপাশি বেশ কুৎসিত / বিপজ্জনক, এই ইন্টারফেসগুলি ব্যবহার করে ক্লায়েন্ট কোডে ত্রুটি-প্রবণ কাস্টিংয়ের দায়িত্বটি আমরা ফাঁস করছি এবং / বা একই বস্তুকে একাধিক বার একইরকম একাধিক পরামিতিগুলিতে প্রেরণ করব বলে দেওয়া হচ্ছে ফাংশন। সুতরাং আমরা শেষ পর্যন্ত প্রায়ই যার উদ্বেগ consolidates আরো একটি মিশ্রিত ইন্টারফেস ডিজাইন অনুপস্থিত IParentingএবং IPositionমত এক জায়গায় IGuiElementযা তারপর লম্ব ইন্টারফেসগুলি যা একইভাবে জন্য আরো সদস্য ফাংশন করতে প্রলুব্ধ করা হবে উদ্বেগ ওভারল্যাপিং সমর্থ হয়ে মত বা কিছু একই "স্বনির্ভরতা" কারণ।

মিশ্রণ দায়িত্ব বনাম ingালাই

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

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

// Returns the absolute position of an entity as the sum
// of its own position and the position of its ancestors.
// `obj` should implement `IPosition` and optionally `IParenting`.
Vec2i abs_position(Object* obj)
{
     // `Object::query_interface` returns nullptr if the interface is
     // not provided by the entity. `Object` is an abstract base class
     // inherited by all entities using this interface query system.
     IPosition* position = obj->query_interface<IPosition>();
     assert(position && "obj does not implement IPosition!");
     const Vec2i xy = position->xy();

     IParenting* parenting = obj->query_interface<IParenting>();
     if (parenting && parenting->parent()->query_interface<IPosition>())
     {
         // If the entity implements IParenting and has a parent, 
         // return the sum of the parent position and the entity's 
         // local position.
         return xy + abs_position(parenting->parent());
     }
     return xy;
}

... অবশ্যই আশাকরি টাইপ-সেফ র‍্যাপারস এবং কাঁচা পয়েন্টারগুলির চেয়ে কিছু বেশি নিরাপদ করার জন্য আপনি কেন্দ্রীয়ভাবে তৈরি করতে পারেন।

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

টেমপ্লেট

যদি টেম্পলেটগুলির কোনও সম্ভাবনা থাকে (আমাদের কাছে প্রয়োজনীয় সংকলন-সময় সম্পর্কিত তথ্য রয়েছে যা আমরা কোনও বস্তুর কাছে যাওয়ার সময় হারিয়ে না যায়, অর্থাত্) তবে আমরা কেবল এটি করতে পারি:

// Returns the absolute position of an entity as the sum
// of its own position and the position of its ancestors.
// `obj` should have `position` and `parent` methods.
template <class Entity>
Vec2i abs_position(Entity& obj)
{
     const Vec2i xy = obj.xy();
     if (obj.parent())
     {
         // If the entity has a parent, return the sum of the parent 
         // position and the entity's local position.
         return xy + abs_position(obj.parent());
     }
     return xy;
}

... অবশ্যই এই জাতীয় ক্ষেত্রে, parentপদ্ধতিটি একই Entityধরণের ফিরে আসতে হবে , এক্ষেত্রে আমরা সম্ভবত সরাসরি সরাসরি ইন্টারফেসগুলি এড়াতে চাই (যেহেতু তারা প্রায়শই বেস পয়েন্টারগুলির সাথে কাজ করার পক্ষে টাইপ তথ্য হারাতে চাইবে)।

সত্তা-উপাদান উপাদান

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

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

ব্যবহারিক পদ্ধতির

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


11

কেস-কেস-কেস ভিত্তিতে আপনাকে করতে হবে এটি একটি রায় কল।

প্রথমত, মনে রাখবেন যে সলিড নীতিগুলি হ'ল ... নীতিগুলি। তারা নিয়ম না। এগুলি কোনও রূপোর বুলেট নয়। তারা কেবল নীতি। এটি তাদের গুরুত্ব থেকে দূরে সরে যাওয়ার নয়, আপনার সর্বদা তাদের অনুসরণ করার দিকে ঝুঁকতে হবে। তবে দ্বিতীয়টি তারা একটি স্তরের ব্যথার পরিচয় দেয়, আপনার প্রয়োজন না হওয়া পর্যন্ত আপনার সেগুলি খনন করা উচিত।

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

আইএসপিটির উদ্দেশ্যটি হ'ল "যদি আমার যে চুক্তিটির প্রয়োজন হয় তা যদি কেবল বিদ্যমান ইন্টারফেসের একটি উপসেট হয় তবে আমার পদ্ধতিতে পাস হওয়া ভবিষ্যতের কোনও ক্লাসে আমার বিদ্যমান ইন্টারফেসটি প্রয়োগ করা উচিত নয়" "

নিম্নলিখিত কোড বিবেচনা করুন:

public interface A
{
    void X();
    void Y();
}

public class Foo
{
     public void ConsumeX(A a)
     {
         a.X();
     }
}

এখন আমাদের একটি পরিস্থিতি রয়েছে যেখানে, যদি আমরা কনসুমেক্সে কোনও নতুন বস্তুটি পাস করতে চাই, তবে চুক্তিটি ফিট করার জন্য এটি এক্স () এবং ওয়াই () প্রয়োগ করতে হবে।

সুতরাং এখনই কি আমাদের পরবর্তী কোডটির মতো দেখতে কোডটি পরিবর্তন করা উচিত?

public interface A
{
    void X();
    void Y();
}

public interface B
{
    void X();
}

public class Foo
{
     public void ConsumeX(B b)
     {
         b.X();
     }
}

আইএসপি পরামর্শ দেয় আমাদের হওয়া উচিত, তাই আমাদের সেই সিদ্ধান্তের দিকে ঝুঁকানো উচিত। তবে, প্রসঙ্গ ছাড়া এটি নিশ্চিত হওয়া শক্ত। এটা কি সম্ভবত আমরা A এবং B প্রসারিত করব? সম্ভবত তারা স্বাধীনভাবে প্রসারিত হবে? সম্ভবত এটি সম্ভবত বি এর এমন কোনও পদ্ধতি প্রয়োগ করবে যেগুলির A প্রয়োজন হয় না? (যদি তা না হয় তবে আমরা বি থেকে একটি উত্স তৈরি করতে পারি)

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

কেন? কারণ পরে আপনার মন পরিবর্তন করা সহজ। আপনার যখন সেই নতুন বর্গের প্রয়োজন হবে, কেবল একটি নতুন ইন্টারফেস তৈরি করুন এবং আপনার পুরানো ক্লাসে উভয়ই প্রয়োগ করুন।


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