কীভাবে আমার জটিল রাষ্ট্রীয় ক্লাসগুলি এবং তাদের পরীক্ষা সহজ করা যায়?


9

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

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

উদাহরণ হিসাবে এবং জিনিসগুলি সহজ এবং পরিষ্কার রাখার জন্য, আসুন আমরা বলতে পারি যে রোবট এবং কার আমার প্রকল্পের ক্লাস ছিল।

সুতরাং, রোবট শ্রেণিতে আমার নিম্নলিখিত পদ্ধতিতে প্রচুর পদ্ধতি থাকবে:

  • ঘুম(); isSleepAvaliable ();
  • জাগ্রত (); isAwakeAvaliable ();
  • (দিক নির্দেশ) পদব্রজে ভ্রমণ; isWalkAvaliable ();
  • অঙ্কুর (দিক নির্দেশ); isShootAvaliable ();
  • turnOnAlert (); isTurnOnAlertAvailable ();
  • turnOffAlert (); isTurnOffAlertAvailable ();
  • রিচার্জ (); isRechargeAvailable ();
  • যন্ত্র বন্ধ(); isPowerOffAvailable ();
  • stepInCar (গাড়ি); isStepInCarAvailable ();
  • stepOutCar (গাড়ি); isStepOutCarAvailable ();
  • selfDestruct (); isSelfDestructAvailable ();
  • মরা (); isDieAvailable ();
  • জীবিত(); জাগ্রত(); isAlertOn (); getBatteryLevel (); getCurrentRidingCar (); getAmmo ();
  • ...

গাড়ী শ্রেণিতে, এটি একই রকম হবে:

  • চালু করা(); isTurnOnAvaliable ();
  • বন্ধ কর(); isTurnOffAvaliable ();
  • (দিক নির্দেশ) পদব্রজে ভ্রমণ; isWalkAvaliable ();
  • আবার জ্বালানি ভরে নেওয়া (); isRefuelAvailable ();
  • selfDestruct (); isSelfDestructAvailable ();
  • বিপর্যস্ত (); isCrashAvailable ();
  • isOperational (); isOn (); getFuelLevel (); getCurrentPassenger ();
  • ...

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

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

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

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

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

সম্পাদনা:
আমি মনে করি রাষ্ট্রীয় মেশিনগুলির বিষয়ে আমি পরিষ্কার ছিলাম না। রোবট নিজেই একটি রাষ্ট্রীয় মেশিন, যেখানে "ঘুমন্ত", "জাগ্রত", "রিচার্জিং", "মৃত" ইত্যাদি রয়েছে The

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


আপনি কোড পর্যালোচনা.এসইতে জিজ্ঞাসা বিবেচনা করেছেন ? অন্য যে, আপনার মত নকশা জন্য আমি চিন্তা শুরু করতে চাই এক্সট্র্যাক্ট ক্লাস ধরনের refactoring
মশা

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

@gnat আপনি কীভাবে প্রদত্ত রোবট এবং গাড়ির দৃশ্যে এক্সট্র্যাক্ট ক্লাস প্রয়োগ করব তার একটি উদাহরণ দিতে পারেন?
ভিক্টর স্টাফুসা

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

এটি কোনও কোড পর্যালোচনা প্রশ্ন নয় - সেখানে আর্কিটেকচারটি অফ-টপিক।
মাইকেল কে

উত্তর:


8

রাজ্য যদি আপনি ইতিমধ্যে এটি ব্যবহার করছেন না নকশা প্যাটার্ন, ব্যবহারের হতে পারে।

তাই আপনার উদাহরণস্বরূপ, অব্যাহত রাখার জন্য - কোর ধারণা যে আপনি প্রতিটি স্বতন্ত্র রাষ্ট্রের জন্য একটি ভেতরের বর্গ তৈরি হয় SleepingRobot, AwakeRobot, RechargingRobotএবং DeadRobotক্লাস সব হবে, একটি সাধারণ ইন্টারফেস বাস্তবায়ন।

Robotশ্রেণীর পদ্ধতিগুলির (যেমন sleep()এবং isSleepAvaliable()) সাধারণ বাস্তবায়ন রয়েছে যা বর্তমান অভ্যন্তরীণ শ্রেণীর প্রতিনিধিত্ব করে।

রাষ্ট্রের পরিবর্তনগুলি বর্তমানের অভ্যন্তর শ্রেণিকে আলাদা আলাদা করে অদলবদল করে প্রয়োগ করা হয়।

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


আমি জাভা ব্যবহার করছি।
ভিক্টর স্টাফুসা

ভাল পরামর্শ। এইভাবে প্রতিটি বাস্তবায়নের একটি স্পষ্ট ফোকাস রয়েছে যা একই সাথে সমস্ত রাজ্যের ২.০০০ লাইনের জুনিট শ্রেণি পরীক্ষা না করে পৃথকভাবে পরীক্ষা করা যেতে পারে।
অলিভারস

3

আমি আপনার কোডটি জানি না, তবে "ঘুম" পদ্ধতির উদাহরণ গ্রহণ করে, আমি ধরে নেব যে এটি নীচের "সরল" কোডের মতো কিছু রয়েছে:

public void sleep() {
 if(!dead && awake) {
  sleeping = true;
  awake = false;
  this.updateState(SLEEPING);
 }
 throw new IllegalArgumentException("robot is either dead or not awake");
}

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

উপরের কোডটি দেওয়া, আমি "মেশিনস্টেট" অবজেক্টটিকে উপহাস করব এবং আমার প্রথম পরীক্ষাটি হ'ল:

testSleep_dead() {
 robot.dead = true;
 robot.awake = false;
 robot.setState(AWAKE);
 try {
  robot.sleep();
  fail("should have got an exception");
 } catch(Exception e) {
  assertTrue(e instanceof IllegalArgumentException);
  assertEquals("robot is either dead or not awake", e.getMessage());
 }
}

আমার ব্যক্তিগত মতামত এই যে ছোট ইউনিট পরীক্ষা লেখার জন্য প্রথম কাজ করা উচিত। আপনি লিখেছেন:

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

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

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

অবশেষে, আপনার কোডটি জটিল (যেমন আপনি এখন বলেছিলেন) বা আপনি রিফ্যাক্টর করার পরে এটি করা যায়।


আমি মনে করি রাষ্ট্রীয় যন্ত্রগুলি সম্পর্কে আমি পরিষ্কার ছিলাম না। রোবট নিজেই একটি রাষ্ট্রীয় মেশিন, যেখানে "ঘুমন্ত", "জাগ্রত", "রিচার্জিং", "মৃত" ইত্যাদি রয়েছে The
ভিক্টর স্টাফুসা

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

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

2

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

আমি নিবন্ধটি উদ্ধৃত করব। সমস্যা: "... একটি প্রধান চাকরির ক্লাস .... বিভিন্ন ক্লায়েন্টের জন্য নির্দিষ্ট প্রচুর পদ্ধতির একটি ফ্যাট ক্লাস।" সমাধান: "... চাকরী শ্রেণি এবং এর সমস্ত ক্লায়েন্টের মধ্যে ইন্টারফেসের একটি স্তর ..."

আপনার সমস্যাটি মনে হচ্ছে যে জেরক্সের একটির অনুমতি ছিল। একটি ফ্যাট শ্রেণীর পরিবর্তে আপনার দুটি রয়েছে এবং প্রচুর ক্লায়েন্টের পরিবর্তে এই দুটি ফ্যাট ক্লাস একে অপরের সাথে কথা বলছে।

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

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