উন্নয়নের সময় বিভিন্ন ধরণের আচরণের মধ্যে স্যুইচ করতে # আইফডিএফ ব্যবহার করা


28

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

আমি সাধারণত বেশ কয়েকটি সনাক্তকারী পরিচয় করিয়ে দিই এবং এর মতো কিছু করি

void foo()
{
    doSomething1();
#ifdef APPROACH1
    foo_approach1();
#endif
    doSomething2();
#ifdef APPROACH2
    foo_approach2();
#endif
}

void bar()
{
    doSomething3();
#ifndef APPROACH3
    doSomething4();
#endif
    doSomething5();
#ifdef APPROACH2
    bar_approach2();
#endif
}

int main()
{
    foo();
    bar();
    return 0;
}

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



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

1
আমি কৌশল প্যাটার্ন বা ভাল অল'পলিমারফিজম ব্যবহারের পরামর্শ দেব, যেহেতু এটি সুইচযোগ্য আচরণের জন্য একটি একক প্লাগ-ইন পয়েন্ট রাখতে সহায়তা করে।
pmf

4
মনে রাখবেন যে কিছু আইডিইগুলি #ifdefযদি ব্লকটি বন্ধ থাকে তবে ব্লকগুলির কোনও কিছুর মূল্যায়ন করে না । আমরা এমন ক্ষেত্রে চলে এসেছি যেখানে কোডগুলি সহজেই বাসি হয়ে যায় এবং আপনি যদি নিয়মিতভাবে সমস্ত পাথ তৈরি না করেন তবে সংকলন করতে পারে না।
বেরিন লরিটস্ক

এই উত্তরটি একবার দেখুন আমি অন্য একটি প্রশ্নের উত্তর দিয়েছি। এটি প্রচুর #ifdefsকম অসুবিধে করার কিছু উপায় দেয় la
ব্যবহারকারী 1118321

উত্তর:


9

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


gitজিনিস এই ধরণের বিশেষত পারদর্শী। হয়তো না, তাই অনেক ক্ষেত্রে svn, hgবা অন্যদের, কিন্তু এটি এখনও করা সম্ভব।
twalberg

এটি আমার প্রাথমিক চিন্তাও ছিল। "অন্যরকম কিছু নিয়ে ঘোরাঘুরি করতে চান?" git branch!
ওয়েজ তোলেম্যান

42

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

আমি এমএফসি সি ++ তে লিখিত একটি উত্তরাধিকারসূত্রে পেয়েছি যা #ifdefপ্ল্যাটফর্ম-নির্দিষ্ট মানগুলি সংজ্ঞায়িত করতে ইতিমধ্যে ব্যবহৃত হয়েছিল। এর অর্থ হ'ল আমি আমার প্রোগ্রামটি 32-বিট প্ল্যাটফর্ম বা 64-বিট প্ল্যাটফর্মের জন্য নির্দিষ্ট ম্যাক্রো মানগুলি সংজ্ঞায়িত করে (বা কিছু ক্ষেত্রে সংজ্ঞায়িত না করে) ব্যবহার করতে সংকলন করতে পারি।

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

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

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

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


ডিবাগ সংস্করণগুলির কী, "যদি ডিবাগ, ভেরিয়েবল এক্স সংজ্ঞায়িত করুন ..." এর মতো মনে হয় এটি লগিংয়ের মতো জিনিসগুলির পক্ষে উপকারী হতে পারে তবে ডিবাগ সক্ষম হওয়ার সময় এবং আপনার প্রোগ্রামটি কীভাবে কাজ করে তা পুরোপুরি পরিবর্তিত হতে পারে when ।
WHN

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

ওহ হ্যাঁ, এটি ডিবাগের জন্য পুনরায় সংকলন না করাই আরও আদর্শ হবে, আমি সে সম্পর্কে ভাবিনি!
WHN

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

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

21

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

তবে সতর্কতার একটি শব্দ: # আইফডিফ শাখাগুলি সেখানে রাখুন না কেন আমার সময় নষ্ট করার চেয়ে একই জিনিসটি চারটি ভিন্ন উপায়ে প্রয়োগ করা হয়, কেবল আমার কোনটি পড়তে হবে তা নির্ধারণ করার জন্য

একটি # আইডিপিডের উপর পড়তে প্রচেষ্টা নেওয়া দরকার কারণ আপনার এটিকে এড়াতে আসলেই মনে রাখতে হবে! একেবারে যত শক্তিশালী হতে হবে তার চেয়ে শক্ত করে তুলবেন না।

আপনার যতটা সম্ভব অল্প পরিমাণে #ifdefs ব্যবহার করুন। স্থায়ী পার্থক্য যেমন ডিবাগ / রিলিজ বিল্ডস বা বিভিন্ন আর্কিটেকচারের জন্য আপনি আপনার বায়ুমণ্ডলের পরিবেশের মধ্যে সাধারণত এটি করতে পারেন ।

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


1

এর মতো # আইফডিফ ব্যবহার করে কোড পড়া খুব কঠিন হয়ে যায়।

সুতরাং, না, এর মতো #ifdefs ব্যবহার করবেন না।

কেন ifdefs ব্যবহার না করার জন্য অনেক তর্ক থাকতে পারে, আমার জন্য এটি যথেষ্ট।

void foo()
{
    doSomething1();
#ifdef APPROACH1
    foo_approach1();
#endif
    doSomething2();
#ifdef APPROACH2
    foo_approach2();
#endif
}

এটি করতে পারে এমন অনেক কিছুই করতে পারে:

void foo()
{
    doSomething1();
    doSomething2();
}

void foo()
{
    doSomething1();
    foo_approach1();
    doSomething2();
}

void foo()
{
    doSomething1();
    doSomething2();
    foo_approach2();
}

void foo()
{
    doSomething1();
    foo_approach1();
    doSomething2();
    foo_approach2();
}

সমস্ত কি পদ্ধতির সংজ্ঞায়িত করা হয় বা না তার উপর নির্ভর করে। এটি কী করে তা প্রথম চেহারাতে একেবারে পরিষ্কার নয়।

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