এখানে বর্ণিত সেরা পদ্ধতিগুলি AIDL ইন্টারফেস কার্যকরভাবে এবং ইন্টারফেসের নমনীয়তার দিকে মনোযোগ দিয়ে ডেভেলপ করার জন্য একটি গাইড হিসেবে কাজ করে, বিশেষ করে যখন AIDL একটি স্থিতিশীল, ব্যাকওয়ার্ড-কম্প্যাটিবল API সংজ্ঞায়িত করতে ব্যবহৃত হয়।
অ্যাপগুলি যখন ব্যাকগ্রাউন্ড প্রসেসে একে অপরের সাথে ইন্টারফেস করতে চায় বা সিস্টেমের সাথে ইন্টারফেস করতে চায়, তখন API নির্ধারণ করতে AIDL ব্যবহার করা যেতে পারে।
HAL ইন্টারফেসের জন্য @VintfStability সহ স্থিতিশীল AIDL ব্যবহার করা হয় এবং ক্লায়েন্ট
ও সার্ভারকে স্বতন্ত্রভাবে আপডেট করার অনুমতি দেয়। এর জন্য ব্যাকওয়ার্ড
কম্প্যাটিবিলিটি ও স্ট্রাকচার্ড ডেটা প্রয়োজন।
AIDL-এর মাধ্যমে অ্যাপে প্রোগ্রামিং ইন্টারফেস ডেভেলপ করা সম্পর্কে আরও তথ্য পেতে, Android ইন্টারফেস ডেফিনিশন ল্যাঙ্গুয়েজ (AIDL) দেখুন। প্র্যাক্টিক্যাল AIDL-এর উদাহরণ দেখতে, HAL-এর জন্য AIDL এবং স্টেবল AIDL দেখুন।
ভার্সনিং
AIDL API-এর প্রতিটি ব্যাকওয়ার্ড-কম্প্যাটিবল স্ন্যাপশট একটি ভার্সনের সাথে সম্পর্কিত।
স্ন্যাপশট নিতে, m <module-name>-freeze-api চালান। API-এর কোনও ক্লায়েন্ট বা সার্ভার রিলিজ করা হলে (যেমন, মেইনলাইন ট্রেনে), আপনাকে স্ন্যাপশট নিতে হবে এবং নতুন ভার্সন তৈরি করতে হবে। সিস্টেম-টু-ভেন্ডর API-এর ক্ষেত্রে, এটি
বার্ষিক প্ল্যাটফর্ম রিভিশনের সাথে হতে হবে।
কোনও ইন্টারফেস ফ্রিজ করা হলে (ভার্সন করা aidl_api ডিরেক্টরিতে সেভ করা হলে), সেটি
কখনও পরিবর্তন করা যাবে না। আপনি শুধুমাত্র current ডিরেক্টরি এডিট করতে পারবেন। আপনি
নিরাপদে ইন্টারফেসের শেষে পদ্ধতি, পার্সেলযোগ্যর শেষে ফিল্ড,
এনামেরেশনের শেষে এনুম এবং ইউনিয়নের শেষে মেম্বার যোগ করতে পারবেন।
পুরনো সার্ভারে নতুন পদ্ধতি কল করা ক্লায়েন্টরা
UNKNOWN_TRANSACTION সমস্যা পান, যা ক্লায়েন্টকে সুন্দরভাবে ম্যানেজ করতে হবে।
অনুমোদিত পরিবর্তনের ধরন সম্পর্কে আরও বিবরণ ও তথ্য পেতে, ভার্সনিং ইন্টারফেস দেখুন।
ডিপেন্ডেন্সি তৈরি করা
Android মডিউল aidl_interface থেকে তৈরি করা লাইব্রেরির একাধিক, বিভিন্ন ভার্সনের উপর নির্ভর করতে পারে না। লাইব্রেরির বিভিন্ন ভার্সন
একই নেমস্পেসে একই ধরনের ডেটা ডিফাইন করে। Android-এর aidl বিল্ড সিস্টেম
এই সমস্যা শনাক্ত করে এবং প্রতিটি ডিপেন্ডেন্সি গ্রাফের সাথে একটি সমস্যা দেখায়
যা লাইব্রেরির অমিল ভার্সনে শেষ হয়।
এর ফলে, কোনও মডিউলে নিজস্ব ডিপেন্ডেন্সি সহ অনেক ডিপেন্ডেন্সি থাকলে, সাধারণ ইন্টারফেসের একটি ভার্সন আপডেট করা কঠিন হতে পারে।
ডেভেলপাররা aidl_interface_defaults ব্যবহার করে শেয়ার করা
ইন্টারফেসের নির্ভরতা অন্যান্য ইন্টারফেসের উপর ঘোষণা করতে পারেন, যাতে সবকটি ইন্টারফেসকে
আলাদাভাবে আপডেট করতে না হয়।
জেনারেট করা লাইব্রেরির উপর ডিপেন্ডেন্সি সাজাতে
আমরা *_defaults মডিউল (যেমন rust_defaults,
cc_defaults, java_defaults) ব্যবহার করার সাজেশন দিই। latest ভার্সনের ইন্টারফেসের জন্য ডিফল্ট থাকা সাধারণ ব্যাপার,
সেইসাথে পূর্ববর্তী ভার্সনের জন্যও ডিফল্ট থাকে
যদি সেগুলি এখনও ব্যবহার করা হয়।
ডেভেলপাররা aidl_interface_defaults ব্যবহার করে অন্যান্য ইন্টারফেসের উপর শেয়ার করা ইন্টারফেসের ডিপেন্ডেন্সি ঘোষণা করতে পারেন, যাতে সবকটি ইন্টারফেসকে আলাদা আলাদাভাবে আপডেট করতে না হয়।
API ডিজাইন সংক্রান্ত নির্দেশিকা
সাধারণ
১. সবকিছু ডকুমেন্ট করা
- প্রতিটি পদ্ধতির শব্দার্থ, আর্গুমেন্ট, বিল্ট-ইন ব্যতিক্রমের ব্যবহার, পরিষেবা-নির্দিষ্ট ব্যতিক্রম এবং রিটার্ন ভ্যালু ডকুমেন্ট করুন।
- প্রতিটি ইন্টারফেসের শব্দার্থের ডকুমেন্টেশন।
- এনাম ও কনস্ট্যান্টের সিম্যান্টিক অর্থ ডকুমেন্ট করুন।
- ইমপ্লিমেন্টারের কাছে যা কিছু অস্পষ্ট মনে হতে পারে তা ডকুমেন্ট করুন।
- প্রাসঙ্গিক হলে উদাহরণ দাও।
২. কেসিং
টাইপের জন্য আপার ক্যামেল কেসিং এবং মেথড, ফিল্ড ও
আর্গুমেন্টের জন্য লোয়ার ক্যামেল কেসিং ব্যবহার করুন। যেমন, পার্সেলযোগ্য ধরনের জন্য MyParcelable এবং আর্গুমেন্টের জন্য anArgument
। সংক্ষিপ্ত রূপের ক্ষেত্রে, সংক্ষিপ্ত রূপটিকে একটি শব্দ হিসেবে বিবেচনা করুন (NFC -> Nfc)।
[-Wconst-name] এনুম ভ্যালু ও কনস্ট্যান্ট ENUM_VALUE ও
CONSTANT_NAME হতে হবে
৩. গ্লোবাল জ্ঞানের প্রয়োজন হয় এমন প্রশ্ন এড়িয়ে যাওয়া
API-এর এমনটি ধরে নেওয়া উচিত নয় যে ডেভেলপারদের সমগ্র কোডবেস বা নির্দিষ্ট ডোমেন সংক্রান্ত বিষয়ে বিশ্বব্যাপী জ্ঞান আছে। ডোমেন-নির্দিষ্ট শনাক্তকারী (যেমন, ডিভাইসের নাম, আইডি বা হ্যান্ডেল) নিয়ে কাজ করার সময়:
- ইন্টারফেসের দুই পক্ষের জন্যই এগুলি জানা গুরুত্বপূর্ণ হলে, এই শনাক্তকারী কোথা থেকে এসেছে এবং এর ফর্ম্যাট কেমন তা স্পষ্টভাবে উল্লেখ করুন এবং ডকুমেন্ট করুন।
- অথবা, ইন্টারফেস-নির্দিষ্ট শনাক্তকারী (যেমন বাইন্ডার অবজেক্ট বা কাস্টম টোকেন) ব্যবহার করুন এবং এক পক্ষকে অন্তর্নিহিত ভ্যালুগুলির ম্যাপিং ম্যানেজ করতে দিন। এর ফলে সংঘর্ষ কমে যায় এবং ব্যবহারকারীদেরকে তাদের ক্ষেত্রের বাইরের ইমপ্লিমেন্টেশন সংক্রান্ত বিবরণ বুঝতে হয় না।
৪. সব ডেটা স্ট্রাকচার্ড এবং ব্যাকওয়ার্ড মানানসই
string, byte[] ও শেয়ার করা মেমরির মতো আনস্ট্রাকচার্ড ডেটার কন্টেন্ট অবশ্যই
স্থিতিশীল ফর্ম্যাটে থাকতে হবে অথবা ইন্টারফেসের একদিকের কাছে তা অস্বচ্ছ হতে হবে।
যেমন, কোনও ফলাফলের জন্য ত্রুটি মেসেজ হিসেবে ব্যবহৃত স্ট্রিং আর্গুমেন্ট
রিসিভ করা এবং ডিবাগ করার জন্য লগ করা যেতে পারে, তবে এটি অবশ্যই পার্স এবং ব্যাখ্যা করা যাবে না
কারণ ফর্ম্যাট এবং কন্টেন্ট ব্যাকওয়ার্ড
কম্প্যাটিবল নাও হতে পারে। ইন্টারফেসের অন্য প্রান্তে যদি রান টাইমে কী সমস্যা হয়েছে তা জানার প্রয়োজন হয়,
তাহলে enum, constant বা ServiceSpecificException ব্যবহার করুন।
একইভাবে, অবজেক্টগুলি স্থিতিশীল এবং ব্যাকওয়ার্ড কম্প্যাটিবল না হলে, byte[] বা শেয়ার করা মেমরিতে সিরিয়ালাইজ করবেন না। কিছু ক্ষেত্রে, আপনি শেয়ার করা মেমরি ও ফাস্ট মেসেজ কিউতে পার্সেল করা যায় এমন ডেটা ও ইউনিয়ন শেয়ার করার জন্য @FixedSize
অ্যানোটেশন ব্যবহার করতে পারবেন।
ইন্টারফেস
১. নামকরণ
[-Winterface-name] ইন্টারফেসের নাম I দিয়ে শুরু হওয়া উচিত, যেমন IFoo।
২. আইডি-ভিত্তিক "অবজেক্ট" সহ বড় ইন্টারফেস এড়িয়ে চলুন
নির্দিষ্ট API সম্পর্কিত অনেক কল থাকলে, সাব-ইন্টারফেস ব্যবহার করুন। এর ফলে নিম্নলিখিত সুবিধাগুলি পাওয়া যায়:
- ক্লায়েন্ট বা সার্ভার কোড আরও সহজে বুঝতে সাহায্য করে
- অবজেক্টের লাইফসাইকেল আরও সহজ করে তোলে
- বাইন্ডার জাল করা যায় না বলে সুবিধা নেয়।
সাজেস্ট করা হয় না: আইডি-ভিত্তিক অবজেক্ট সহ একটি সিঙ্গেল, বড় ইন্টারফেস
interface IManager {
int getFooId();
void beginFoo(int id); // clients in other processes can guess an ID
void opFoo(int id);
void recycleFoo(int id); // ownership not handled by type
}
সাজেস্ট করা: স্বতন্ত্র ইন্টারফেস
interface IManager {
IFoo getFoo();
}
interface IFoo {
void begin(); // clients in other processes can't guess a binder
void op();
}
৩. একমুখী ও দ্বিমুখী পদ্ধতি মিশিয়ে দেবেন না
[-Wmixed-oneway] একমুখী পদ্ধতির সাথে অ-একমুখী পদ্ধতি মেশাবেন না, কারণ এটি ক্লায়েন্ট ও সার্ভারের জন্য থ্রেডিং মডেল বোঝা কঠিন করে তোলে। বিশেষ করে, কোনও নির্দিষ্ট ইন্টারফেসের ক্লায়েন্ট কোড পড়ার সময়, আপনাকে প্রতিটি পদ্ধতির জন্য দেখতে হবে যে সেই পদ্ধতিটি ব্লক করবে কিনা।
৪. স্ট্যাটাস কোড রিটার্ন করা এড়িয়ে চলুন
পদ্ধতিগুলি রিটার্ন ভ্যালু হিসেবে স্ট্যাটাস কোড এড়িয়ে চলা উচিত, কারণ সব AIDL পদ্ধতিতে
একটি অন্তর্নিহিত স্ট্যাটাস রিটার্ন কোড থাকে। ServiceSpecificException অথবা
EX_SERVICE_SPECIFIC দেখুন। কনভেনশন অনুযায়ী, এই ভ্যালুগুলি AIDL ইন্টারফেসে
কনস্ট্যান্ট হিসেবে সংজ্ঞায়িত করা হয়। সমস্যার পাশাপাশি কাস্টম বিলম্ব বা অনন্য সমস্যার ডেটা প্রয়োজন হলে, শুধুমাত্র সেই সময়েই কাস্টম রেসপন্স অবজেক্টে সমস্যা
দেখানো উচিত। আরও বিস্তারিত তথ্য পেতে, সমস্যা সমাধান দেখুন।
৫. আউটপুট প্যারামিটার হিসেবে অ্যারে ক্ষতিকর হিসেবে বিবেচিত হয়
[-Wout-array] অ্যারে আউটপুট প্যারামিটার আছে এমন মেথড, যেমন
void foo(out String[] ret) সাধারণত ভাল নয়, কারণ আউটপুট অ্যারের সাইজ অবশ্যই
জাভাতে ক্লায়েন্টকে ঘোষণা ও অ্যালোকেট করতে হবে এবং তাই অ্যারে
আউটপুটের সাইজ সার্ভার বেছে নিতে পারে না। এই অবাঞ্ছিত আচরণটি ঘটে কারণ
জাভাতে অ্যারে কীভাবে কাজ করে (সেগুলি আবার অ্যালোকেট করা যায় না)। এর পরিবর্তে String[] foo()-এর মতো API
ব্যবহার করুন।
৬. inout প্যারামিটার এড়িয়ে চলুন
[-Winout-parameter] এটি ক্লায়েন্টদের বিভ্রান্ত করতে পারে কারণ in প্যারামিটারগুলিও out প্যারামিটারের
মতোই দেখতে হয়।
৭. আউট এবং ইনআউট @nullable নন-অ্যারে প্যারামিটার এড়িয়ে চলুন
[-Wout-nullable] যেহেতু Java ব্যাকএন্ড @nullable অ্যানোটেশন হ্যান্ডেল করে না
কিন্তু অন্যান্য ব্যাকএন্ড করে, তাই out/inout @nullable T ব্যাকএন্ড জুড়ে
অসঙ্গতিপূর্ণ আচরণ করতে পারে। যেমন, জাভা নয় এমন ব্যাকএন্ড আউট @nullable
প্যারামিটারকে নাল হিসেবে সেট করতে পারে (C++-এ, এটিকে std::nullopt হিসেবে সেট করা) কিন্তু জাভা ক্লায়েন্ট
এটিকে নাল হিসেবে পড়তে পারে না।
৮. অনন্য অনুরোধ ও উত্তর ব্যবহার করা
প্রয়োজনীয় সব প্যারামিটারকে একটি ইনপুটে parcelable গ্রুপ করুন।
প্রতিটি ইন্টারফেস পদ্ধতির জন্য ডেডিকেটেড অনুরোধ ও উত্তর পার্সেলযোগ্য তৈরি করুন
প্রিমিটিভ পাস করার পরিবর্তে (যেমন, আলাদা
ভেরিয়েবল পাস করার পরিবর্তে
ComputeResponse compute(in ComputeRequest request) ব্যবহার করুন)। এর ফলে, ফাংশন সিগনেচার পরিবর্তন না করেই পরে নতুন আর্গুমেন্ট যোগ করা যায়।
এই প্যাটার্নটি তখনই সাজেস্ট করা হয় যখন মনে করা হয় যে
ভবিষ্যতে আরও প্যারামিটার যোগ করা হতে পারে অথবা কোনও পদ্ধতিতে ইতিমধ্যেই চারটির
বেশি প্যারামিটার আছে।
যেসব পদ্ধতিতে অতিরিক্ত ইনপুট বা আউটপুটের প্রয়োজন হয় না সেগুলি এই সাজেশন থেকে উপকৃত হবে না। প্রতিটি কেস সম্পর্কে স্পষ্টভাবে চিন্তা করা এবং ভবিষ্যতের পরিবর্তনের জন্য নমনীয় থাকা, কম বাতিল করা পদ্ধতি এবং ব্যাকওয়ার্ড-কম্প্যাটিবল কোডের জন্য কম জটিলতার দিকে নিয়ে যেতে পারে।
এই প্যাটার্ন ব্যবহার করে কোনও পদ্ধতি তৈরি করা না হলে, আপনি এই প্যাটার্নে পরিবর্তন করতে পারেন অনুরোধ ও উত্তর পার্সেলযোগ্য সহ একটি নতুন পদ্ধতি তৈরি করে এবং পুরনো পদ্ধতিটি বাতিল করে। যেমন:
void foo(int a, int b, int c); // original version, but deprecated in favor of the next version
void fooV2(in MyArg arg); // new version having int a, b, c, and d.
স্ট্রাকচার্ড পার্সেলযোগ্য
১. কখন ব্যবহার হবে
একাধিক ধরনের ডেটা পাঠানোর প্রয়োজন হলে স্ট্রাকচার্ড পার্সেলযোগ্য ডেটা ব্যবহার করুন।
অথবা, আপনার কাছে একটি ডেটার ধরন আছে কিন্তু আপনি আশা করেন যে ভবিষ্যতে আপনাকে
সেটি আরও বাড়াতে হবে। যেমন, String username ব্যবহার করবেন না। একটি
এক্সটেন্ডেবল পার্সেলযোগ্য ব্যবহার করুন, যেমন নিম্নলিখিত:
parcelable User {
String username;
}
যাতে ভবিষ্যতে আপনি এটি নিম্নলিখিতভাবে বাড়াতে পারেন:
parcelable User {
String username;
int id;
}
২. ডিফল্ট ভ্যালু স্পষ্টভাবে উল্লেখ করা
[-Wexplicit-default, -Wenum-explicit-default] Provide explicit defaults for fields. পার্সেলেবলে নতুন ফিল্ড যোগ করা হলে, পুরনো ক্লায়েন্ট ও সার্ভার সেগুলি বাদ দেয়, কিন্তু নতুন ক্লায়েন্ট ও সার্ভারের জন্য ডিফল্ট ভ্যালু অটোমেটিক পূরণ হয়ে যায়।
৩. ভেন্ডর এক্সটেনশনের জন্য ParcelableHolder ব্যবহার করা
আপনি যদি এমন কোনও AOSP parcelable নির্ধারণ করেন যা ডিভাইস ইমপ্লিমেন্টারদের বাড়াতে হবে,
তাহলে আপনার অবজেক্টে ParcelableHolder-এর একটি ইনস্ট্যান্স এম্বেড করুন। এটি মার্জ কনফ্লিক্ট তৈরি না করেই
এক্সটেনশন পয়েন্ট হিসেবে কাজ করে। এটি
অ্যাটাচ করা ইন্টারফেস এক্সটেনশনের
মতোই, তবে এটি ইমপ্লিমেন্টকারীদের নিজস্ব ইন্টারফেস ও ধরন তৈরি না করেই
আগে থেকে থাকা parcelable-এর সাথে তাদের মালিকানাধীন parcelable অন্তর্ভুক্ত করার অনুমতি দেয়।
৪. ডেটা স্ট্রাকচার
- ম্যাপের জন্য অ্যারে বা পার্সেলযোগ্য
Listব্যবহার করুন, কারণ AIDL নেটিভ ব্যাকএন্ডে নিরাপদে ট্রান্সলেট করা যায় এমনMapটাইপকে নেটিভভাবে সাপোর্ট করে না (যেমন,FeatureToScoreEntry[])। - ভবিষ্যতে প্যারালাল অ্যারের প্রয়োজনীয়তা এড়াতে, রিপিট করা ফিল্ডের জন্য
প্রিমিটিভের অ্যারের পরিবর্তে
parcelableঅবজেক্টের অ্যারে ব্যবহার করুন। - IPC-এর মাধ্যমে সিরিয়ালাইজ করা স্ট্রিং বা JSON-এর পরিবর্তে স্ট্রংলি টাইপ করা
parcelableঅবজেক্ট ব্যবহার করুন। - ভবিষ্যতে আরও যোগ করার জন্য, স্ট্যাটাসের ক্ষেত্রে বুলিয়ানের পরিবর্তে এনাম ব্যবহার করুন। বিটমাস্কের
জন্য, কিছু ব্যাকএন্ডে জটিল কাস্টিং এড়াতে
enumধরনের পরিবর্তেconst intব্যবহার করুন।
ননস্ট্রাকচার্ড পার্সেলযোগ্য আইটেম
১. কখন ব্যবহার হবে
Java-তে
@JavaOnlyStableParcelable-এর সাথে এবং NDK ব্যাকএন্ডে
@NdkOnlyStableParcelable-এর সাথে নন-স্ট্রাকচার্ড পার্সেলযোগ্য উপলভ্য। সাধারণত, এগুলি হল পুরনো ও আগে থেকে থাকা পার্সেলযোগ্য আইটেম
যেগুলিকে স্ট্রাকচার করা যায় না।
কনস্ট্যান্ট ও এনুম
১. বিটফিল্ডে কনস্ট্যান্ট ফিল্ড ব্যবহার করা উচিত
বিটফিল্ডে কনস্ট্যান্ট ফিল্ড ব্যবহার করা উচিত (যেমন, কোনও
ইন্টারফেসে const int FOO = 3;)।
২. Enum-এর সেট বন্ধ করা উচিত।
Enum-এর সেট বন্ধ করা উচিত। মনে রাখবেন: শুধুমাত্র ইন্টারফেসের মালিকই enum এলিমেন্ট যোগ করতে পারবেন। ভেন্ডর বা OEM-দের এইসব ফিল্ডের মেয়াদ বাড়াতে হলে, বিকল্প মেকানিজম প্রয়োজন। সম্ভব হলে, আপস্ট্রিম ভেন্ডর ফাংশনালিটিকে অগ্রাধিকার দেওয়া উচিত। তবে, কিছু ক্ষেত্রে, কাস্টম ভেন্ডর ভ্যালু অনুমোদিত হতে পারে (যদিও, ভেন্ডরদের কাছে এটির ভার্সন করার জন্য একটি মেকানিজম থাকা উচিত, সম্ভবত AIDL নিজেই, তাদের একে অপরের সাথে বিরোধ করা উচিত নয় এবং এই ভ্যালুগুলি থার্ড-পার্টি অ্যাপে প্রকাশ করা উচিত নয়)।
৩. "NUM_ELEMENTS"-এর মতো ভ্যালু এড়িয়ে চলুন
যেহেতু enum-এর ভার্সন আছে, তাই কতগুলি ভ্যালু আছে তা নির্দেশ করে এমন ভ্যালু
এড়িয়ে যাওয়া উচিত। C++-এ, enum_range<>-এর মাধ্যমে এই সমস্যার সমাধান করা যেতে পারে। Rust-এর জন্য
enum_values() ব্যবহার করুন। Java-তে এখনও কোনও সমাধান নেই।
সাজেস্ট করা হয় না: সংখ্যাসূচক ভ্যালু ব্যবহার করা
@Backing(type="int")
enum FruitType {
APPLE = 0,
BANANA = 1,
MANGO = 2,
NUM_TYPES, // BAD
}
৪. অপ্রয়োজনীয় উপসর্গ ও প্রত্যয় এড়িয়ে চলুন
[-Wredundant-name] কনস্ট্যান্ট ও এনুমেরেটরে অপ্রয়োজনীয় বা একাধিকবার ব্যবহৃত উপসর্গ ও প্রত্যয় এড়িয়ে চলুন।
সাজেস্ট করা হয় না: অপ্রয়োজনীয় প্রিফিক্স ব্যবহার করা
enum MyStatus {
STATUS_GOOD,
STATUS_BAD // BAD
}
সাজেস্ট করা হয়েছে: সরাসরি enum-এর নাম দেওয়া
enum MyStatus {
GOOD,
BAD
}
FileDescriptor
[-Wfile-descriptor] AIDL ইন্টারফেস পদ্ধতির আর্গুমেন্ট বা রিটার্ন ভ্যালু হিসেবে
FileDescriptor-এর ব্যবহার একেবারেই বাঞ্ছনীয় নয়। বিশেষ করে, যখন
AIDL জাভাতে প্রয়োগ করা হয়, তখন এটি ফাইল ডেসক্রিপটর লিক করতে পারে, যদি না
যত্ন সহকারে ম্যানেজ করা হয়। সহজভাবে বলতে গেলে, আপনি কোনও FileDescriptor-এ সম্মতি জানালে, সেটি আর ব্যবহার না করা হলে আপনাকে
ম্যানুয়ালি বন্ধ করতে হবে।
নেটিভ ব্যাকএন্ডের ক্ষেত্রে, আপনি সুরক্ষিত কারণ FileDescriptor unique_fd
এর সাথে ম্যাপ করা হয় যা অটোমেটিক বন্ধ করা যায়। তবে আপনি যে ব্যাকএন্ড ভাষাই ব্যবহার করুন না কেন,
FileDescriptor একেবারেই ব্যবহার না করাই ভাল, কারণ এটি ভবিষ্যতে ব্যাকএন্ড ভাষা পরিবর্তন করার
স্বাধীনতা সীমিত করে দেবে।
পরিবর্তে, ParcelFileDescriptor ব্যবহার করুন, যা অটোমেটিক বন্ধ হয়ে যায়।
পরিবর্তনযোগ্য ইউনিট
নামে যেন ভেরিয়েবল ইউনিট অন্তর্ভুক্ত থাকে, যাতে সেগুলির ইউনিট ভালভাবে সংজ্ঞায়িত ও বোঝা যায় এবং তার জন্য ডকুমেন্টেশন রেফার করার প্রয়োজন না হয়
উদাহরণ
long duration; // Bad
long durationNsec; // Good
long durationNanos; // Also good
double energy; // Bad
double energyMilliJoules; // Good
int frequency; // Bad
int frequencyHz; // Good
টাইমস্ট্যাম্পে অবশ্যই রেফারেন্স উল্লেখ করতে হবে
টাইমস্ট্যাম্পে (আসলে, সব ইউনিটে!) অবশ্যই ইউনিট ও রেফারেন্স পয়েন্ট স্পষ্টভাবে উল্লেখ করতে হবে।
উদাহরণ
/**
* Time since device boot in milliseconds
*/
long timestampMs;
/**
* UTC time received from the NTP server in units of milliseconds
* since January 1, 1970
*/
long utcTimeMs;
কনকারেন্সি ও অ্যাসিঙ্ক্রোনাস অপারেশন
ব্লকিং এড়াতে অ্যাসিঙ্ক্রোনাস (oneway) ইন্টারফেসের মাধ্যমে
দীর্ঘ সময় ধরে চলা অপারেশন ম্যানেজ করুন।
কোনও পরিষেবা যদি তার ক্লায়েন্টকে বিশ্বাস না করে, তাহলে ক্লায়েন্টের থেকে পাওয়া যেকোনও কলব্যাক
oneway ইন্টারফেস হতে হবে। এর ফলে ক্লায়েন্টরা অনির্দিষ্টকালের জন্য পরিষেবা ব্লক করতে
পারেন না।
ফরোয়ার্ড কল, ইনপুট আর্গুমেন্ট ও ফলাফল পাওয়ার জন্য কলব্যাক ইন্টারফেস সহ অ্যাসিঙ্ক্রোনাস API স্ট্রাকচার করুন। যুক্তি সংক্রান্ত সাজেশন পেতে অনন্য অনুরোধ ও উত্তর ব্যবহার করুন দেখুন।