আমার ক্লাসটি বইয়ের (শ্রেণীর ওওপি) শ্রেণীর শ্রেণিবিন্যাসের চেয়ে খারাপ কেন?


11

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

Lesson charge 20. Charge type: hourly rate. Lesson type: seminar.
Lesson charge 30. Charge type: fixed rate. Lesson type: lecture.

নিম্নলিখিত হিসাবে ইনপুট যখন হয়:

$lessons[] = new Lesson('hourly rate', 4, 'seminar');
$lessons[] = new Lesson('fixed rate', null, 'lecture');

আমি এটি লিখেছি:

class Lesson {
    private $chargeType;
    private $duration;
    private $lessonType;

    public function __construct($chargeType, $duration, $lessonType) {
        $this->chargeType = $chargeType;
        $this->duration = $duration;
        $this->lessonType = $lessonType;
    }

    public function getChargeType() {
        return $this->getChargeType;
    }

    public function getLessonType() {
        return $this->getLessonType;
    }

    public function cost() {
        if($this->chargeType == 'fixed rate') {
            return "30";
        } else {
            return $this->duration * 5;
        }
    }
}

$lessons[] = new Lesson('hourly rate', 4, 'seminar');
$lessons[] = new Lesson('fixed rate', null, 'lecture');

foreach($lessons as $lesson) {
    print "Lesson charge {$lesson->cost()}.";
    print " Charge type: {$lesson->getChargeType()}.";
    print " Lesson type: {$lesson->getLessonType()}.";
    print "<br />";
}

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

  • কোড সদৃশ
  • যে শ্রেণীটি তার প্রসঙ্গে খুব বেশি জানত
  • সবজান্তা - ক্লাস অনেক কিছু করার চেষ্টা
  • শর্তাধীন বিবৃতি

আমি দেখতে পাচ্ছি একমাত্র সমস্যা শর্তসাপেক্ষ বিবৃতি, এবং তাও একটি অস্পষ্ট পদ্ধতিতে - তবে এটি কেন রিফ্যাক্টর? ভবিষ্যতে এমন কোন সমস্যা দেখা দিতে পারে যা আমি আগেই ভাবিনি?

আপডেট : আমি উল্লেখ করতে ভুলে গেছি - এটি সমাধান হিসাবে লেখক প্রদত্ত শ্রেণিবদ্ধ কাঠামো - কৌশলটির ধরণ :

কৌশল প্যাটার্ন


29
পিএইচপি বই থেকে অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং শিখবেন না।
জিওরজিওসিরোনি

4
@ জিওরজিওসিরোনি আমি ভাষা মূল্যায়ন ছেড়ে দিয়েছি। আমি প্রতিদিনের ভিত্তিতে পিএইচপি ব্যবহার করি এবং সুতরাং এটিতে নতুন ধারণাটি শিখতে আমার পক্ষে সবচেয়ে দ্রুত। এমন লোকেরা সবসময় থাকে যারা একটি ভাষা ঘৃণা করে (জাভা: slidesha.re/91C4pX ) - স্বীকার করেছেন যে পিএইচপি বিচ্ছিন্ন করার চেয়ে জাভা বিদ্বেষীদের সন্ধান করা আরও কঠিন, তবে এখনও। পিএইচপি এর ওওতে সমস্যা হতে পারে তবে জাভা বাক্য গঠন, "জাভা উপায়" এবং ওওপি শিখতে এই মুহুর্তের জন্য আমি সময়টি ছাড়তে পারি না। এছাড়াও ডেস্কটপ প্রোগ্রামিং আমার কাছে এলিয়েন। আমি একজন সম্পূর্ণ ওয়েব ব্যক্তি তবে আপনি জেএসপিতে যাওয়ার আগে আপনার ডেস্কটপ জাভা জানা উচিত (কোনও উদ্ধৃতি দেওয়া হয়নি, আমি কি ভুল?)
আদিত্য এমপি

স্ট্রিংয়ের পরিবর্তে "স্থির হার" / "প্রতি ঘন্টা" এবং "সেমিনার" / "বক্তৃতা" এর জন্য ধ্রুবক ব্যবহার করুন।
টম মার্থেনাল

উত্তর:


19

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

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

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


3
উত্তরাধিকারের চেয়ে কার্যকরী এক্সটেনশান ব্যবহার করা এক বিস্তৃত ধারণা।
ডেডএমজি

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

কীভাবে সমস্যাটির কাছে যাওয়ার সর্বোত্তম উপায় ? নিকৃষ্ট সমাধান শেখানোর কোনও অর্থ নেই কারণ এটি ওও।
ডেডএমজি

16

আমি অনুমান করি যে বইটি শিক্ষাদানের লক্ষ্য কী তা এই জাতীয় জিনিস এড়ানো:

public function cost() {
    if($this->chargeType == 'fixed rate') {
        return "30";
    } else {
        return $this->duration * 5;
    }
}

বইটির আমার ব্যাখ্যাটি হল আপনার তিনটি শ্রেণি হওয়া উচিত:

  • AbstractLesson
  • HourlyRateLesson
  • FixedRateLesson

তারপরে আপনার costউভয় সাবক্লাসে ফাংশনটি পুনরায় প্রতিস্থাপন করা উচিত ।

আমার ব্যক্তিগত মতামত

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

  • 1 এর পরিবর্তে 3 ক্লাস
  • 0 এর পরিবর্তে 1 উত্তরাধিকারের স্তর
  • শর্তাধীন বিবৃতি একই সংখ্যা

এটি কোনও অতিরিক্ত সুবিধা ছাড়া আরও জটিলতা।


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

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

+1 দুর্দান্ত পুঙ্খানুপুঙ্খভাবে। "কোনও অতিরিক্ত সুবিধা ছাড়া এটি আরও জটিলতা" মন্তব্যটি সঠিকভাবে প্রোগ্রামিংয়ে 'সুযোগ ব্যয়' ধারণাটি চিত্রিত করে। তত্ত্ব! = ব্যবহারিকতা।
ইভান প্লেস

7

বইয়ের উদাহরণটি বেশ আশ্চর্যজনক। আপনার প্রশ্ন থেকে, মূল বিবৃতিটি হ'ল:

লক্ষ্যটি পাঠের প্রকার (বক্তৃতা বা সেমিনার) আউটপুট করা এবং পাঠের জন্য চার্জগুলি একটি ঘন্টা বা স্থির মূল্যের পাঠের উপর নির্ভর করে output

যা, ওওপি-র একটি অধ্যায়ের প্রসঙ্গে, এর অর্থ হ'ল লেখক সম্ভবত আপনার নিম্নলিখিত কাঠামোটি রাখতে চান:

+ abstract Lesson
    - Lecture inherits Lesson
    - Seminar inherits Lesson

+ abstract Charge
    - HourlyCharge inherits Charge
    - FixedCharge inherits Charge

তবে তারপরে আপনি যে ইনপুটটি উদ্ধৃত করেছেন তা আসে:

$lessons[] = new Lesson('hourly rate', 4, 'seminar');
$lessons[] = new Lesson('fixed rate', null, 'lecture');

উদাহরণস্বরূপ এমন কিছু যা স্ট্রলি টাইপড কোড বলা হয় , এবং যা সত্য, এই প্রসঙ্গে যখন পাঠক ওওপি শেখার উদ্দেশ্যে থাকে তখন তা ভয়াবহ।

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

const string $HourlyRate = 'hourly rate';
const string $FixedRate = 'fixed rate';

// [...]

Charge $charge;
switch ($chargeType)
{
    case $HourlyRate:
        $charge = new HourlyCharge();
        break;

    case $FixedRate:
        $charge = new FixedCharge();
        break;

    default:
        throw new ParserException('The value of chargeType is unexpected.');
}

// Imagine the similar code for lecture/seminar, and the similar code for both on output.

"সাইনপোস্টগুলি" হিসাবে:

  • কোড সদৃশ

    আপনার কোডটির সদৃশ নেই। লেখক আপনার যে কোডটি লিখেছেন তা প্রত্যাশা করে।

  • ক্লাস হু তার প্রসঙ্গ সম্পর্কে খুব বেশি জানত

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

  • জ্যাক অফ অল ট্রেড - ক্লাস যা অনেক কিছুই করার চেষ্টা করে

    আবার, আপনি কেবল স্ট্রিংগুলি পার করছেন, এর চেয়ে বেশি কিছুই নয়।

  • শর্তাধীন বিবৃতি

    আপনার কোডে একটি শর্তাধীন বিবৃতি রয়েছে is এটি পাঠযোগ্য এবং বোধগম্য।


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

+ abstract Lesson
    - Lecture inherits Lesson
    - Seminar inherits Lesson

+ abstract Charge
    - HourlyCharge inherits Charge
    - FixedCharge inherits Charge

+ LessonFactory

+ ChargeFactory

+ Parser // Uses factories to transform the input into `Lesson`.

এই ক্ষেত্রে, আপনি নয়টি ক্লাস শেষ করবেন, যা একটি ওভার-আর্কিটেকচারের নিখুঁত উদাহরণ হবে ।

পরিবর্তে, আপনি বোঝার জন্য সহজ, পরিষ্কার কোড দিয়ে শেষ করেছেন, যা দশগুণ ছোট।


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

আমি চাই তাই এই উত্তর গ্রহণ করতে ভালোবাসি, কিন্তু ওহ, আমি কি করব আমি @ ian31 এর উত্তর :( মত!
আদিত্য এমপি

5

সবার আগে আপনি "ম্যাজিক নম্বরগুলি" 30 এবং 5 এর মতো ব্যয় () ফাংশনে আরও অর্থবহ ভেরিয়েবলে পরিবর্তন করতে পারেন :)

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

আর কেন আপনি ভুল ভাবছেন? এই শ্রেণিটি কি আপনার পক্ষে "যথেষ্ট ভাল" নয়? আপনি কিছু বইয়ের জন্য কেন চিন্তিত;)


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

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

@ অ্যাডটিয়ামনন তারপরে আপনার উত্তরটি "রিফ্যাক্টরিং পরে আসবে"। কোডটি সহজতর করার জন্য কেবল তখনই অন্যান্য ক্লাসগুলি যুক্ত করুন - সাধারণত, তৃতীয় অনুরূপ ব্যবহারের ক্ষেত্রে যখন আসে তখনই। সাইমন এর উত্তর দেখুন।
ইজকাটা

3

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


1
এটা মজার. আপনি একটি উদাহরণ দিয়ে কীভাবে তা ব্যাখ্যা করতে পারেন?
guillaume31

+1, আমি সম্মত, অতিরিক্ত ইঞ্জিনিয়ার / এত ছোট কার্যকারিতা জটিল করার কোনও কারণ নেই।
গ্র্যান্ডমাস্টারবি

@ আইয়ান 31: বিশেষভাবে কি করবেন?
ডেডএমজি

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