ক্লিন কোড এবং হাইব্রিড অবজেক্টস এবং ফিচার হিংসা


10

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

হাইব্রিড

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

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

সম্প্রতি আমি আমার এক কর্মী বস্তুর কোডটির দিকে তাকিয়ে ছিলাম (যা দর্শকের প্যাটার্নটি বাস্তবায়নের জন্য ঘটে ) এটি দেখেছি:

@Override
public void visit(MarketTrade trade) {
    this.data.handleTrade(trade);
    updateRun(trade);
}

private void updateRun(MarketTrade newTrade) {
    if(this.data.getLastAggressor() != newTrade.getAggressor()) {
        this.data.setRunLength(0);
        this.data.setLastAggressor(newTrade.getAggressor());
    }
    this.data.setRunLength(this.data.getRunLength() + newTrade.getLots());
}

আমি তাত্ক্ষণিক নিজেকে বলেছিলাম "বৈশিষ্ট্য হিংসা! এই যুক্তিটি Dataক্লাসে হওয়া উচিত - বিশেষত handleTradeপদ্ধতিতে handleTradeএবং এবং সর্বদা একসাথে updateRunহওয়া উচিত "। তবে আমি ভেবেছিলাম "ডেটা ক্লাসটি কেবল একটি ডেটা স্ট্রাকচার, যদি আমি এটি করা শুরু করি, তবে এটি একটি হাইব্রিড অবজেক্ট আসবে!"public

কি ভাল এবং কেন? আপনি কীভাবে সিদ্ধান্ত নেবেন?


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

উত্তর:


9

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

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

এই লাইনটি অতিক্রম করা হয় যখন কোনও বস্তুর পাবলিক ইন্টারফেস আমাদের এনক্যাপসুলেশনটি ভেঙে দিতে দেয়: এমন কিছু ইন্টার্নাল রয়েছে যা আমরা সরাসরি অ্যাক্সেস করতে পারি, সুতরাং অবজেক্টটিকে একটি অবৈধ অবস্থায় নিয়ে আসে। আমার কাছে মনে হয় এর Dataরাষ্ট্র রয়েছে এবং এটি একটি অবৈধ অবস্থায় আনা যেতে পারে:

  • কোনও বাণিজ্য পরিচালনা করার পরে, শেষ আগ্রাসক আপডেট হতে পারে না।
  • কোনও নতুন বাণিজ্য না ঘটে এমনকি সর্বশেষ আগ্রাসক আপডেট করা যেতে পারে।
  • আগ্রাসী আপডেট হওয়া সত্ত্বেও রান দৈর্ঘ্যটি তার পুরানো মান ধরে রাখতে পারে।
  • প্রভৃতি

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

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

আমি সম্প্রতি এনক্যাপসুলেশন সম্পর্কে একটি উত্তর লিখেছি , যা এনক্যাপসুলেশন কী এবং আপনি কীভাবে এটি নিশ্চিত করতে পারবেন তার আরও গভীরতায় যায়।


5

এই ঘটনাটি handleTrade()এবং updateRun()সর্বদা একসাথে ঘটে (এবং দ্বিতীয় পদ্ধতিটি আসলে দর্শকের উপরে থাকে এবং ডেটা অবজেক্টে আরও কয়েকটি পদ্ধতি কল করে) অস্থায়ী সংযোগের গন্ধ পায় । এর অর্থ হ'ল আপনাকে অবশ্যই একটি নির্দিষ্ট ক্রমে পদ্ধতিগুলি কল করতে হবে এবং আমি অনুমান করব যে কলিং পদ্ধতিগুলি ক্রম ছাড়াই খুব খারাপ কিছু ভেঙে ফেলবে বা সর্বোত্তমভাবে অর্থবহ ফলাফল দিতে ব্যর্থ হবে। ভাল না.

সাধারণত নির্ভরশীলতার বাইরে থাকা নির্ভরযোগ্যতার সঠিক উপায় হ'ল প্রতিটি পদ্ধতির ফলাফল ফেরত দেওয়া যা পরবর্তী পদ্ধতিতে খাওয়ানো যায় বা সরাসরি কাজ করা যেতে পারে।

পুরানো কোড:

MyObject x = ...;
x.actionOne();
x.actionTwo();
String result = x.actionThree();

নতুন কোড:

MyObject x = ...;
OneResult r1 = x.actionOne();
TwoResult r2 = r1.actionTwo();
String result = r2.actionThree();

এর বিভিন্ন সুবিধা রয়েছে:

  • এটি পৃথক উদ্বেগকে পৃথক বস্তুগুলিতে ( এসআরপি ) স্থানান্তর করে ।
  • এটি অস্থায়ী সংযুক্তিকে সরিয়ে দেয়: পদ্ধতিগুলিকে ক্রম ছাড়াই কল করা অসম্ভব এবং পদ্ধতি স্বাক্ষরগুলি কীভাবে তাদের কল করতে হবে সে সম্পর্কে নিখুঁত দলিল সরবরাহ করে। আপনি কি ডকুমেন্টেশনের দিকে নজর রেখেছেন, আপনি যে জিনিসটি চান তা দেখেছেন এবং পিছনের দিকে কাজ করেছেন? আমি জেড অবজেক্টটি চাই, তবে আমার জেড পেতে একটি ওয়াই দরকার need একটি ওয়াই পেতে আমার এক্স দরকার A আহা! আমার একটি ডাব্লু রয়েছে, যা একটি এক্স পাওয়ার জন্য প্রয়োজন all এটি একসাথে চেইন করুন এবং আপনার ডব্লু এখন একটি জেড পেতে ব্যবহার করতে পারেন
  • এর মতো বিভাজনকারী বস্তুগুলি এগুলি অপরিবর্তনীয় করে তোলার সম্ভাবনা বেশি, যার এই প্রশ্নের ক্ষেত্রের বাইরে বহুবিধ সুবিধা রয়েছে। দ্রুত গ্রহণযোগ্যতা হ'ল অপরিবর্তনীয় বস্তুগুলি এমন কোডের দিকে পরিচালিত করে যা আরও নিরাপদ।

এই দুটি পদ্ধতির কলগুলির মধ্যে কোনও অস্থায়ী সংযোগ নেই। তাদের অর্ডার অদলবদল করুন এবং আচরণ পরিবর্তন হয় না।
durron597

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

এর দৃশ্যমানতা updateRunঅপ্রাসঙ্গিক, কী গুরুত্বপূর্ণ তা বাস্তবায়ন this.dataযা প্রশ্নটিতে উপস্থিত নেই এবং এটি হ'ল ভিজিটর অবজেক্ট দ্বারা বস্তুটি হেরফের করা হচ্ছে।

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

0

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

"দুর্ভাগ্যজনক হাইব্রিড ডেটা স্ট্রাকচার" উত্থাপিত হয় যদি আপনি শ্রেণি রাজ্যের সদস্য-পরিবর্তনশীল (বা তাদের গ্রাহক / সেটটার) জনসাধারণ হিসাবে প্রকাশিত না হন তবে সর্বজনীন করেন।

সুতরাং আমি ডেটা ডেটা অবজেক্ট এবং কর্মী অবজেক্টের জন্য পৃথক ক্লাস করার দরকার নেই।

আপনি রাষ্ট্র-সদস্য-ভেরিয়েবলগুলি অ-সর্বজনীন রাখতে সক্ষম হবেন (আপনার ডাটাবেস-স্তরটি জন-সদস্য-ভেরিয়েবলগুলি পরিচালনা করতে সক্ষম হবে)

ফিচার হিংসা এমন একটি শ্রেণি যা অন্য শ্রেণীর পদ্ধতিগুলি অতিরিক্তভাবে ব্যবহার করে। কোড_স্মেল দেখুন । পদ্ধতি এবং রাষ্ট্র সহ একটি শ্রেণি থাকলে এটি দূর হবে।

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