পৃথক বৈশিষ্ট্যগুলির পরিবর্তে পুরো ক্লাসগুলি প্যারামিটার হিসাবে গ্রহণের জন্য একটি ক্লাস ডিজাইন করা


30

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

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

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

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

ব্যবহারকারী কেবল একটি উদাহরণ। এটি আমাদের কোডে ব্যাপকভাবে অনুশীলিত হয়।

আমি কি ভেবে ভেবে ঠিক বলছি যে এটি উন্মুক্ত / বন্ধ নীতি লঙ্ঘন? কেবল বিদ্যমান ক্লাসগুলি পরিবর্তনের কাজ নয়, তাদেরকে প্রথম স্থানে স্থাপন করা যাতে ভবিষ্যতে ব্যাপক পরিবর্তনগুলির খুব সম্ভবত প্রয়োজন হয়?

আমরা যদি কেবলমাত্র Userঅবজেক্টে পাস করি তবে আমি যে ক্লাসের সাথে কাজ করছি তার মধ্যে আমি একটি ছোট পরিবর্তন আনতে পারি। যদি আমাকে কোনও প্যারামিটার যোগ করতে হয় তবে ক্লাসের রেফারেন্সে আমাকে কয়েক ডজন পরিবর্তন করতে হতে পারে।

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

বেসিক ডিফেন্সিভ প্রোগ্রামিং নীতিগুলির মতো কি অন্যান্য, নন-সলিড নীতিগুলি লঙ্ঘিত হচ্ছে?

আমার নির্মাতাকে এইরকম দেখতে হবে:

MyConstructor(GUID userid, String username)

অথবা এটা:

MyConstructor(User theUser)

পোস্ট সম্পাদনা:

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


11
@gnat: এটি অবশ্যই একটি সদৃশ নয়। সম্ভাব্য সদৃশটি কোনও অবৈধ শ্রেণিবদ্ধের গভীরে পৌঁছানোর জন্য পদ্ধতি শৃঙ্খলা সম্পর্কে about এই প্রশ্নটি এ সম্পর্কে মোটেই জিজ্ঞাসা করে না বলে মনে হয়।
গ্রেগ বার্গার্ড্ট

2
দ্বিতীয় ফর্মটি প্রায়শই ব্যবহৃত হয় যখন পরামিতিগুলির সংখ্যাটি অতিরঞ্জিত হয়ে যায়।
রবার্ট হার্ভে

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

9
"পার্স" শব্দটি আপনি যে প্রসঙ্গে ব্যবহার করছেন তাতে কোনও ধারণা নেই। আপনি কি পরিবর্তে "পাস" বলতে চাচ্ছেন?
কনরাড রুডলফ

5
সম্পর্কে কি Iমধ্যে SOLID? MyConstructorমূলত এখন বলে "আমার দরকার একটি Guidএবং একটি string"। সুতরাং কেন একটি ইন্টারফেস একটি Guidএবং একটি সরবরাহ করে না string, Userসেই ইন্টারফেসটি MyConstructorবাস্তবায়ন করে সেই ইন্টারফেসটি বাস্তবায়নের কোনও উদাহরণের উপর নির্ভর করে? এবং যদি MyConstructorপরিবর্তনের প্রয়োজন হয় তবে ইন্টারফেসটি পরিবর্তন করুন। - এটি সরবরাহকারীর পরিবর্তে গ্রাহকের সাথে "সম্পর্কিত" ইন্টারফেসের কথা চিন্তা করতে আমাকে ব্যাপকভাবে সহায়তা করেছে । সুতরাং ভাবেন " ভোক্তা হিসাবে আমার এমন কিছু প্রয়োজন যা এটি করে এবং সরবরাহকারী হিসাবে" পরিবর্তে " আমি এটি করতে পারি এবং এটি"।
করাক

উত্তর:


31

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

সাধারণ ডেটা ধরণগুলি পাস করা দুর্দান্ত, যতক্ষণ না তারা বোঝায় অন্য কিছু। এই উদাহরণ বিবেচনা করুন:

public class Foo
{
    public void Bar(int userId)
    {
        // ...
    }
}

এবং একটি উদাহরণ ব্যবহার:

var user = blogPostRepository.Find(32);
var foo = new Foo();

foo.Bar(user.Id);

আপনি ত্রুটি স্পট করতে পারেন? সংকলক পারে না। "ব্যবহারকারী আইডি" পাস করা হচ্ছে কেবল একটি পূর্ণসংখ্যা। আমরা ভেরিয়েবলটির নাম রাখি userতবে তার মানটি প্রাথমিক থেকে blogPostRepositoryবস্তু থেকে শুরু করি , এটি সম্ভবত BlogPostবস্তুগুলি নয়, বস্তুগুলি প্রত্যাবর্তন Userকরে - তবুও কোডটি সংকলিত হয় এবং আপনি একটি উইকিপিড রানটাইম ত্রুটির সাথে শেষ করেন।

এখন এই পরিবর্তিত উদাহরণ বিবেচনা করুন:

public class Foo
{
    public void Bar(User user)
    {
        // ...
    }
}

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

var user = blogPostRepository.Find(32);
var foo = new Foo();

foo.Bar(user);

এখন আমাদের একটি সংকলক ত্রুটি আছে। blogPostRepository.Findপদ্ধতি ফেরৎ BlogPostবস্তুর, যা আমরা চালাকি করে "ব্যবহারকারী" কল। তারপরে আমরা এই "ব্যবহারকারীকে" Barপদ্ধতিতে পাস করি এবং তাত্ক্ষণিকভাবে একটি সংকলক ত্রুটি পাই, কারণ আমরা BlogPostকোনও পদ্ধতি গ্রহণ করে না এমন একটি পদ্ধতিতে পাস করতে পারি না User

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

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


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

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

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

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

1
"তার জায়গায় চারদিকে একটি পয়েন্টার পাস করার সাথে কোনও অসুবিধা নেই।" বা একটি রেফারেন্স, আপনি যে পয়েন্টারে যেতে পারেন সেগুলি দিয়ে সমস্ত সমস্যা এড়াতে avoid
Yay295

17

আমি কি ভেবে ভেবে ঠিক বলছি যে এটি উন্মুক্ত / বন্ধ নীতি লঙ্ঘন?

না, এটি সেই নীতির লঙ্ঘন নয়। এই নীতিটি Userকোডটি ব্যবহার করে এমন অন্যান্য অংশগুলিকে প্রভাবিত করে এমন পদ্ধতিতে পরিবর্তন না করার সাথে সম্পর্কিত । আপনার পরিবর্তনগুলি Userযেমন লঙ্ঘন হতে পারে তবে এটি সম্পর্কিত নয়।

এই অনুশীলন দ্বারা অন্য কোন নীতি ভেঙে দেওয়া হয়? নির্ভরতা বিপর্যয় পেরে যায়?

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

বেসিক ডিফেন্সিভ প্রোগ্রামিং নীতিগুলির মতো কি অন্যান্য, নন-সলিড নীতিগুলি লঙ্ঘিত হচ্ছে?

না। এই পদ্ধতির কোডিংয়ের একটি সঠিক বৈধ উপায়। এটি এ জাতীয় নীতি লঙ্ঘন করছে না।

তবে নির্ভরতা বিপর্যয় কেবল একটি নীতি; এটি একটি অটুট আইন নয়। এবং খাঁটি ডিআই সিস্টেমে জটিলতা যুক্ত করতে পারে। আপনি যদি দেখতে পান যে কেবলমাত্র ব্যবহারকারীর মানগুলি পদ্ধতিতে বা ইনস্ট্রাক্টরের মধ্যে পুরো ব্যবহারকারীর প্রবেশের পরিবর্তে পদ্ধতিগুলিতে ইনজেক্ট করা সমস্যা তৈরি করে, তবে সেভাবে এটি করবেন না। এগুলি হ'ল নীতি এবং ব্যবহারিকতার মধ্যে ভারসাম্য অর্জন সম্পর্কে।

আপনার মন্তব্য ঠিকানা:

শৃঙ্খলার পাঁচটি স্তরে অযথা নতুন মানটিকে পার্স করার পরে সমস্যাগুলি রয়েছে এবং তারপরে বিদ্যমান সমস্ত পাঁচটি পদ্ধতির সমস্ত রেফারেন্সের পরিবর্তন করুন ...

এখানে সমস্যার একটি অংশ হ'ল "অযথা [পাস] ..." মন্তব্য অনুসারে আপনি এই পদ্ধতিটি পরিষ্কারভাবে পছন্দ করেন না। এবং এটি যথেষ্ট ন্যায্য; এখানে সঠিক উত্তর নেই। যদি আপনি এটি বোঝা লাগে তবে সেভাবে এটি করবেন না।

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

... তবে অবশ্যই সেই নীতিটি মেনে চলার পরিকল্পনা যতদূর সম্ভব তা সম্ভব ভবিষ্যতের পরিবর্তনের প্রয়োজনীয়তা হ্রাস করার কৌশলগুলি অন্তর্ভুক্ত করবে?

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

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


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

@ জিম্বো, আমি আপনার মন্তব্যটি চেষ্টা করার জন্য উত্তরটি আপডেট করেছি।
ডেভিড আরনো

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

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

@ জেমসেলিস-জোনস, নির্ভরতা ইনভারশন "জিজ্ঞাসা", "বলুন" থেকে নির্ভরতাগুলি ফ্লিপ করে। যদি আপনি কোনও Userউদাহরণে পাস করেন এবং তারপরে প্যারামিটারটি পাওয়ার জন্য সেই বিষয়টিকে জিজ্ঞাসা করেন, তবে আপনি কেবল আংশিকভাবে নির্ভরতাগুলি উল্টিয়ে দিচ্ছেন; এখনও কিছু জিজ্ঞাসা চলছে। সত্য নির্ভরতা বিপর্যয় 100% "বলুন, জিজ্ঞাসা করবেন না"। তবে এটি একটি জটিল মূল্যে আসে।
ডেভিড আরনো

10

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

কিন্তু যে ইন্টারফেস বিচ্ছিন্নতার নীতি এর afoul চালানোর পারে, যেহেতু আপনি বরাবর ক্ষণস্থায়ী যেতে পারে পথ ফাংশন চাহিদা চেয়ে অধিক বিবরণের তার কাজ।

সুতরাং, বেশিরভাগ জিনিসগুলির মতো - এটি নির্ভর করে

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

পুরো ব্যবহারকারীর ব্যবহার এটি ব্যবহার সম্পর্কে আরও পরিষ্কার করে এবং এর কলকারীদের সাথে আরও দৃ contract় চুক্তি করে। এটির পরিবর্তনের জন্য স্থিতিস্থাপকতা সরবরাহ করে যদি আপনি মনে করেন যে আরও বেশি ব্যবহারকারীর প্রয়োজন হবে।


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

5
@ ডকার্কিং, " আপনি যখন পাস করেন (ব্যবহারকারী ব্যবহারকারী) আপনি খুব ন্যূনতম তথ্য পাস করেন, একটি বস্তুর রেফারেন্স "। আপনি object বস্তুর সাথে সম্পর্কিত সর্বাধিক তথ্যটি পাস করুন: পুরো অবজেক্ট। " বলা পদ্ধতিটি সর্বদা ব্যবহারকারী.ফাইন্ড (ইউজারিড) কল করতে পারে ..."। একটি সুপরিকল্পিত সিস্টেমে, এটি সম্ভব হবে না কারণ প্রশ্নে পদ্ধতিতে অ্যাক্সেস থাকবে না User.find()। বস্তুত এমনকি করা উচিত নয় হতে একটি User.find। ব্যবহারকারীর সন্ধান করা কখনই এর দায়িত্ব হওয়া উচিত নয় User
ডেভিড আরনো

2
@dcorking - এনএইচ। আপনি যে রেফারেন্সটি ছোট বলে মনে করছেন তা প্রযুক্তিগত কাকতালীয় ঘটনা। আপনি পুরো Userফাংশনে সংযুক্ত করছেন । সম্ভবত এটি বোধগম্য হয়। তবে সম্ভবত ফাংশনটি কেবল ব্যবহারকারীর নাম সম্পর্কেই যত্নবান হওয়া উচিত - এবং ব্যবহারকারীর যোগদানের তারিখের মতো জিনিসগুলি পেরিয়ে যাওয়া বা ঠিকানাটি অনুপযুক্ত।
টেলাস্টিন

@ ডেভিড আর্নো সম্ভবত এটি ওপি-র স্পষ্ট উত্তরের জন্য মূল বিষয়। কার ব্যবহারকারীর সন্ধানের দায়িত্ব থাকা উচিত? শ্রেণি থেকে সন্ধানকারী / কারখানাকে আলাদা করার নকশার নীতিমালার কোনও নাম আছে কি?
dcorking

1
@ ডকার্কিং আমি বলব যে এটি একক দায়বদ্ধতার নীতিমালাটির অন্তর্ভুক্ত। ব্যবহারকারীরা কোথায় সংরক্ষিত রয়েছে এবং আইডি দিয়ে কীভাবে তাদের পুনরুদ্ধার করবেন তা পৃথক দায়িত্ব কUser ক্লাসের নয়। এই UserRepositoryজাতীয় জিনিসগুলির সাথে ডিল করে এমন কোনও বা অনুরূপ থাকতে পারে be
হাল্ক

3

এই নকশাটি প্যারামিটার অবজেক্ট প্যাটার্ন অনুসরণ করে । এটি পদ্ধতির স্বাক্ষরে অনেকগুলি পরামিতি থাকা থেকে উদ্ভূত সমস্যাগুলির সমাধান করে।

আমি কি ভেবে ভেবে ঠিক বলছি যে এটি উন্মুক্ত / বন্ধ নীতি লঙ্ঘন?

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

এই অনুশীলন দ্বারা অন্য কোন নীতি ভেঙে দেওয়া হয়?

এটা তোলে করতে ঘটে। সলাইড নীতিগুলির ভিত্তিতে আমাকে ব্যাখ্যা করতে দিন।

একক দায়িত্ব নীতি যদি এটা নকশা হিসাবে আপনি ব্যাখ্যা আছে (SRP) লঙ্ঘন করা যেতে পারে:

এই শ্রেণিটি ব্যবহারকারী, তাদের আইডি, নাম, প্রতিটি মডিউল অ্যাক্সেসের স্তর, টাইমজোন ইত্যাদি সম্পর্কিত সমস্ত তথ্য প্রকাশ করে

সমস্যাটি সমস্ত তথ্য নিয়ে । যদি Userবর্গ অনেক বৈশিষ্ট্য আছে, এটি একটি বিশাল হয়ে ডেটা ট্রান্সফার অবজেক্টে পরিণত হয় যা গ্রাসকারী শ্রেণীর দৃষ্টিকোণ থেকে অসম্পর্কিত তথ্য পরিবহন করে। উদাহরণ: গ্রাসকারী শ্রেণীর দৃষ্টিকোণ থেকে UserAuthenticationসম্পত্তি User.Idএবং User.Nameপ্রাসঙ্গিক, তবে তা নয় User.Timezone

ইন্টারফেস পৃথকীকরণ নীতি (আইএসপি) একটি similiar যুক্তি দিয়ে লঙ্ঘন কিন্তু অন্য দৃষ্টিকোণ যোগ করা হয়। উদাহরণ: ধরুন একটি গ্রাহক শ্রেণিUserManagement জন্য সম্পত্তি User.Nameবিভক্ত হওয়া প্রয়োজন User.LastNameএবং এর User.FirstNameজন্য শ্রেণিটিও UserAuthenticationপরিবর্তন করতে হবে।

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

class User : IUserAuthenticationInfo, IUserLocationInfo { ... }

প্রতিটি ইন্টারফেসে Userগ্রাহক শ্রেণীর ক্রিয়াকলাপটি পুরোপুরি পূরণের জন্য প্রয়োজনীয় শ্রেণীর সম্পর্কিত বৈশিষ্ট্যের একটি উপসেট প্রকাশ করা উচিত । বৈশিষ্ট্যগুলির গুচ্ছ অনুসন্ধান করুন। ইন্টারফেস পুনরায় ব্যবহার করার চেষ্টা করুন। গ্রাহক ক্ষেত্রে পরিবর্তে UserAuthenticationব্যবহার IUserAuthenticationInfoকরুন User। তারপরে যদি সম্ভব Userহয় তবে "স্টেনসিল" হিসাবে ইন্টারফেস ব্যবহার করে একাধিক কংক্রিটের ক্লাসে ক্লাস বিভাজন করুন ।


1
একবার ব্যবহারকারী জটিল হয়ে উঠলে, সম্ভাব্য সাবিনটারফেসগুলি সংযুক্ত করে বিস্ফোরণ ঘটতে পারে উদাহরণস্বরূপ, যদি ব্যবহারকারীর মাত্র 3 টি বৈশিষ্ট্য থাকে তবে সেখানে 7 টি সম্ভাব্য সংমিশ্রণ রয়েছে। আপনার প্রস্তাবটি দুর্দান্ত মনে হলেও অকার্যকর।
user949300

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

2

আমার নিজস্ব কোডে এই সমস্যাটির সাথে মোকাবিলা করার সময়, আমি সিদ্ধান্ত নিয়েছি যে মৌলিক মডেল শ্রেণি / অবজেক্টই এর উত্তর।

একটি সাধারণ উদাহরণ হ'ল সংগ্রহস্থল প্যাটার্ন। প্রায়শই সংগ্রহস্থলের মাধ্যমে ডাটাবেস অনুসন্ধান করার সময়, সংগ্রহস্থলের অনেকগুলি পদ্ধতি একই পরামিতিগুলিতে লাগে take

ভাণ্ডারগুলির জন্য আমার নিয়মগুলির থাম্বটি হ'ল:

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

  • যেখানে কোনও পদ্ধতিতে 2 টিরও বেশি পরামিতি লাগে, পরামিতিগুলিকে একটি মডেল অবজেক্ট হিসাবে একত্রে গ্রুপ করা উচিত।

  • মডেলগুলি একটি সাধারণ বেস থেকে উত্তরাধিকারী হতে পারে, তবে কেবল যখন এটি সত্যিকার অর্থে বোধ করা হয় (সাধারণত উত্তরাধিকারের কথা মনে রেখে শুরু করার চেয়ে পরে রিফ্যাক্টর করা ভাল)।


প্রকল্পটি কিছুটা জটিল হওয়া অবধি অন্য স্তর / অঞ্চলগুলির মডেলগুলি ব্যবহার করার সমস্যাগুলি স্পষ্ট হয়ে ওঠে না। তবেই আপনি কম কোডটি বেশি কাজ বা আরও জটিলতা তৈরি করে খুঁজে পান।

এবং হ্যাঁ, পৃথক স্তর / উদ্দেশ্য (যেমন। ভিওমোডেলস বনাম পোকো) পরিবেশন করে এমন দুটি বৈশিষ্ট্যযুক্ত আলাদা আলাদা মডেল থাকা সম্পূর্ণ জরিমানা।


2

আসুন সলাইডের স্বতন্ত্র দিকগুলি যাচাই করা যাক:

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

একটি জিনিস যা ডিজাইনের প্রবৃত্তিগুলিকে বিভ্রান্ত করে তোলে তা হ'ল শ্রেণিটি মূলত বিশ্বব্যাপী অবজেক্টগুলির জন্য এবং মূলত কেবলমাত্র পঠনযোগ্য। এমন পরিস্থিতিতে, বিমূর্ততা লঙ্ঘন করা খুব বেশি ক্ষতি করে না: সংশোধিত হয় না এমন ডেটা পড়া কেবল একটি দুর্বল দম্পতি তৈরি করে; এটি একটি বিশাল স্তূপ হয়ে গেলেই ব্যথাটি লক্ষণীয় হয়ে ওঠে।
ডিজাইনের প্রবৃত্তিগুলি পুনরুদ্ধার করতে, কেবল ধরে নিন যে অবজেক্টটি খুব গ্লোবাল নয়। Userকোনও বিষয়টির কোনও সময় পরিবর্তন করতে পারলে কোন ফাংশনটির প্রয়োজন হবে? অবজেক্টের কোন উপাদানগুলি সম্ভবত একসাথে রূপান্তরিত হবে? এগুলি এর বাইরে বিভক্ত করা যেতে পারে User, কোনও রেফারেন্সযুক্ত সাবোবজেক্ট হিসাবে বা কোনও ইন্টারফেস হিসাবে যা সম্পর্কিত ক্ষেত্রগুলির কেবল একটি "স্লাইস" প্রকাশ করে তা গুরুত্বপূর্ণ নয় isn't

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

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

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

অন্য কথায়: আপনি যদি নিজের ডোমেনটি সত্যিই জানেন না এবং মডিউলটি কী কী দিকগুলির সাথে সম্পর্কিত তা সম্পর্কে একটি পরিষ্কার ধারণা Userনা থাকলে প্রোগ্রামটির কাঠামোর উন্নতি করা সত্যিকার অর্থেই উপযুক্ত নয়।


1

এটি একটি সত্যিই আকর্ষণীয় প্রশ্ন। এটা নির্ভর করে।

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

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

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


1

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

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

interface IIdentifieable
{
    Guid ID { get; }
}

অথবা

interface INameable
{
    string Name { get; }
}

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


1

এখানে সময়ে সময়ে আমি এমন কিছু মুখোমুখি হয়েছি:

  • একটি পদ্ধতি প্রকারের User(বা Productযা কিছু) একটি যুক্তি নেয় যা প্রচুর বৈশিষ্ট্যযুক্ত রয়েছে, যদিও পদ্ধতিটি কেবল তাদের কয়েকটি ব্যবহার করে।
  • কোনও কারণে, কোডটির কিছু অংশে সেই পদ্ধতিটি কল করতে হবে যদিও এর সম্পূর্ণ জনবহুল না রয়েছে User অবজেক্ট নেই। এটি একটি দৃষ্টান্ত তৈরি করে এবং পদ্ধতির আসলে প্রয়োজনীয় বৈশিষ্ট্যগুলির সূচনা করে।
  • এটি অনেক সময় ঘটে।
  • কিছুক্ষণ পরে, আপনি যখন কোনও পদ্ধতির সাথে Userযুক্তিযুক্ত মুখোমুখি হন, তখন আপনি নিজেকে সেই পদ্ধতিতে কলগুলি খুঁজে Userপেয়েছিলেন কোথা থেকে আসে তা খুঁজে পেতে যাতে কোন বৈশিষ্ট্যটি জনবহুল হয় তা আপনি জানতে পারেন। এটি কোনও ইমেল ঠিকানা সহ একজন "প্রকৃত" ব্যবহারকারী, বা এটি কেবলমাত্র একটি ব্যবহারকারী আইডি এবং কিছু অনুমতি পাস করার জন্য তৈরি করা হয়েছিল?

যদি আপনি Userএকটি কয়েকটি তৈরি করেন এবং কেবল কয়েকটি বৈশিষ্ট্য তৈরি করেন কারণ পদ্ধতির প্রয়োজনগুলি সেগুলি হ'ল, তবে কলার প্রকৃতপক্ষে পদ্ধতির অভ্যন্তরীণ কার্যকারিতা সম্পর্কে আরও বেশি জানেন it

এমনকি খারাপ, যখন আপনি আছে একটি দৃষ্টান্তUser , আপনি কি জানেন এটা যেখানে তাই থেকে এসেছিলেন আপনাকে জানাতে চাই যে যা বৈশিষ্ট্য জনবহুল হয় আছে। আপনি এটি জানতে চান না।

সময়ের সাথে সাথে, যখন বিকাশকারীরা দেখেন User পদ্ধতির আর্গুমেন্টগুলির জন্য ধারক হিসাবে ব্যবহৃত , তারা একক-ব্যবহারের পরিস্থিতিতে এটিতে বৈশিষ্ট্য যুক্ত করা শুরু করতে পারে। এখন এটি কুৎসিত হয়ে উঠছে, কারণ শ্রেণিটি এমন বৈশিষ্ট্যগুলির সাথে বিশৃঙ্খল হয়ে উঠছে যা প্রায় সর্বদা নাল বা ডিফল্ট হবে।

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

যেখানে সম্ভব, কেবল আপনার যা পাস করতে হবে তা পাশ করে পরবর্তী বিকাশকারীকে সঠিক উদাহরণ স্থাপন করুন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.