ভাল অনুশীলনে DRY নীতি?


11

আমি আমার প্রোগ্রামিংয়ে DRY নীতিটি যথাসাধ্য অনুসরণ করার চেষ্টা করছি। সম্প্রতি আমি ওওপিতে নকশার ধরণগুলি শিখছি এবং আমি নিজেকে বেশ গুচ্ছ পুনরাবৃত্তি করে শেষ করেছি।

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

আমি নিজের জন্য যে সমস্যাটি তৈরি করেছিলাম তা হ'ল আমি যে টেবিলগুলি পেয়েছি তার জন্য একই জিনিসগুলি তৈরি করি। উদাহরণস্বরূপ, এগুলি হ'ল আমার কোনও টেবিল হ্যান্ডেল করা প্রয়োজন comments

class Comment extends Model {

    protected $id;
    protected $author;
    protected $text;
    protected $date;
}

class CommentFactory implements iFactory {

    public function createFrom(array $data) {
        return new Comment($data);
    }
}

class CommentGateway implements iGateway {

    protected $db;

    public function __construct(\Database $db) {
        $this->db = $db;
    }

    public function persist($data) {

        if(isset($data['id'])) {
            $sql = 'UPDATE comments SET author = ?, text = ?, date = ? WHERE id = ?';
            $this->db->prepare($sql)->execute($data['author'], $data['text'], $data['date'], $data['id']);
        } else {
            $sql = 'INSERT INTO comments (author, text, date) VALUES (?, ?, ?)';
            $this->db->prepare($sql)->execute($data['author'], $data['text'], $data['date']);
        }
    }

    public function retrieve($id) {

        $sql = 'SELECT * FROM comments WHERE id = ?';
        return $this->db->prepare($sql)->execute($id)->fetch();
    }

    public function delete($id) {

        $sql = 'DELETE FROM comments WHERE id = ?';
        return $this->db->prepare($sql)->execute($id)->fetch();
    }
}

class CommentRepository {

    protected $gateway;
    protected $factory;

    public function __construct(iFactory $f, iGateway $g) {
        $this->gateway = $g;
        $this->factory = $f;
    }

    public function get($id) {

        $data = $this->gateway->retrieve($id);
        return $this->factory->createFrom($data);
    }

    public function add(Comment $comment) {

        $data = $comment->toArray();
        return $this->gateway->persist($data);
    }
}

তারপরে আমার কন্ট্রোলারের মত দেখাচ্ছে

class Comment {

    public function view($id) {

        $gateway = new CommentGateway(Database::connection());
        $factory = new CommentFactory();
        $repo = new CommentRepository($factory, $gateway);

        return Response::view('comment/view', $repo->get($id));
    }
}

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

আমি এমন একটি সমাধানের কথা চিন্তা করলাম যেখানে ইন্টারফেসের পরিবর্তে আমার বিমূর্ত ক্লাস ছিল যা ক্লাসের নামটি ব্যবহার করে তাদের যে টেবিলটি ম্যানিপুলেট করতে হবে তা বের করে তবে এটি করার মতো সঠিক জিনিসটি মনে হয় না, যদি আমি কোনও ফাইল স্টোরেজে যাওয়ার সিদ্ধান্ত নিয়ে থাকি বা মেমক্যাচে যেখানে কোনও টেবিল নেই।

আমি কি এটি সঠিকভাবে পৌঁছাচ্ছি, বা আমার অন্যদিকে দেখার মতো অন্য দৃষ্টিভঙ্গি রয়েছে?


আপনি যখন একটি নতুন টেবিল তৈরি করেন, আপনি কি সর্বদা এটির সাথে ইন্টারঅ্যাক্ট করার জন্য এসকিউএল কোয়েরিগুলির একই সেট (বা একটি অত্যন্ত অনুরূপ সেট) ব্যবহার করেন? এছাড়াও, ফ্যাক্টরিটি বাস্তব প্রোগ্রামে কোনও অর্থবোধ যুক্তি সংযুক্ত করে?
Ixrec

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

আমি সম্ভবত সঠিক উত্তর দেওয়ার জন্য যোগ্য নই, তবে আমি এই ধারণাটি পেয়েছি যে 1) কারখানা এবং সংগ্রহশালা ক্লাসগুলি সত্যিই দরকারী কিছু করছে না, তাই আপনি তাদের খিঁচুনি করে এবং কেবল মন্তব্য এবং মন্তব্যগেটওয়ের সাথে সরাসরি কাজ করা ভাল be ২) সাধারণ অবিচ্ছিন্ন / পুনরুদ্ধার / মুছে ফেলা ফাংশনগুলি একক স্থানে কপি-পেস্ট করার পরিবর্তে রাখা সম্ভব হবে, সম্ভবত "ডিফল্ট বাস্তবায়নগুলি" (জাভা-র সংগ্রহগুলি কী কী পছন্দ করে) এর বিমূর্ত শ্রেণিতে
Ixrec

উত্তর:


12

আপনি যে সমস্যাটি সমাধান করছেন সেটি বেশ মৌলিক।

আমি একই সমস্যার অভিজ্ঞতা পেয়েছি যখন আমি এমন একটি সংস্থার হয়ে কাজ করেছি যা একটি বিশাল J2EE অ্যাপ্লিকেশন তৈরি করেছিল যা বেশ কয়েকটি শতাধিক ওয়েব পৃষ্ঠাগুলি এবং জাভা কোডের মিলিয়ন এবং দেড় লাইনের সমন্বয়ে তৈরি করে। এই কোডটি অধ্যবসায়ের জন্য ওআরএম (জেপিএ) ব্যবহার করেছে।

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

আপনি যে প্রোগ্রামিং ল্যাঙ্গুয়েজটি ব্যবহার করছেন তার স্তরে আপনার সমস্যার সমাধান হতে পারে না। নিদর্শনগুলি ব্যবহার করা ভাল তবে আপনি দেখতে পাচ্ছেন এটি কোডের পুনরাবৃত্তি ঘটায় (আকরিক আরও সঠিকভাবে বলা যায়: ডিজাইনের পুনরাবৃত্তি)।

আমি এটি যেভাবে দেখছি কেবলমাত্র 3 টি সমাধান রয়েছে। অনুশীলনে এই সমাধানগুলি একই হয়ে আসে।

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

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

সমাধান 3: কোড তৈরির কিছু ফর্ম ব্যবহার করে কোড এবং ডিজাইনের পুনরাবৃত্তিটি স্বয়ংক্রিয় করুন। হ্যান্ড-কোডিং পুনরাবৃত্ত কোড / ডিজাইন DRY নীতি লঙ্ঘন করার কারণে আপনার উদ্বেগ নিদর্শন এবং ডিজাইনের হ্যান্ড-কোড পুনরাবৃত্তিগুলি সম্পর্কে। আজকাল সেখানে খুব শক্তিশালী কোড জেনারেটরের ফ্রেমওয়ার্ক রয়েছে। এমন কি "ভাষার ওয়ার্কব্যাঞ্চগুলি" রয়েছে যা আপনাকে তাড়াতাড়ি অনুমতি দেয় (অর্ধ দিন যখন আপনার কোনও অভিজ্ঞতা নেই) আপনার নিজস্ব প্রোগ্রামিং ভাষা তৈরি করতে পারে এবং সেই ভাষাটি ব্যবহার করে কোনও কোড (পিএইচপি / জাভা / এসকিউএল - কোনও ভাবাবেগযুক্ত টেক্সট ফাইল) তৈরি করতে পারে। আমার এক্সটেক্সট নিয়ে অভিজ্ঞতা আছে তবে মেটাএডিট এবং এমপিএসও ঠিক আছে বলে মনে হচ্ছে। আমি আপনাকে দৃ strongly়ভাবে পরামর্শ দিচ্ছি যে এর মধ্যে একটি ভাষা ওয়ার্ক-বেঞ্চ পরীক্ষা করে দেখুন। আমার কাছে এটি ছিল আমার পেশাগত জীবনের সর্বাধিক মুক্ত করার অভিজ্ঞতা।

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


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

এটিই আমি এক্সটেক্সট এর প্রথম শুনেছি এবং এটি খুব শক্তিশালী দেখাচ্ছে। আমাকে এই সম্পর্কে সচেতন করার জন্য আপনাকে ধন্যবাদ!
ম্যাথু জেমস ব্রিগেস

8

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

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


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

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

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

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