কীভাবে একজন যুক্তি কম রাখে এবং তৃতীয় পক্ষের নির্ভরতা আলাদা রাখে?


13

আমি একটি তৃতীয় পক্ষের লাইব্রেরি ব্যবহার করি। তারা আমাকে একটি পোজো পাস করেছে যা আমাদের উদ্দেশ্য এবং উদ্দেশ্যগুলির জন্য সম্ভবত এইভাবে প্রয়োগ করা হয়েছে:

public class OurData {
  private String foo;
  private String bar;
  private String baz;
  private String quux;
  // A lot more than this

  // IMPORTANT: NOTE THAT THIS IS A PACKAGE PRIVATE CONSTRUCTOR
  OurData(/* I don't know what they do */) {
    // some stuff
  }

  public String getFoo() {
    return foo;
  }

  // etc.
}

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

public class DataTypeOne implements DataInterface {
  private String foo;
  private int bar;
  private double baz;

  public DataTypeOne(String foo, int bar, double baz) {
    this.foo = foo;
    this.bar = bar;
    this.baz = baz;
  }
}

public class DataTypeTwo implements DataInterface {
  private String foo;
  private int bar;
  private double baz;

  public DataTypeOne(String foo, int bar, double baz, String quux) {
    this.foo = foo;
    this.bar = bar;
    this.baz = baz;
    this.quux = quux;
  }
}

এবং তারপরে এটি:

public class ThirdPartyAdapter {
  public static makeMyData(OurData data) {
    if(data.getQuux() == null) {
      return new DataTypeOne(
        data.getFoo(),
        Integer.parseInt(data.getBar()),
        Double.parseDouble(data.getBaz()),
      );
    } else {
      return new DataTypeTwo(
        data.getFoo(),
        Integer.parseInt(data.getBar()),
        Double.parseDouble(data.getBaz()),
        data.getQuux();
      );
  }
}

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

তিনটিরও বেশি আর্গুমেন্টের (পলিয়েডিক) খুব বিশেষ ন্যায্যতা প্রয়োজন - এবং তারপরে যাইহোক এটি ব্যবহার করা উচিত নয়।

আমি যে বিষয়গুলি বিবেচনা করেছি:

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

এই পরিস্থিতি কীভাবে পরিচালনা করা উচিত?


নোট করুন এটি একটি দুর্নীতিবিরোধী স্তর পরিস্থিতি নয়। তাদের এপিআই-তে কোনও সমস্যা নেই। সমস্যাগুলি হ'ল:

  • আমি আমার ডেটা স্ট্রাকচারগুলি চাই না import com.third.party.library.SomeDataStructure;
  • আমি আমার পরীক্ষার ক্ষেত্রে তাদের ডেটা স্ট্রাকচার তৈরি করতে পারি না
  • আমার বর্তমান সমাধানটির ফলাফল খুব উচ্চতর আর্গুমেন্টের গণনায়। আমি তাদের ডেটা স্ট্রাকচারে পাস না করেই যুক্তি গণনা কম রাখতে চাই।
  • যে প্রশ্ন হল " কি একটি দুর্নীতি দমন স্তর?"। আমার প্রশ্ন " এই পরিস্থিতিটি সমাধান করতে আমি কীভাবে কোনও প্যাটার্ন, কোনও প্যাটার্ন ব্যবহার করতে পারি?"

আমি কোডের জন্য জিজ্ঞাসা করছি না, হয় (অন্যথায় এই প্রশ্নটি এসও তে হবে), আমাকে কার্যকরভাবে কোড লিখতে সক্ষম করার জন্য যথেষ্ট উত্তর চেয়েছিলেন (যা এই প্রশ্নটি সরবরাহ করে না)।


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

ক্লিন কোড থেকে সম্পূর্ণ উক্তি:The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification — and then shouldn’t be used anyway.
লিলিয়ান্থল

11
কোনও প্যাটার্নে অন্ধ অনুসরণ বা প্রোগ্রামিং গাইডলাইন এর নিজস্ব অ্যান্টি-প্যাটার্ন
লিলিয়েনথাল

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

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

উত্তর:


10

বেশ কয়েকটি সূচনা পরামিতি থাকা অবস্থায় আমি যে কৌশলটি ব্যবহার করেছি তা হ'ল একটি প্রকার তৈরি করা যা কেবলমাত্র প্রাথমিককরণের জন্য পরামিতিগুলি ধারণ করে

public class DataTypeTwoParameters {
    public String foo;  // use getters/setters instead if it's appropriate
    public int bar;
    public double baz;
    public String quuz;
}

তারপরে ডেটা টাইপটুইয়ের জন্য কনস্ট্রাক্টর একটি ডেটা টাইপটুইপ্যারামিটার অবজেক্ট নেয় এবং ডেটা টাইপটাইউ এর মাধ্যমে তৈরি করা হয়:

DataTypeTwoParameters p = new DataTypeTwoParameters();
p.foo = "Hello";
p.bar = 4;
p.baz = 3;
p.quuz = "World";

DataTypeTwo dtt = new DataTypeTwo(p);

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


আকর্ষণীয় পদ্ধতির। আপনি কোথায় প্রাসঙ্গিক রাখবেন Integer.parseInt? সেটারে, নাকি পরামিতি ক্লাসের বাইরে?
durron597

5
প্যারামিটার ক্লাসের বাইরে। পরামিতিগুলির বর্গটি একটি "বোবা" অবজেক্ট হওয়া উচিত এবং প্রয়োজনীয় ইনপুট এবং তার প্রকারগুলি কী তা প্রকাশ করা ছাড়া আর কিছু করার চেষ্টা করা উচিত নয়। পার্সিং অন্যত্র সম্পন্ন করতে হবে, মত: p.bar = Integer.parseInt("4")
এরিক

7
একটি মত এই শব্দ প্যারামিটার অবজেক্ট প্যাটার্ন
মশা

9
... বা অ্যান্টি-প্যাটার্ন
তেলস্তিন

1
... অথবা আপনি কেবল নামকরণ DataTypeTwoParametersকরতে পারেন DataTypeTwo
ব্যবহারকারী 253751

14

আপনার এখানে সত্যিই দুটি পৃথক উদ্বেগ রয়েছে: একটি এপিআই মোড়ানো এবং যুক্তি গণনা কম রাখুন।

কোনও এপিআই মোড়ানোর সময়, ধারণাটি ইন্টারফেসটি এমনভাবে নকশা করা হয় যেন স্ক্র্যাচ থেকে প্রয়োজনীয়তা ব্যতীত অন্য কিছুই জেনে নেই। আপনি বলতে সেখানে কিছু তাদের এপিআই সঙ্গে ভুল একটি নম্বর তারপর একই শ্বাস তালিকায় তাদের API- এর সাথে কিছুই ভুল,: testability, constructability, এক বস্তু অনেকগুলি পরামিতি, ইত্যাদি এপিআই আপনি লিখতে চান আপনি ছিল। যদি এটির পরিবর্তে একাধিক বস্তুর প্রয়োজন হয় তবে এটি করুন do POJO তৈরি করা বস্তুগুলিতে যদি এটির এক স্তর উচ্চতর মোড়কের প্রয়োজন হয় তবে তা করুন।

তারপরে একবার আপনার কাঙ্ক্ষিত এপিআই হয়ে গেলে প্যারামিটার গণনা আর কোনও সমস্যা হতে পারে না। যদি এটি হয় তবে বিবেচনা করার মতো কয়েকটি সাধারণ নিদর্শন রয়েছে:

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

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

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

public class DataTypeTwo implements DataInterface {
  private OurData data;

  public DataTypeOne(OurData data) {
    this.data = data;
  }

   public String getFoo() {
    return data.getFoo();
  }

  public int getBar() {
    return Integer.parseInt(data.getBar());
  }
  ...
}

এই উত্তরের প্রথম অর্ধেক: দুর্দান্ত, খুব সহায়ক, +1। এই উত্তরের দ্বিতীয়ার্ধ: " OurDataঅবজেক্টের একটি রেফারেন্স স্টোর করে অন্তর্নিহিত এপিআইয়ের মধ্য দিয়ে যান " - নির্ভরতা নেই তা নিশ্চিত করার জন্য এটি অন্তত বেস ক্লাসে আমি এড়াতে চাইছি।
durron597

1
এজন্য আপনি কেবল আপনার প্রয়োগের একটিতে এটি করেন DataInterface। আপনি আপনার মক অবজেক্টগুলির জন্য অন্য একটি বাস্তবায়ন তৈরি করেন।
কার্ল বিলেফেল্ড 18

@ durron597: হ্যাঁ, তবে আপনি যদি ইতিমধ্যে বিরক্ত হন তবে কীভাবে সমস্যাটি সমাধান করবেন আপনি ইতিমধ্যে তা জানেন।
ডক ব্রাউন

1

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

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

আপনি যদি আপনার ক্ষেত্রগুলির জন্য সেটারগুলি প্রকাশ করতে এবং তাদের কল করতে না চান তবে আমি মনে করি যে একটি ভাল-সংজ্ঞায়িত এবং এনক্যাপসুলেটেড কারখানার ভিতরে একটি পলিয়েডিক কনস্ট্রাক্টরের সাথে লেগে থাকা ভাল।


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