সদৃশ কোড সরানোর জন্য জটিলতা যুক্ত করা হচ্ছে


24

আমার বেশ কয়েকটি ক্লাস রয়েছে যা সমস্ত জেনেরিক বেস বর্গ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত। বেস ক্লাসে বিভিন্ন ধরণের অবজেক্টের সংগ্রহ রয়েছে T

প্রতিটি শিশু শ্রেণিকে অবজেক্টগুলির সংগ্রহ থেকে আন্তঃবিবাহিত মানগুলি গণনা করতে সক্ষম হওয়া প্রয়োজন, তবে যেহেতু শিশু শ্রেণিগুলি বিভিন্ন ধরণের ব্যবহার করে, গণনাটি এক শ্রেণিতে পৃথক পৃথক হয়ে যায়।

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

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

সম্পাদনা করুন:

আমি যে সর্বোত্তম সমাধানটি নিয়ে আসতে পারি তা হ'ল এরকম কিছু:

বেস শ্রেণি:

protected T GetInterpolated(int frame)
{
    var index = SortedFrames.BinarySearch(frame);
    if (index >= 0)
        return Data[index];

    index = ~index;

    if (index == 0)
        return Data[index];
    if (index >= Data.Count)
        return Data[Data.Count - 1];

    return GetInterpolatedItem(frame, Data[index - 1], Data[index]);
}

protected abstract T GetInterpolatedItem(int frame, T lower, T upper);

শিশু শ্রেণি এ:

public IGpsCoordinate GetInterpolatedCoord(int frame)
{
    ReadData();
    return GetInterpolated(frame);
}

protected override IGpsCoordinate GetInterpolatedItem(int frame, IGpsCoordinate lower, IGpsCoordinate upper)
{
    double ratio = GetInterpolationRatio(frame, lower.Frame, upper.Frame);

    var x = GetInterpolatedValue(lower.X, upper.X, ratio);
    var y = GetInterpolatedValue(lower.Y, upper.Y, ratio);
    var z = GetInterpolatedValue(lower.Z, upper.Z, ratio);

    return new GpsCoordinate(frame, x, y, z);
}

শিশু শ্রেণি বি:

public double GetMph(int frame)
{
    ReadData();
    return GetInterpolated(frame).MilesPerHour;
}

protected override ISpeed GetInterpolatedItem(int frame, ISpeed lower, ISpeed upper)
{
    var ratio = GetInterpolationRatio(frame, lower.Frame, upper.Frame);
    var mph = GetInterpolatedValue(lower.MilesPerHour, upper.MilesPerHour, ratio);
    return new Speed(frame, mph);
}

9
ডিআরওয়াই এবং কোড পুনরায় ব্যবহারের মতো ধারণাগুলির অত্যধিক মাইক্রো-প্রয়োগ অনেক বেশি পাপকে বাড়ে।
এফাই 2'12

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

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

1
প্রথমটি হ'ল এক্স, ওয়াই, জেডকে ট্রিপলেটটি একটি পজিশনের ধরণে সংগ্রহ করা এবং সেই ধরণের সাথে সদস্য বা সম্ভবত কোনও স্থিতিশীল পদ্ধতিতে ইন্টারপোলেশন যুক্ত করা: পজিশন ইন্টারপোলেট (পজিশন অন্য, অনুপাত)।
কেভিন ক্লাইন

উত্তর:


30

এক উপায়ে, আপনি আপনার নিজের প্রশ্নের উত্তরটি গত অনুচ্ছেদে সেই মন্তব্যে দিয়েছিলেন:

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

যখনই আপনি কিছু সমস্যা অনুধাবন করেন যা আপনার সমস্যার সমাধানের জন্য সত্যই ব্যবহারিক নয়, তখন এই অনুশীলনটিকে ধর্মীয়ভাবে ব্যবহার করার চেষ্টা করবেন না (এই শব্দটির জন্য নিন্দা শব্দটি এক ধরণের সতর্কবাণী)। সর্বাধিক চর্চা তাদের আছে whens এবং whys এবং এমনকি যদি তারা সব সম্ভব ক্ষেত্রে 99% আবরণ, যে 1% যেখানে আপনি একটি ভিন্ন পদ্ধতি প্রয়োজন হতে পারে এখনো আছে।

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

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

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


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

@ স্পিশ আকর্ষণীয় পয়েন্ট। কখনও সেভাবে সে সম্পর্কে ভাবেননি।
ফিল

17

শিশু ক্লাসে বিভিন্ন ধরণের ব্যবহার করা হয়, গণনাটি ক্লাস থেকে ক্লাসে খুব সামান্য থাকে।

প্রথম এবং সর্বাগ্রে বিষয় হ'ল: প্রথমটি পরিষ্কারভাবে চিহ্নিত করুন যে কোন অংশটি পরিবর্তন হচ্ছে এবং কোন অংশটি ক্লাসগুলির মধ্যে পরিবর্তন হচ্ছে না। এটি চিহ্নিত করার পরে আপনার সমস্যাটি সমাধান হয়ে যায়।

রি-ফ্যাক্টরিং শুরু করার আগে প্রথম অনুশীলন হিসাবে এটি করুন। এরপরে অন্য সব কিছু স্বয়ংক্রিয়ভাবে জায়গায় পড়ে যাবে।


2
ভাল করা. এটি কেবল বারবার ফাংশনটি খুব বড় হওয়ার সমস্যা হতে পারে।
কার্ল বিলেফেল্ট

8

আমি বিশ্বাস করি যে কোডের কয়েকটি লাইনেরও বেশি প্রায় সমস্ত পুনরাবৃত্তি কোনও না কোনও উপায়ে তৈরি করা যেতে পারে এবং প্রায় সর্বদা হওয়া উচিত।

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

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

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

আপনার কোডটির জন্য নির্দিষ্ট সুপারিশ দেওয়া অসম্ভব কারণ আপনি কোডটি পোস্ট করেননি বা আপনি কোন ভাষাটি ব্যবহার করছেন তাও নির্দেশ করেছেন indicated


লুয়া কোনও সংক্ষিপ্ত বিবরণ নয়।
ডেড জিএম

@ ডেড এমএমজি: উল্লেখ করা; সম্পাদনা করতে নির্দ্বিধায়। এজন্য আমরা আপনাকে সেই সমস্ত খ্যাতি দিয়েছি।
কেভিন ক্লিন 2

5

আপনি যখন বলছেন বেস ক্লাসটি একটি অ্যালগোরিদম সম্পাদন করতে হয়, তবে অ্যালগোরিদম প্রতিটি উপ শ্রেণীর জন্য পরিবর্তিত হয়, এটি টেমপ্লেট প্যাটার্নের জন্য নিখুঁত প্রার্থী বলে মনে হয় ।

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


4

প্রতিটি ক্লাসে আপনার "একটি জেনেরিক ইন্টারপোলেশন পদ্ধতি" এর মতো শব্দগুলি খুব বেশি করছে এবং এটি আরও ছোট পদ্ধতিতে তৈরি করা উচিত।

আপনার গণনা কতটা জটিল তা নির্ভর করে কেন গণনার প্রতিটি "টুকরা" এই জাতীয় ভার্চুয়াল পদ্ধতি হতে পারে না

Public Class Fraction
{
     public virtual Decimal GetNumerator(params?)
     public virtual Decimal GetDenominator(params?)
     //Some concrete method to actually compute GetNumerator / GetDenominator
}

এবং যখন গণনার যুক্তিতে আপনার "সামান্য প্রকরণ" তৈরি করা দরকার তখন পৃথক টুকরোগুলি ওভাররাইড করুন।

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


3

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

তবে আপনি এই জাতীয় নিন্দামূলক চিন্তাভাবনা থেকে সতর্ক হওয়াও বেশ সঠিক। আপনার বিকল্পগুলি এটিকে একা রেখে যাওয়ার সিদ্ধান্ত নেওয়ার আগে ভাবার চেষ্টা করুন।

উদাহরণস্বরূপ, বেস ক্লাসের চেয়ে সেই পুনরাবৃত্তি কোডটি কোনও ইউটিলিটি ক্লাস / পদ্ধতিতে রাখাই ভাল? উত্তরাধিকারের চেয়ে বেশি পছন্দ রচনা দেখুন ।


2

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

যদি আপনি এই প্রশ্নের যে কোনও একটিতে হ্যাঁ উত্তর দিতে পারেন তবে সম্ভাব্য সদৃশ কোডটি রেখে যাওয়ার জন্য আপনার একটি শক্তিশালী মামলা রয়েছে


0

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

এই ক্ষেত্রে, অ্যালগরিদমগুলিকে এক বিশাল আকারে রিফ্যাক্ট করা এটিকে আরও জটিল করে তুলবে, ভবিষ্যতের রক্ষণাবেক্ষণের পক্ষে এটি অত্যন্ত জটিল করে তুলবে। সুতরাং আপনি যদি সাধারণ জিনিস সাধারণভাবে ফ্যাক্ট করতে না পারেন তবে সাধারণ:

// this code is similar to class x function b

মন্তব্য যথেষ্ট হবে। সমস্যা সমাধান.


0

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

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

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