শ্রেণি প্রয়োগের অন্যান্য প্রোগ্রামারদের কীভাবে সতর্ক করা যায়


96

আমি এমন ক্লাস লিখছি যা "অবশ্যই একটি নির্দিষ্ট উপায়ে ব্যবহার করা উচিত" (আমি অনুমান করি সমস্ত শ্রেণি অবশ্যই আবশ্যক ...)।

উদাহরণস্বরূপ, আমি fooManagerক্লাস তৈরি করি , যার জন্য একটি কল প্রয়োজন, বলুন Initialize(string,string)। এবং, উদাহরণটিকে আরও কিছুটা এগিয়ে নিয়ে যাওয়ার জন্য, আমরা এর ThisHappenedক্রিয়াটি না শুনলে শ্রেণিটি অকেজো হবে ।

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

তবে আমি এটি পছন্দ করি না। আমি আদর্শভাবে যা চাই তা হ'ল পদ্ধতিটি না বললে কোডটি সংকলন না করা; আমি অনুমান করছি যে এটি সম্ভব নয়। বা এমন কিছু যা অবিলম্বে দৃশ্যমান এবং স্পষ্ট হবে।

আমি এখানে উপস্থিত বর্তমান পদ্ধতির দ্বারা নিজেকে বিরক্ত বোধ করি, যা নিম্নলিখিত:

ক্লাসে একটি বেসরকারী বুলিয়ান মান যুক্ত করুন, এবং ক্লাসটি আরম্ভ করা হয়েছে কিনা তা সর্বত্র প্রয়োজনীয় পরীক্ষা করুন; যদি তা না হয় তবে আমি একটি ব্যতিক্রম ছুঁড়ে বলব "ক্লাসটি আরম্ভ করা হয়নি, আপনি কি নিশ্চিত যে আপনি কল করছেন .Initialize(string,string)?"

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

এছাড়াও, কখনও কখনও Initiliazeকল করার চেয়ে আরও বেশি পদ্ধতি থাকলে এটি কখনও কখনও আরও বেশি কোড হয় । আমি আমার ক্লাসগুলিকে খুব বেশি পাবলিক পদ্ধতি / ক্রিয়া না রাখার চেষ্টা করি, তবে এটি কেবল যুক্তিসঙ্গত রেখে সমস্যার সমাধান করছে না keeping

আমি এখানে যা খুঁজছি তা হ'ল:

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

এটিকে সহজভাবে বলতে, আমি যখন ক্লাসটি পরে বা অন্য কারও দ্বারা পুনরায় ব্যবহার করা হয় তখন কলগুলি কার্যকর করতে কখনই ভুলে যাবার উপায়টি বের করার চেষ্টা করছি।

স্পষ্টকরণ:

এখানে অনেক প্রশ্ন পরিষ্কার করতে:

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

  • আমি সি # ভাষা ব্যবহার করছি! আমি কীভাবে তা উল্লেখ করিনি ?! আমি একটি জামারিন পরিবেশে রয়েছি এবং পিসিএল, আইওএস, অ্যান্ড্রয়েড এবং উইন্ডোজ প্রকল্পগুলি সহ একটি সমাধানে সাধারণত প্রায় 6 থেকে 9 টি প্রকল্প ব্যবহার করে মোবাইল অ্যাপস তৈরি করি। আমি প্রায় দেড় বছর ধরে স্কুল বিকাশকারী (স্কুল এবং কাজ মিলিত), তাই আমার মাঝে মাঝে হাস্যকর বক্তব্য \ প্রশ্ন। এগুলি সম্ভবত এখানে অপ্রাসঙ্গিক তবে খুব বেশি তথ্য সর্বদা একটি খারাপ জিনিস নয়।

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

তিনি কীভাবে নিশ্চিত হন যে তিনি এই ইভেন্টে নিবন্ধভুক্ত?

আমি কীভাবে এটি নিশ্চিত করতে পারি যে তিনি "এক পর্যায়ে প্রক্রিয়াটি থামাতে" ভুলেন নি

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

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


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


5
অন্যান্য প্রশ্নের উত্তর অপ্রাসঙ্গিক, প্রশ্নটি এক নয়, তাই এগুলি পৃথক প্রশ্ন। যদি কেউ সেই আলোচনার সন্ধান করে তবে সে অন্য প্রশ্নের শিরোনামটি টাইপ করবে না।
গিল বালির

6
সিটারে প্রাথমিককরণের সামগ্রীটি মার্জ করতে বাধা দিচ্ছে কি ? initializeঅবজেক্টটি তৈরি হওয়ার পরে কলটি দেরী করা উচিত? কোরটি কী "ব্যতীত ঝুঁকিপূর্ণ" অর্থে তা ব্যতিক্রম ছুঁড়ে ফেলা এবং সৃষ্টির শৃঙ্খলা ভঙ্গ করতে পারে?
স্পট করেছেন

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

উত্তর:


161

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

কলকারীদের FooManagerএটি আরম্ভ করার আগে একটি নির্মাণ করা প্রয়োজন , উদাহরণস্বরূপ কারণ এটি FooManagerনির্ভরতা হিসাবে প্রায় পেরিয়ে গেছে।

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

ctorArgs = ...;
getFooManager = (initInfo) -> new FooManager(ctorArgs, initInfo);
...
getFooManager(myInitInfo).fooMethod();

এটির সাথে সমস্যাটি হ'ল প্রতিবার অ্যাক্সেস করার সময় আপনাকে সূচনা তথ্য সরবরাহ করতে হবে FooManager

যদি এটি আপনার ভাষায় প্রয়োজন হয় তবে আপনি getFooManager()অপারেশনটি কারখানার মতো বা বিল্ডারের মতো শ্রেণিতে গুটিয়ে রাখতে পারেন।

আমি initialize()টাইপ-সিস্টেম-স্তরের সমাধান ব্যবহার না করে পদ্ধতিটি বলা হয়েছিল যে রানটাইম চেকগুলি সত্যই করতে চাই ।

কোনও আপস খুঁজে পাওয়া সম্ভব। আমরা একটি মোড়কের ক্লাস তৈরি MaybeInitializedFooManagerকরি যার একটি get()পদ্ধতি রয়েছে যা ফেরত দেয় FooManager, তবে যদি FooManagerপুরোপুরি আরম্ভ করা না হয় তবে ছুঁড়ে দেয় । এটি কেবল তখনই কাজ করে যদি প্রাথমিককরণটি মোড়কের মাধ্যমে করা হয়, বা যদি কোনও FooManager#isInitialized()পদ্ধতি থাকে।

class MaybeInitializedFooManager {
  private final FooManager fooManager;

  public MaybeInitializedFooManager(CtorArgs ctorArgs) {
    fooManager = new FooManager(ctorArgs);
  }

  public FooManager initialize(InitArgs initArgs) {
    fooManager.initialize(initArgs);
    return fooManager;
  }

  public FooManager get() {
    if (fooManager.isInitialized()) return fooManager;
    throw ...;
  }
}

আমি আমার ক্লাসের এপিআই পরিবর্তন করতে চাই না।

সেক্ষেত্রে, আপনি if (!initialized) throw;প্রতিটি পদ্ধতিতে শর্তসাপেক্ষে এড়াতে চাইবেন । ভাগ্যক্রমে, এটি সমাধান করার জন্য একটি সাধারণ প্যাটার্ন রয়েছে।

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

class FooManager {
  private CtorArgs ctorArgs;
  private Impl impl;

  public FooManager(CtorArgs ctorArgs) {
    this.ctorArgs = ctorArgs;
    this.impl = new UninitializedImpl();
  }

  public void initialize(InitArgs initArgs) {
    impl = new MainImpl(ctorArgs, initArgs);
  }

  public X foo() { return impl.foo(); }
  public Y bar() { return impl.bar(); }
}

interface Impl {
  X foo();
  Y bar();
}

class UninitializedImpl implements Impl {
  public X foo() { throw ...; }
  public Y bar() { throw ...; }
}

class MainImpl implements Impl {
  public MainImpl(CtorArgs c, InitArgs i);
  public X foo() { ... }
  public Y bar() { ... }
}

এটি ক্লাসের মূল আচরণটি কে MainImpl


9
আমি প্রথম দুটি সমাধান (+1 টি) -এর মত, কিন্তু আমি পদ্ধতি তার পুনরাবৃত্তি সঙ্গে আপনার শেষ স্নিপেট মনে করি না FooManagerএবং UninitialisedImplকোন পুনরাবৃত্তি বেশী ভালো if (!initialized) throw;
বার্গি

3
@ বার্গি কিছু লোক ক্লাস খুব বেশি পছন্দ করে। যদিও যদি FooManagerএকটি আছে অনেক পদ্ধতি, এটা সম্ভাব্য কিছু বিস্মরণ তুলনায় অনেক সহজ হতে পারে if (!initialized)চেক। তবে সেক্ষেত্রে আপনার সম্ভবত ক্লাস ভাঙা পছন্দ করা উচিত।
ইমিবিস

1
খুব সম্ভবত আমার কাছেও ইনিশিয়ালাইজডফু ভাল বলে মনে হয় না, তবে কিছু বিকল্প / ধারণা দেওয়ার জন্য +1 করে।
ম্যাথু জেমস ব্রিগেস

7
+1 কারখানাটি সঠিক বিকল্প। আপনি কোনও নকশা এটি পরিবর্তন না করে উন্নত করতে পারবেন না, সুতরাং অর্ধেক কীভাবে করা উচিত সে সম্পর্কে উত্তরের শেষ বিট আইএমএইচও এটি ওপিকে সহায়তা করবে না।
নাথান কুপার

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

79

ক্লায়েন্টদের কোনও বস্তুর "অপব্যবহার" করা থেকে বিরত রাখার সবচেয়ে কার্যকর এবং সহায়ক উপায় হ'ল এটি অসম্ভব করে দেওয়া।

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

আপনার যদি প্রাথমিককরণের আগে অবিচ্ছিন্ন বস্তুটি অ্যাক্সেস করতে সক্ষম হওয়া দরকার হয় তবে আপনি দুটি রাজ্যকে পৃথক শ্রেণি হিসাবে প্রয়োগ করতে পারেন, সুতরাং আপনি একটি UnitializedFooManagerউদাহরণ দিয়ে শুরু করবেন , যার কোনও Initialize(...)পদ্ধতি রয়েছে যা প্রত্যাবর্তন করবে InitializedFooManager। যে পদ্ধতিগুলি কেবল প্রাথমিক অবস্থায় বলা যেতে পারে কেবল সেগুলিতেই বিদ্যমান InitializedFooManager। আপনার প্রয়োজন হলে এই পদ্ধতির একাধিক রাজ্যে প্রসারিত হতে পারে।

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

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

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

একটি সাধারণ উদাহরণ: আপনার কাছে একটি- Fileঅবজেক্ট রয়েছে যা আপনাকে কোনও ফাইল থেকে পড়তে দেয়। তবে, পদ্ধতিটি কল Openকরার আগে ক্লায়েন্টকে কল ReadLineকরতে হবে এবং সর্বদা কল করা উচিত Close(এমনকি কোনও ব্যতিক্রম ঘটলে) তার পরে ReadLineপদ্ধতিটি আর কল করা উচিত নয়। এটি অস্থায়ী সংযুক্তি। এটি একটি একক পদ্ধতি যা এড়াতে পারে যা একটি যুক্তি হিসাবে কলব্যাক বা প্রতিনিধি গ্রহণ করে। পদ্ধতিটি ফাইলটি খোলার পরিচালনা করে, কলব্যাক কল করে এবং তারপরে ফাইলটি বন্ধ করে দেয়। এটি Readকলব্যাকের সাথে একটি পদ্ধতি সহ একটি স্বতন্ত্র ইন্টারফেসটি পাস করতে পারে । এইভাবে, ক্লায়েন্টের পক্ষে সঠিক ক্রমে পদ্ধতি কল করতে ভুলে যাওয়া সম্ভব নয়।

টেম্পোরাল কাপলিংয়ের সাথে ইন্টারফেস:

class File {
     /// Must be called on a closed file.
     /// Remember to always call Close() when you are finished
     public void Open();

     /// must be called on on open file
     public string ReadLine();

     /// must be called on an open file
     public void Close();
}

অস্থায়ী মিলন ছাড়া:

class File {
    /// Opens the file, executes the callback, and closes the file again.
    public void Consume(Action<IOpenFile> callback);
}

interface IOpenFile {
    string ReadLine();
}

আরও একটি হেভিওয়েট সমাধান হ'ল Fileএকটি বিমূর্ত শ্রেণি হিসাবে সংজ্ঞায়িত করা যা আপনাকে একটি (সুরক্ষিত) পদ্ধতি প্রয়োগ করতে হবে যা খোলা ফাইলটিতে কার্যকর করা হবে। একে বলা হয় একটি টেম্পলেট পদ্ধতি প্যাটার্ন।

abstract class File {
    /// Opens the file, executes ConsumeOpenFile(), and closes the file again.
    public void Consume();

    /// override this
    abstract protected ConsumeOpenFile();

    /// call this from your ConsumeOpenFile() implementation
    protected string ReadLine();
}

সুবিধাটি একই: ক্লায়েন্টকে একটি নির্দিষ্ট ক্রমে পদ্ধতি কল করার কথা মনে রাখতে হবে না। পদ্ধতিগুলিকে ভুল ক্রমে কল করা সহজভাবে সম্ভব নয়।


2
এছাড়াও আমি এমন কেসগুলি মনে করি যেখানে কন্সট্রাক্টরের কাছ থেকে যাওয়া সহজভাবে সম্ভব ছিল না, তবে এখনই আমার কাছে উদাহরণ দেখানোর মতো উদাহরণ নেই
গিল স্যান্ড

2
উদাহরণটি এখন একটি কারখানার প্যাটার্ন বর্ণনা করে - তবে প্রথম বাক্যটি আসলে RAII দৃষ্টান্ত বর্ণনা করে । সুতরাং কোনটি এই উত্তরটি সুপারিশ করার কথা?
Ext3h

11
@ Ext3h আমি মনে করি না কারখানার প্যাটার্ন এবং আরআইআই পারস্পরিক একচেটিয়া।
পিটার বি

@ পিটারবি না, তারা নয়, একটি কারখানাটি আরআইআই নিশ্চিত করতে পারে। তবে কেবলমাত্র অতিরিক্ত প্রভাবের সাথেই টেমপ্লেট / কনস্ট্রাক্টর আরগস (ডাকা UnitializedFooManager) অবশ্যই উদাহরণস্বরূপ ( InitializedFooManager) এর সাথে একটি রাজ্য ভাগ করে নেবে না , যেমনটি Initialize(...)বাস্তবে Instantiate(...)শব্দার্থক। অন্যথায়, একই টেম্পলেটটি কোনও বিকাশকারী দ্বারা দু'বার ব্যবহার করা হলে এই উদাহরণটি নতুন সমস্যার দিকে পরিচালিত করে। ভাষাটি স্পষ্টভাবে moveটেম্পলেটটি গ্রাস করার জন্য শব্দার্থবিজ্ঞানকে সমর্থন না করে তা স্থিরভাবে রোধ / বৈধকরণ সম্ভব নয় ।
Ext3h

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

39

আমি সাধারনত অন্তরঙ্গকরণের জন্য যাচাই করে দেখি এবং IllegalStateExceptionযদি আপনি চেষ্টা করেন এবং এটি আরম্ভ না করা হয় তবে এটি ব্যবহার করুন (বলুন) ।

তবে, আপনি যদি সংকলন-সময় নিরাপদ হতে চান (এবং এটি প্রশংসনীয় এবং পছন্দসই) তবে কেন আরম্ভের কারণটিকে কোনও ফ্যাক্টরি পদ্ধতি হিসাবে বিবেচনা করবেন না যেমন একটি নির্মিত এবং আরম্ভকৃত বস্তুর উদ্বোধন করে যেমন

ComponentBuilder builder = new ComponentBuilder();
Component forClients = builder.initialise(); // the 'Component' is what you give your clients

এবং সুতরাং আপনি অবজেক্টগুলি সৃষ্টি এবং জীবনচক্র নিয়ন্ত্রণ করেন এবং আপনার ক্লায়েন্টরা Componentআপনার সূচনাটির ফলস্বরূপ এটি পান। এটি কার্যকরভাবে একটি অলস তাত্পর্য।


1
ভাল উত্তর - একটি ভাল সংক্ষিপ্ত উত্তরের 2 টি ভাল বিকল্প। উপরে উপস্থিত অন্যান্য টাইপ-সিস্টেম জিমন্যাস্টিকগুলি যা (তাত্ত্বিকভাবে) বৈধ; তবে সংখ্যাগরিষ্ঠ ক্ষেত্রে, এই 2 টি সহজ বিকল্প আদর্শ ব্যবহারিক পছন্দ choices
থমাস ডব্লিউ

1
দ্রষ্টব্য: .NET- এ, মাইক্রোসফ্ট দ্বারা আপনাকে যা বলা হয়েছিল , অবৈধ অপারেশন এক্সপ্রেশনটি প্রচারিত হয় IllegalStateException
মিরোক্লাভ

1
আমি এই উত্তরটি কম ভোট দিচ্ছি না তবে এটি আসলে একটি ভাল উত্তর নয়। কেবল নীল ছুঁড়ে ফেলে IllegalStateExceptionবা ফেলে দিয়ে InvalidOperationException, কোনও ব্যবহারকারী কখনই বুঝতে পারবেন না যে সে কী ভুল করেছে। এই ব্যতিক্রমগুলি ডিজাইনের ত্রুটি সমাধানের জন্য বাইপাসে পরিণত হওয়া উচিত নয়।
নাম

আপনি লক্ষ করবেন যে ব্যতিক্রম নিক্ষেপ করা একটি সম্ভাব্য বিকল্প এবং আমি আমার পছন্দসই বিকল্পটি সম্পর্কে বিস্তারিত বলতে যাচ্ছি - এই সংকলন-সময়কে নিরাপদ করে তুলছি। আমি এর জোর দেওয়ার জন্য আমার উত্তরটি সম্পাদনা করেছি
ব্রায়ান অ্যাগনিউ

14

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

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

অন্যদিকে, আপনি যদি সি লিখছেন, আপনার সহকর্মীরা পুরোপুরি তাদের অধিকারের অধীনে আপনাকে ফিরিয়ে নেবে এবং আলাদা অপারেশনগুলিকে সমর্থন করে এমন পৃথক struct FooManagerএবং struct UninitializedFooManagerপ্রকারের সংজ্ঞা দেওয়ার জন্য আপনাকে গুলি করবে , কারণ এটি খুব অল্প উপকারের জন্য অকারণে জটিল কোডের দিকে নিয়ে যায় ।

আপনি যদি পাইথন লিখছেন, ভাষার এটি করার কোনও ব্যবস্থা নেই।

আপনি সম্ভবত হাস্কেল, পাইথন, বা সি লিখছেন না, তবে টাইপ সিস্টেমটি কতটা / কতটা কম কাজ আশা করতে পারে এবং কী করতে সক্ষম হবে সে ক্ষেত্রে তারা উদাহরণস্বরূপ।

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


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

3
"এটি" দ্বারা, আমি রানটাইমের বিপরীতে একটি সংকলন-সময় ত্রুটি বোঝাতে চাইছি।
প্যাট্রিক কলিন্স

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

ওহ ঠিক আছে. বিলেড +1 এমনকি বিভ্রান্ত, এটি খুব অন্তর্দৃষ্টিপূর্ণ ছিল।
AL ফ্লানাগান

আমি তোমার স্টাইল প্যাট্রিক পছন্দ করি
গিল বালির

4

আপনার মনে হয় যে কোড চেকটি গ্রাহকের কাছে প্রেরণ করতে চান না (তবে এটি প্রোগ্রামারের জন্য এটি করা ভাল বলে মনে হচ্ছে) আপনি যদি আপনার প্রোগ্রামিং ভাষায় উপলব্ধ থাকে তবে আপনি দৃsert় ফাংশনগুলি ব্যবহার করতে পারেন ।

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

সুতরাং, একটি জাভা শ্রেণি এটি ব্যবহার করে দেখতে লাগবে:

/** For some reason, you have to call init and connect before the manager works. */
public class FooManager {
   private int state = 0;

   public FooManager () {
   }

   public synchronized void init() {
      assert state==0 : "you called init twice.";
      // do something
      state = 1;
   }

   public synchronized void connect() {
      assert state==1 : "you called connect before init, or connect twice.";
      // do something
      state = 2;
   }

   public void someWork() {
      assert state==2 : "You did not properly init FooManager. You need to call init and connect first.";
      // do the actual work.
   }
}

আপনার প্রয়োজনীয় প্রোগ্রামের রানটাইম স্থিতি যাচাই করার জন্য দৃser় প্রতিবেদনগুলি একটি দুর্দান্ত সরঞ্জাম, তবে বাস্তবে কেউ বাস্তবে কোনও ভুল করছেন এমন প্রত্যাশা করবেন না।

এছাড়াও এগুলি বেশ স্লিম এবং যদি () নিক্ষেপ করেন ... সিনট্যাক্সের বিশাল অংশ গ্রহণ করবেন না, তাদের ধরার দরকার নেই, ইত্যাদি


3

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

class SomeClass
{
   private int valueRequiredByMethodB;

   public IReadyForB a (int v) { valueRequiredByMethodB = v; return new ReadyForB(this); }

   public interface IReadyForB { public void b (); }

   private class ReadyForB : IReadyForB
   {
      SomeClass owner;
      private ReadyForB (SomeClass owner) { this.owner = owner; }
      public void b () { Console.WriteLine (owner.valueRequiredByMethodB); }
   }
}

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


2

আমি যখন কোনও বেস ক্লাস প্রয়োগ করি যার জন্য অতিরিক্ত প্রাথমিককরণের তথ্য প্রয়োজন হয় বা এটি কার্যকর হওয়ার আগে অন্যান্য বস্তুর সাথে লিঙ্ক হয়, আমি সেই বেস বর্গকে বিমূর্ত করে তুলি, তারপরে সেই শ্রেণীর বিভিন্ন বিমূর্ত পদ্ধতি সংজ্ঞায়িত করি যা বেস শ্রেণীর প্রবাহে ব্যবহৃত হয় (যেমন abstract Collection<Information> get_extra_information(args);এবং abstract Collection<OtherObjects> get_other_objects(args);যা উত্তরাধিকারের চুক্তির মাধ্যমে কংক্রিট বর্গ দ্বারা বাস্তবায়ন করা উচিত, সেই বেস শ্রেণির ব্যবহারকারীকে বেস বর্গ দ্বারা প্রয়োজনীয় সমস্ত জিনিস সরবরাহ করতে বাধ্য করা।

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

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


2

উত্তর: হ্যাঁ, না, এবং কখনও কখনও। :-)

আপনার বর্ণিত কিছু সমস্যা সহজেই সমাধান করা যায়, কমপক্ষে অনেক ক্ষেত্রে।

কম-টাইম চেকিং অবশ্যই রান-টাইম চেকিংয়ের চেয়ে বেশি পছন্দনীয়, যা মোটেও পরীক্ষা না করাই ভাল।

আরআর রান-টাইম:

রান-টাইম চেক সহ কিছু নির্দিষ্ট ক্রমে ডেকে আনা ফাংশনগুলিকে বাধ্য করা কমপক্ষে ধারণাগতভাবে সহজ। সবেমাত্র পতাকা লাগান যা বলে যে কোন ফাংশনটি চালিত হয়েছে, এবং প্রতিটি ফাংশনটি "প্রাক-শর্ত -১ নয় বা প্রাক-শর্ত -২ নয় তবে ব্যতিক্রম নিক্ষেপ করুন" এর মতো কিছু দিয়ে শুরু করা যাক। যদি চেকগুলি জটিল হয়ে যায়, আপনি এগুলি একটি ব্যক্তিগত ফাংশনে ঠেলাতে পারেন।

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

সংকলন সময়:

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

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

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

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

কার্যকর করা অসম্ভব

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

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

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

তবে এমন কিছু বিষয় রয়েছে যেখানে আপনাকে বলতে হবে যে প্রোগ্রামারটির ফাংশনে ডকুমেন্টেশনটি পড়া উচিত।


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


2

হ্যাঁ, আপনার প্রবৃত্তিগুলি স্পট-অন রয়েছে। বহু বছর আগে আমি ম্যাগাজিনগুলিতে নিবন্ধগুলি লিখেছিলাম (ধরণের জায়গা যেমন, তবে মৃত গাছের উপরে এবং প্রতি মাসে একবার প্রকাশ করা হয়) ডিবাগিং , অ্যাবগিং এবং অ্যান্টিবাগিং নিয়ে আলোচনা করে ।

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

তবে রান-টাইমের পরিবর্তে সংকলন সময়ে ব্যবহার শনাক্ত করার জন্য একটি পরীক্ষা করা সত্যই একই ধরণের পরীক্ষা: আপনাকে এখনও প্রথমে যথাযথ ফাংশনগুলি কল করতে এবং সেগুলি সঠিক উপায়ে ব্যবহার করতে হবে।

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

আপনি জিজ্ঞাসা করেন, সঠিক ব্যবহার নিশ্চিত করার জন্য যদি রান-টাইমে পরীক্ষা করা যায়, আপনার কি তা করা উচিত?

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

সম্ভবত চেকিংটি কেবল একটি ডিবাগ বিল্ডে করা হয়।

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

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

আপনার প্রবৃত্তি ভাল। এটা বজায় রাখা!


0

ইনফরমেশন হিডিং (এনক্যাপসুলেশন) নীতিটি হ'ল এই শ্রেণীর সঠিকভাবে ব্যবহার করার জন্য শ্রেণীর বাইরের সত্তাগুলি আরও কিছু জানেন না।

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

  • হয় নির্মাতায় স্পষ্টভাবে প্রয়োজনীয় তথ্য জিজ্ঞাসা করুন;
  • বা কনস্ট্রাক্টরদের অক্ষত রাখুন এবং পদ্ধতিগুলি সংশোধন করুন যাতে পদ্ধতিগুলি কল করার জন্য আপনাকে নিখোঁজ ডেটা সরবরাহ করতে হবে।

জ্ঞানের শব্দ:

* যেভাবেই আপনাকে ক্লাস এবং / অথবা কনস্ট্রাক্টর এবং / অথবা পদ্ধতিগুলি নতুন করে ডিজাইন করতে হবে।

* সঠিকভাবে ডিজাইন না করে এবং সঠিক তথ্য থেকে ক্লাস অনাহারে আপনি নিজের ক্লাসটিকে একটিতে নয় বরং একাধিক জায়গায় ভাঙতে ঝুঁকির মধ্যে ফেলছেন।

* আপনি যদি ব্যতিক্রম এবং ত্রুটির বার্তাগুলি দুর্বলভাবে লিখে থাকেন তবে আপনি শ্রেণিটি নিজের সম্পর্কে আরও বেশি কিছু দিচ্ছেন।

* অবশেষে, যদি বহিরাগতকে এটির ধারণা হয় যে এটি a, b এবং c আরম্ভ করতে হবে এবং তারপরে d (), e (), f (int) কল করবে তবে আপনার বিমূর্ততায় আপনার একটি ফুটো আছে।


0

যেহেতু আপনার নির্দিষ্ট করা যে আপনার C # এর ব্যবহার করছেন আপনার অবস্থা করার জন্য একটি টেকসই সমাধান লিভারেজ হয় Roslyn কোড বিশ্লেষক । এটি আপনাকে অবিলম্বে লঙ্ঘনগুলি ধরতে অনুমতি দেবে এবং এমনকি কোড সংশোধন করার পরামর্শ দেবে ।

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

public abstract class Foo
{
   [TemporallyCoupled(1)]
   public abstract void Init();

   [TemporallyCoupled(2)]
   public abstract void DoBar();

   [TemporallyCoupled(3)]
   public abstract void Close();
}

1: আমি কখনও কোনও রোজলিন কোড অ্যানালাইজার লিখিনি তাই এটি সর্বোত্তম বাস্তবায়ন নাও হতে পারে। আপনার এপিআই সঠিকভাবে ব্যবহৃত হচ্ছে যাচাই করতে রোজলিন কোড অ্যানালাইজার ব্যবহার করার ধারণাটি যদিও 100% সাউন্ড is


-1

এই সমস্যার সমাধান করার আগে আমি যেভাবে প্রাইভেট কনস্ট্রাক্টর এবং MakeFooManager()ক্লাসের মধ্যে একটি স্থিতিশীল পদ্ধতি নিয়ে ছিলাম । উদাহরণ:

public class FooManager
{
     public string Foo { get; private set; }
     public string Bar { get; private set; }

     private FooManager(string foo, string bar)
     {
         Foo = foo;
         Bar = bar;
     }

     public static FooManager MakeFooManager(string foo, string bar)
     {
         // Can do other checks here too.
         if(foo == null || bar == null)
         {
             return null;
         }
         else
         {
             return new FooManager(foo, bar);
         }
     }
}

যেহেতু কোনও কনস্ট্রাক্টর বাস্তবায়িত হয়েছে, তাই কারও পক্ষে কোনও ঘটনা FooManagerছাড়াই উদাহরণ তৈরি করার উপায় নেই MakeFooManager()


1
এই নিছক বিন্দু তৈরি এবং একটি ব্যাখ্যা পুনরাবৃত্তি বলে মনে হয় পূর্বে উত্তর আগে বেশ কয়েক ঘন্টা পোস্ট করা হয়েছে
মশা

1
এই ctor মধ্যে নাল চেকিং সব জুড়ে কোন সুবিধা আছে? দেখে মনে হচ্ছে আপনি কেবল এমন একটি পদ্ধতি তৈরি করেছেন যা অন্য পদ্ধতি মোড়ানো ছাড়া কিছুই করে না। কেন?
সারা

এছাড়াও, কেন foo এবং বার সদস্যের ভেরিয়েবল?
প্যাট্রিক এম

-1

বেশ কয়েকটি পন্থা রয়েছে:

  1. শ্রেণিকে সঠিক এবং সঠিক ব্যবহারকে ভুল ব্যবহার সহজ করুন hard অন্যান্য উত্তরগুলির মধ্যে কিছু এই পয়েন্টটিতে একচেটিয়াভাবে ফোকাস করে, তাই আমি কেবলমাত্র RAII এবং বিল্ডার প্যাটার্নটি উল্লেখ করব ।

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

  3. আপনার ডিবাগ বিল্ডগুলিতে সংস্থান ব্যবহার করুন ।

  4. শ্রেণীর ব্যবহারটি অবৈধ হলে ব্যতিক্রম ছুঁড়ে ফেলুন।

* এগুলি এমন ধরণের মন্তব্য যা আপনার লেখা উচিত নয়:

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