পরিসংখ্যানগুলি অভ্যন্তরীণ বা বাহ্যিক পদ্ধতিতে থাকা উচিত?


17

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

এটি ধরে নেওয়া যুক্তিযুক্ত যে অঙ্কন () কেবলমাত্র এমন এক স্থান যেখানে অন্য ড্র পদ্ধতিগুলি ডাকা হত। এটি কেবল এখানে দেখানো তিনটি নয়, আরও অনেক আঁকো * পদ্ধতি এবং শো * বৈশিষ্ট্যগুলিতে প্রসারিত হওয়া দরকার।

public void Draw()
{
    if (ShowAxis)
    {
        DrawAxis();
    }

    if (ShowLegend)
    {
        DrawLegend();
    }

    if (ShowPoints && Points.Count > 0)
    {
        DrawPoints();
    }
}

private void DrawAxis()
{
    // Draw things.
}

private void DrawLegend()
{
    // Draw things.
}

private void DrawPoints()
{
    // Draw things.
}

অথবা

public void Draw()
{
    DrawAxis();
    DrawLegend();
    DrawPoints();
}

private void DrawAxis()
{
    if (!ShowAxis)
    {
        return;
    }

    // Draw things.
}

private void DrawLegend()
{
    if (!ShowLegend)
    {
        return;
    }

    // Draw things.
}

private void DrawPoints()
{
    if (!ShowPoints ||  Points.Count <= 0))
    {
        return;
    }

    // Draw things.
}

আরো অবগতির জন্য, আমি তাই এই জিজ্ঞাসা - stackoverflow.com/questions/2966216/...
Tesserex

1
যখনই আমি "এর আরও অনেকগুলি প্রসারিত হওয়া দরকার ..." এর মতো বাক্যটি দেখি তখনই আমি ততক্ষণে মনে করি "এটি একটি লুপ হওয়া উচিত"।
পল কসাই

উত্তর:


28

আমি মনে করি না এই ধরণের জিনিসটির জন্য আপনার কম্বল বিধি থাকতে পারে, এটি পরিস্থিতির উপর নির্ভর করে।

এই ক্ষেত্রে, আমি পদ্ধতির বাইরে যদি ক্লজ থাকার পরামর্শ দিচ্ছি কারণ অঙ্কন পদ্ধতির নামগুলি বোঝায় যে তারা কেবল কোনও বিশেষ শর্ত ছাড়াই জিনিসগুলি আঁকেন।

আপনি যদি দেখতে পান যে অনেক জায়গায় পদ্ধতিতে কল করার আগে আপনাকে চেক করতে হবে, তবে আপনি পদ্ধতিগুলির মধ্যে চেকটি স্থাপন করতে পারেন এবং এটি পুনরায় নামকরণ করে পরিষ্কার করতে পারেন যে এটি ঘটছে rif


7

আমি দ্বিতীয় বলি।

পদ্ধতিগুলির বিমূর্ততার একই স্তরের হওয়া উচিত।

দ্বিতীয় উদাহরণে, Draw()পদ্ধতির দায়বদ্ধতা হ'ল নিয়ন্ত্রকের মতো কাজ করা, প্রতিটি অঙ্কন পদ্ধতিকে কল করে। এই Draw()পদ্ধতির সমস্ত কোড বিমূর্ততার একই স্তরে। এই নির্দেশিকাটি পুনরায় ব্যবহারের দৃশ্যে কার্যকর হয়। উদাহরণস্বরূপ, আপনি যদি DrawPoints()অন্য কোন পাবলিক পদ্ধতিতে এই পদ্ধতিটি পুনরায় ব্যবহার করতে প্ররোচিত হন (আসুন এটি কল করুন Sketch()), আপনাকে প্রহরী ধারাটি পুনরাবৃত্তি করতে হবে না (যদি বিবৃতিটি আঁকতে হবে কিনা তা স্থির করে)।

প্রথম উদাহরণে, যদিও, Draw()পদ্ধতিটি প্রতিটি পৃথক পদ্ধতিতে কল করতে হবে কিনা তা নির্ধারণ করার জন্য এবং তারপরে সেই পদ্ধতিগুলি কল করার জন্য দায়বদ্ধ। Draw()কিছু নিম্ন-স্তরের পদ্ধতি রয়েছে যা কাজ করে, তবুও এটি অন্যান্য নিম্ন-স্তরের কাজগুলিকে অন্যান্য পদ্ধতির সাথে প্রতিনিধিত্ব করে এবং সুতরাং Draw()বিমূর্তির বিভিন্ন স্তরে কোড রয়েছে। পুনরায় ব্যবহার করার জন্য DrawPoints()Sketch(), আপনাকে পাহারা দফা প্রতিলিপি করতে হবে Sketch()হিসাবে ভাল।

এই ধারণাটি রবার্ট সি মার্টিনের "ক্লিন কোড" বইয়ে আলোচনা করা হয়েছে, যা আমি অত্যন্ত সুপারিশ করব।


1
ভাল জিনিস. অন্য উত্তরে তৈরি পয়েন্টটি সম্বোধন করতে, আমি এটির নাম পরিবর্তন করার পরামর্শ দেব DrawAxis()। অল। ইঙ্গিত যে তাদের ফাঁসি শর্তসাপেক্ষ হয়, হয়তো TryDrawAxis()। অন্যথায় আপনার Draw()আচরণটি নিশ্চিত করার জন্য আপনাকে পদ্ধতি থেকে প্রতিটি পৃথক সাবমেডুডে নেভিগেট করতে হবে ।
জোশ আর্ল

6

বিষয় সম্পর্কে আমার মতামতটি বেশ বিতর্কিত, তবে আমার সাথে সহ্য করুন, কারণ আমি বিশ্বাস করি যে প্রায় সবাই শেষ ফলাফলের সাথে একমত। আমি সেখানে পৌঁছানোর জন্য একটি ভিন্ন পন্থা আছে।

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

ওপিতে বলা হয়েছে:

এটি ধরে নেওয়া যুক্তিযুক্ত যে অঙ্কন () কেবলমাত্র এমন এক স্থান যেখানে অন্য ড্র পদ্ধতিগুলি ডাকা হত।

এটি আমাকে (মধ্যবর্তী) তৃতীয় বিকল্পের উল্লেখ না করে নিয়ে যায়। আমি 'কোড ব্লক' বা 'কোড অনুচ্ছেদ' তৈরি করি যা অন্যরা এর জন্য ফাংশন তৈরি করে।

public void Draw()
{
    // Draw axis.
    if (ShowAxis)
    {
        // Drawing code ...
    }

    // Draw legend.
    if (ShowLegend)
    {
        // Drawing code ...
    }

    // Draw points.
    if (ShowPoints && Points.Count > 0)
    {
        // Drawing code ...
    }
}

ওপি আরও বলেছে:

এটি কেবল এখানে দেখানো তিনটি নয়, আরও অনেক আঁকো * পদ্ধতি এবং শো * বৈশিষ্ট্যগুলিতে প্রসারিত হওয়া দরকার।

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

private void Initialize()
{               
    // Create axis.
    Axe xAxe = new Axe();
    Axe yAxe = new Axe();

    _drawObjects = new List<Drawable>
    {
        xAxe,
        yAxe,
        new Legend(),
        ...
    }
}

public void Draw()
{
    foreach ( Drawable d in _drawObjects )
    {
        d.Draw();
    }
}

অবশ্যই যুক্তিগুলি এখনও পাস করতে হবে এবং এরকম such


যদিও আমি ফাংশন হেল সম্পর্কে আপনার সাথে একমত নই, তবে আপনার সমাধানটি হ'ল সঠিক (আইএমএইচও) এবং এটি একটি যা ক্লিন কোড এবং এসআরপি-র যথাযথ প্রয়োগ থেকে উত্পন্ন হবে।
পল কসাই

4

আপনি যে ক্ষেত্রটি আঁকবেন কিনা তা নিয়ন্ত্রণ করে এমন ক্ষেত্রগুলি পরীক্ষা করছেন এমন ক্ষেত্রে এটির ভিতরে থাকা বোধগম্য Draw()। যখন এই সিদ্ধান্তটি আরও জটিল হয়ে ওঠে, তখন আমি পছন্দ করি (বা এটি বিভক্ত করুন) prefer যদি আপনার আরও নমনীয়তার প্রয়োজন হয় তবে আপনি সর্বদা এটি প্রসারিত করতে পারেন।

private void DrawPoints()
{
    if (ShouldDrawPoints())
    {
        DoDrawPoints();
    }
}

protected void ShouldDrawPoints()
{
    return ShowPoints && Points.Count > 0;
}

protected void DoDrawPoints()
{
    // Draw things.
}

লক্ষ্য করুন যে অতিরিক্ত পদ্ধতিগুলি সুরক্ষিত রয়েছে যা সাবক্লাসগুলি তাদের প্রয়োজন অনুযায়ী প্রসারিত করতে দেয়। এটি আপনাকে টেস্টিংয়ের জন্য অঙ্কন বা অন্য যে কোনও কারণ হতে পারে তা জোর করার অনুমতি দেয়।


এটি দুর্দান্ত: প্রতিটি জিনিস যা পুনরাবৃত্তি হয় তা তার নিজস্ব পদ্ধতিতে। আপনি এখন এমন একটি DrawPointsIfItShould()পদ্ধতিও যুক্ত করতে পারেন যা if(should){do}:) শর্টকাটগুলিকে :)
কনারাক

4

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

যদিও স্টিভেন জিউরিসের উত্তর প্রশ্নের দুটি সংস্করণের চেয়ে ভাল।


3

Show___প্রতিটি অংশের জন্য পৃথক সম্পত্তি থাকার পরিবর্তে আমি সম্ভবত একটি সামান্য ক্ষেত্র সংজ্ঞায়িত করব। এটি এটিকে কিছুটা সহজ করবে:

[Flags]
public enum DrawParts
{
    Axis = 1,
    Legend = 2,
    Points = 4,
    // More...
}

public class MyClass
{
    public void Draw() {
        if (VisibleParts.HasFlag(DrawPart.Axis))   DrawAxis();
        if (VisibleParts.HasFlag(DrawPart.Legend)) DrawLegend();
        if (VisibleParts.HasFlag(DrawPart.Points)) DrawPoints();
        // More...
    }

    public DrawParts VisibleParts { get; set; }
}

এর বাইরে, আমি বাইরের পদ্ধতিতে দৃশ্যমানতা যাচাই করার দিকে ঝুঁকছি, অভ্যন্তরীণ নয়। এটা সব পরে, DrawLegendএবং না DrawLegendIfShown। তবে এটি এক ধরণের উপর নির্ভর করে বাকি ক্লাসের উপর। যদি সেই জায়গাগুলি কল করে এমন আরও কিছু জায়গা রয়েছে DrawLegendএবং তাদের ShowLegendখুব চেক করা দরকার হয় তবে আমি সম্ভবত চেকটি সরিয়ে নিয়ে যেতে পারি DrawLegend


2

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


1

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

int do_something()
{
    sometype* x;
    if(!(x = sometype_new())) return -1;
    foo(x);
    bar(x);
    baz(x);
    return 0;
}

পরিবর্তে:

int do_something()
{
    sometype x* = sometype_new();
    if(ERROR == foo(x)) return -1;
    if(ERROR == bar(x)) return -1;
    if(ERROR == baz(x)) return -1;
    return 0;
}

এবং অবশ্যই এটি এমনকি আরও ন্যাশিয়র হয় যদি আপনি একক-প্রস্থান কার্যকর করেন, আপনার মেমরি মুক্ত করতে হবে, ইত্যাদি


0

এটি সমস্ত প্রসঙ্গে নির্ভর করে:

void someThing(var1, var2)
{
    // If input fails validation then return quickly.
    if (!isValid(var1) || !isValid(var2))
    {   return;
    }


    // Otherwise do what is logical and makes the code easy to read.
    if (doTaskConditionOK())
    {   doTask();
    }

    // Return early if it is logical
    // This is OK in C++ but not C like languages.
    // You have to be careful of cleanup in C like languages while RIAA will do
    // that auto-magically in C++. 
    if (allFinished)
    {   return;
    }

    doAlternativeIfNotFinished();

    // -- Alternative to the above for C
    if (!allFinished)
    {   
        doAlternativeIfNotFinished();
    }

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