বহু পরামিতি বনাম একাধিক পদ্ধতি সহ একক পদ্ধতি যাতে ক্রম হিসাবে কল করা উচিত


16

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

আমি কি এমন কোনও প্রোগ্রামিং দৃষ্টান্ত ব্যবহার করতে পারি যা বাগগুলি হ্রাস করতে এবং কোডটি পড়তে সহজ করে তোলে?


3
সবচেয়ে বড় সমস্যাটি হ'ল তাদেরকে যথাযথভাবে কল না করা, এটি 'না জানা' যে আপনার (বা আরও স্পষ্টতই, ভবিষ্যতের প্রোগ্রামার) অবশ্যই তাদেরকে যথাযথভাবে কল করতে হবে। কোনও রক্ষণাবেক্ষণ প্রোগ্রামার বিশদ জানেন কিনা তা নিশ্চিত করুন (এটি আপনার প্রয়োজনীয়তা, নকশা এবং নির্দিষ্টকরণ কীভাবে ডকুমেন্ট করবেন তার উপর এটি নির্ভর করবে)। ইউনিট পরীক্ষা, মন্তব্যগুলি এবং সহায়তা ফাংশনগুলি ব্যবহার করুন যা সমস্ত পরামিতি নেয় এবং অন্যদের কল করে
mattnz

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

অ বিনিময় অপারেশন উদাহরণ: ইমেজ রূপান্তরের (ঘুর্ণন, স্কেলিং এবং ক্রপিং), ম্যাট্রিক্স multiplications, ইত্যাদি
rwong

হতে পারে আপনি তরকারী ব্যবহার করতে পারেন: এটি পদ্ধতিতে / ক্রিয়াকে ভুল ক্রমে প্রয়োগ করা অসম্ভব করে তোলে।
জর্জিও

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

উত্তর:


24

টেম্পোরাল কাপলিং থেকে সাবধান থাকুন । তবে এটি সর্বদা একটি সমস্যা নয় issue

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

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

জটিল কোডটি এভাবে দেখতে হবে:

public List<Widget> process(File file) throws IOException {
  try (BufferedReader in = new BufferedReader(new FileReader(file))) {
    List<Widget> widgets = new LinkedList<>();
    String line;
    while ((line = in.readLine()) != null) {
      if (isApplicable(line)) { // Filter blank lines, comments, etc.
        Ore o = preprocess(line);
        Ingot i = smelt(o);
        Alloy a = combine(i, new Nonmetal('C'));
        Widget w = smith(a);
        widgets.add(w);
      }
    }
    return widgets;
  }
}

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

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

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


2
ধন্যবাদ, আমি মনে করি সমস্যাটি মোকাবেলার জন্য এটি একটি ভাল উপায়। যদিও এটি বস্তুর সংখ্যা বৃদ্ধি করে (এবং এটি অপ্রয়োজনীয় বোধ করতে পারে), এটি সুশৃঙ্খলা বজায় রেখে অর্ডারকে বাধ্য করে।
টমস্রবটস

10

"ক্রমে অবশ্যই মৃত্যুদন্ড কার্যকর করা উচিত" যুক্তিটি মোট হওয়ায় আপনার সমস্ত কোড অবশ্যই সঠিক ক্রমে কার্যকর করা উচিত। সর্বোপরি, আপনি কোনও ফাইল লিখতে পারবেন না, তারপরে এটি খুলুন এবং এটি বন্ধ করুন, আপনি কি পারেন?

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


5

আমি একটি » ইমেজপ্রসেসর create (বা যে কোনও নামই আপনার প্রকল্পের জন্য উপযুক্ত) এবং একটি কনফিগারেশন অবজেক্ট প্রসেস কনফিগারেশন তৈরি করব , যা সমস্ত প্রয়োজনীয় পরামিতি ধারণ করে।

 ImageProcessor p = new ImageProcessor();

 ProcessConfiguration config = new processConfiguration().setTranslateX(100)
                                                         .setTranslateY(100)
                                                         .setRotationAngle(45);
 p.process(image, config);

চিত্রপ্রসেসরের অভ্যন্তরে আপনি পুরো মেথডের পিছনে পুরো প্রক্রিয়াটি আবদ্ধ করেন process()

public class ImageProcessor {

    public Image process(Image i, ProcessConfiguration c){
        Image processedImage=i.getCopy();
        shift(processedImage, c);
        rotate(processedImage, c);
        return processedImage;
    }

    private void rotate(Image i, ProcessConfiguration c) {
        //rotate
    }

    private void shift(Image i, ProcessConfiguration c) {
        //shift
    }
}

এই পদ্ধতি সঠিক অনুক্রমে রূপান্তরমূলক পদ্ধতির কল shift(), rotate()। প্রতিটি পদ্ধতি পাস হওয়া প্রক্রিয়া কনফিগারেশন থেকে উপযুক্ত পরামিতি পায় ।

public class ProcessConfiguration {

    private int translateX;

    private int rotationAngle;

    public int getRotationAngle() {
        return rotationAngle;
    }

    public ProcessConfiguration setRotationAngle(int rotationAngle){
        this.rotationAngle=rotationAngle;
        return this;
    }

    public int getTranslateY() {
        return translateY;
    }

    public ProcessConfiguration setTranslateY(int translateY) {
        this.translateY = translateY;
        return this;
    }

    public int getTranslateX() {
        return translateX;
    }

    public ProcessConfiguration setTranslateX(int translateX) {
        this.translateX = translateX;
        return this;
    }

    private int translateY;

}

আমি তরল ইন্টারফেস ব্যবহার করেছি

public ProcessConfiguration setRotationAngle(int rotationAngle){
    this.rotationAngle=rotationAngle;
    return this;
}

যা নিফটি আরম্ভের অনুমতি দেয় (উপরে দেখানো হয়েছে)।

সুস্পষ্ট সুবিধা, একটি বস্তুতে প্রয়োজনীয় পরামিতিগুলি encapsulating। আপনার পদ্ধতির স্বাক্ষরগুলি পঠনযোগ্য হয়ে উঠেছে:

private void shift(Image i, ProcessConfiguration c)

এটি কোনও চিত্র স্থানান্তর করার বিষয়ে এবং বিস্তারিত পরামিতিগুলি কোনওভাবে কনফিগার করা হয়েছে

বিকল্পভাবে, আপনি একটি প্রসেসিং পাইপলাইন তৈরি করতে পারেন :

public class ProcessingPipeLine {

    Image i;

    public ProcessingPipeLine(Image i){
        this.i=i;
    };

    public ProcessingPipeLine shift(Coordinates c){
        shiftImage(c);
        return this;
    }

    public ProcessingPipeLine rotate(int a){
        rotateImage(a);
        return this;
    }

    public Image getResultingImage(){
        return i;
    }

    private void rotateImage(int angle) {
        //shift
    }

    private void shiftImage(Coordinates c) {
        //shift
    }

}

কোনও পদ্ধতির কাছে কোনও মেথড কল এ processImageজাতীয় পাইপলাইনটি তাত্ক্ষণিকভাবে তৈরি করে এবং কী এবং কোন ক্রম সম্পন্ন হয় তা স্বচ্ছ করে তোলে: শিফট , ঘোরান

public Image processImage(Image i, ProcessConfiguration c){
    Image processedImage=i.getCopy();
    processedImage=new ProcessingPipeLine(processedImage)
            .shift(c.getCoordinates())
            .rotate(c.getRotationAngle())
            .getResultingImage();
    return processedImage;
}

3

আপনি কি একধরণের কারি ব্যবহারের কথা বিবেচনা করেছেন ? কল্পনা করুন যে আপনার একটি ক্লাস Processeeএবং একটি ক্লাস রয়েছে Processor:

class Processor
{
    private final Processee _processee;

    public Processor(Processee p)
    {
        _processee = p;
    }

    public void process(T1 a1, T2 a2)
    {
        // Process using a1
        // then process using a2
    }
}

এখন আপনি ক্লাসটি Processorদুটি ক্লাস দ্বারা প্রতিস্থাপন করতে পারেন Processor1এবং Processor2:

class Processor1
{
    private final Processee _processee;

    public Processor1(Processee p)
    {
        _processee = p;
    }

    public Processor2 process(T1 a1)
    {
        // Process using argument a1

        return new Processor2(_processee);
    }
}

class Processor2
{
    private final Processee _processee;

    public Processor(Processee p)
    {
        _processee = p;
    }

    public void process(T2 a2)
    {
        // Process using argument a2
    }
}

তারপরে আপনি সঠিক ক্রমে ক্রিয়াকলাপগুলি ব্যবহার করে কল করতে পারেন:

new Processor1(processee).process(a1).process(a2);

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


আমাদের প্রায় একই ধারণা ছিল;) পার্থক্যটি হ'ল, আপনার পাইপলাইন একটি কঠোর প্রক্রিয়াকরণ আদেশ প্রয়োগ করে।
টমাস জাঙ্ক

@ থমাস জাঙ্ক: যতদূর আমি বুঝতে পেরেছি, এটি একটি প্রয়োজনীয়তা: "সঠিক ফলাফল পাওয়ার জন্য এই পদ্ধতিগুলিকে খুব নির্দিষ্ট ক্রমে ডাকা দরকার"। কঠোর মৃত্যুদণ্ড কার্যকর করার আদেশটি ফাংশন রচনার মতো শোনাচ্ছে।
জর্জিও 10

আর আমিও করেছি But তবে, যদি প্রক্রিয়াজাতকরণের অর্ডার পরিবর্তন হয় তবে আপনাকে অনেকগুলি রিফ্যাক্টরিং করতে হবে;)
টমাস জাঙ্ক

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