در آموزش گذشته، با مفهوم ریسورس آشنا شدیم. اساساً یکسری به اصطلاح Best Practice در نحوهٔ نامگذاری ریسورسها وجود دارد که با پیروی از آنها میتوانیم وب سرویسی در اختیار سایر توسعهدهندگان قرار دهیم که با کمترین میزان سردرگمی شروع به استفاده از آن کنند که در ادامه با برخی از مهمترین آنها آشنا خواهیم شد.
استفاده از Noun به جای Verb در نامگذاری ریسورسها
به طور کلی، به منظور نامگذاری ریسورسها میباید به جای افعال، از اسامی استفاده کرد اما پیش از توضیح بیشتر پیرامون این موضوع، نیاز است تا ریسورسها را بر اساس ماهیتی که دارند تقسیمبندی کنیم.
Collection به مجموعهای از ریسورسهای مرتبط به هم اشاره دارد که برای نامگذاری آنها باید از اسامی جمع استفاده کرد به طوری که داریم:
GET http://example.com/api/users
برخی دولوپرها اقدام به مشخص کردن فرمت خروجی در یوآرآی میکنند به طوری که مثلاً داریم:
GET http://example.com/api/users.json
همانطور که میبینیم، پسوند json.
به انتهای نام ریسورس اضافه شده است. در چنین مواقعی میباید شرایطی در کد لحاظ گردد که اگر کاربر ایپیای پسوندی را مشخص نکرد، فرمت پیشفرضی در نظر گرفته شود.
یک ریسورس از جنس Document اصولاً به یک رکورد در دیتابیس اشاره دارد که برای ریسورسهایی از این دست میباید از اسامی مفرد یا یک شناسه استفاده کرد:
GET http://example.com/api/users/1
در واقع، از آنجا که یک کاربر خاص به عنوان بخشی از کلیهٔ کاربران است، با درج شناسه میتوانیم به دادههای وی دست یابیم. حال فرض کنیم که قصد داریم یک یوآرآی داشته باشیم که با استفاده از آن کاربر بتواند یک مقالهٔ جدید ایجاد کند. یکی از راههای عملی کردن این ریکوئست عبارت است از:
POST http://example.com/api/users/1/articles
در واقع، در مثال فوق قصد داریم تا برای کاربری با شناسهٔ ۱ مقالهای ثبت کنیم. حال اگر همین یوآرای را با متد GET
به صورت زیر فراخوانی کنیم:
GET http://example.com/api/users/1/articles
کلیهٔ مقالات کاربری با شناسهٔ ۱ ریترن خواهد شد.
استفاده از / به منظور نشان دادن سلسلهمراتب
کاراکتر /
به منظور نشان دادن ارتباط سلسلهمراتبی مابین ریسورسها مورد استفاده قرار میگیرد:
GET http://api.example.com/device-management/managed-devices
همانطور که ملاحظه میشود، یک ریسورس اصلی داریم به نام device-management
که زیرشاخهاش ریسورس managed-devices
است که با یک /
از هم جدا شدهاند.
عدم استفاده از / در انتهای URI
به عنوان یک قانون کلی، باید سعی کنیم که در انتهای یوآرای یا لینکی که برای ریسورس مد نظر خود در نظر گرفتهایم، هرگز از /
استفاده ننماییم. به عبارت دیگر، به جای لینک زیر:
GET http://api.example.com/device-management/managed-devices/
میباید از لینک زیر استفاده کنیم:
GET http://api.example.com/device-management/managed-devices
همانطور که میبینیم، در لینک فوق /
پایانی حذف گردیده است تا منجر به ایجاد سردرگمی برای توسعهدهندهای که از این ایپیآی استفاده میکند نگردد.
استفاده از - به منظور افزایش خوانایی
با توجه به اینکه خوانایی ایپیآی یک اصل مهم و کلیدی است، میباید به منظور دستیابی به این مهم از علامت -
به منظور مجزاسازی نام ریسورسها استفاده کرد:
GET http://api.example.com/deviceManagement/managedDevices
به طوری که به عنوان نسخهٔ خواناتر یوآرآی فوق داریم:
GET http://api.example.com/device-management/managed-devices
همانطور که میبینیم، مجزا کردن واژگان با استفاده از علامت -
منجر به خوانایی بیشتر آنها میگردد. همچنین لازم به یادآوری است که به جای -
میتوان از علامت _
نیز استفاده نمود اما این احتمال وجود دارد که بسته به نوع فونت انتخابی، این علامت از دید کاربر پنهان مانده و یا در برخی صفحهنمایشها به خوبی نماش داده نشود و از همین روی استفاده از _
خیلی توصیه نمیشود.
استفاده از حروف کوچک
در نامگذاری ریسورسها بهتر آن است که همواره از حروف کوچک استفاده نماییم و این اصل را در تمامی مراحل توسعهٔ ایپیآی حفظ کنیم:
GET http://api.example.com/Device-Management/MANAGED-DEVICES
همانطور که میبینیم، استفاده از حروف بزرگ خوانایی را پایین میآورد و از همین روی بهتر است که همواره از حروف کوچک استفاده کرد.
عدم استفاده از فایل اِکستنشن
درج پسوند فایلها صرفاً منجر به افزایش طول یوآرآی میگردد مضاف بر اینکه کمکی به درک بهتر اِندپیونت مذکور نمیکند:
GET http://api.example.com/device-management/managed-devices.xml
در عوض، بهتر است که از معادل زیر استفاده کنیم:
GET http://api.example.com/device-management/managed-devices
میبینیم که اِندپوینت فوق خواناتر و در عین حال کوتاهتر است.
استفاده از کوئری به منظور فیلتر کردن ریسورسها
گاهی اوقات بسته به نیازهای نرمافزاری خود نیاز داریم تا با اِعمال فیلتر، دادههای خاصی را از سرور فراخوانی کنیم که در چنین مواقعی اصلاً نیاز به افزودن اِندپوینتهای جدید نداریم بلکه با افزودن کوئری (پارامتر) به انتهای لینک میتوانیم به نیاز خود دست یابیم:
GET http://api.example.com/device-management/managed-devices?region=USA
همانطور که ملاحظه میشود، با درج علامت ?
و قرار دادن یک جفت Key/Value میتوانیم پارامترهای مد نظر خود را ارسال کرده و در سمت بکاند این پارامتر را در نوع کوئری زدن به دیتابیس دخیل کرده و به دادههای مد نظر خود دست یابیم.
اساساً استفاده از پارامتر به منظور فیلتر کردن دیتا استراتژی خوبی میباشد اما این در حالی است که چنانچه به روش زیر عمل کنیم:
GET http://example.com/api?type=user&id=1
همانطور که میبینیم، با استفاده از یکسری پارامتر ریسورس خاصی را فِچ (فراخوانی) کردهایم که این روش در معماری رِست اصلاً توصیه نمیشود.
درآمدی بر Pagination در توسعهٔ RESTful API
زمانی که با دیتاسِتهای بزرگ سروکار داشته باشیم، مسلماً نمیتوانیم تمامی دیتای مذکور را در قالب یک ریسپانس در اختیار کاربر قرار دهیم بلکه نیاز است تا دیتا را به صورت اصطلاحاً Chunk by Chunk یا «تکهتکه» در اختیار کاربر قرار دهیم و اینجا است که باید با مفهومی تحت عنوان Pagination یا «صفحهبندی» آشنا شویم.
همانطور که در لینک تمامی مقالات وبلاگ مشاهده میشود، در انتهای صفحه مجموعه لینکهایی قرار داده شده که کلیهٔ مقالات وبلاگ سکان آکادمی در قالب یکسری صفحه در معرض دید کاربر قرار داده شده که وی با کلیک روی هر کدام از آنها، میتواند تعداد مشخصی از مقالات را مشاهده کند.
در توسعهٔ رِست ایپیآی هم از طریق اصطلاحاً Query-String Parameter میتوان دست به صفحهبندی دادههای درخواستی کرد به طوری که مثلاً داریم:
GET https://example.com/api/articles?offset=0&limit=25
همانطور که ملاحظه میشود، در مثال فوق ریکوئستی از جنس GET
ارسال شده تا ریسورسی تحت عنوان articles
را دریافت کند اما برای فیلتر کردن دیتای مذکور، از یکسری پارامتر استفاده شده که با درج علامت ?
در انتهای یوآرال شروع شدهاند. مقادیر offset
و limit
قراردادی هستند و بسته به نیاز خود میتوانید نامهای دلخواه دیگری نیز استفاده نمایید.
در واقع، پارامتر offset
نقطهٔ شروع فِچ کردن دیتا را مشخص میسازد و limit
هم تعداد ریسورسها از آن نقطه به بعد را نشان میدهد به طوری که در مثال فوق، به وب سرور دستور دادهایم تا از نقطهٔ ۰ (یعنی اولین مقاله) تعداد ۲۵ ریسورس را در اختیارمان قرار دهد.
اساساً یکی از راههای یادگیری روشهای درست انجام کاری، دنبال کردن راهی است که برندهای مطرح این صنعت دنبال میکنند که در همین راستا توصیه میکنیم به لینکهای زیر که مرتبط با مستندات ایپیآی شرکتهای توییتر و اینستاگرام است مراجعه نمایید:
- Twiter API Reference
- Instagram API Reference
آشنایی با یکسری Anti Pattern در نامگذاری ریسورسها
به طور کلی، منظور از اصطلاح Anti Pattern یکسری روشهای اشتباه است که دولوپرها در توسعهٔ نرمافزار استفاده میکنند که در ادامه قصد داریم تا برخی از آنها در پروسهٔ نامگذاری در فرآیند توسعهٔ RESTful API را برشمریم.
پیش از این هم اشاره کردیم که استفاده از پارامترها برای فیلتر کردن دیتا مناسب است اما به منظور دستیابی به یک ریسورس خاص روش مناسبی نیست:
GET http://example.com/api/services?op=update_customer&id=12345&format=json
با استفاده از یوآرال فوق، قصد داریم تا یک تَسک آپدیت انجام دهیم که به طور معمول برای این منظور از متد PUT
استفاده میشود اما این در حالی است که در مثال فوق از متد GET
استفاده شده که معمولاً برای فراخوانی دیتا مورد استفاده قرار میگیرد. به عنوان مثال اشتباه دیگری نیز میتوان یوآرال زیر را مد نظر قرار داد:
GET http://example.com/api/customers/12345/update
با توجه به اینکه پیش از این گفتیم در نامگذاری این معماری به جای افعال میباید از اسامی استفاده کرد، درج update
در یوآلال فوق غیرضروری است چرا که صرفاً با استفاده از متد اچتیتیپی مناسب، که در این مثال PUT
است، میتوانیم به مقصود خود برسیم:
PUT http://example.com/api/customers/12345/update
این مثال کماکان مشکل دارد چرا که کلمهٔ update
منجر به سردرگمی توسعهدهنده خواهد شد تا جایی که به منظور بهبود آن میتوان یوآرال زیر را در نظر گرفت:
PUT http://example.com/api/customers/12345
پیش از این گفتم که باید از اسامی جمع برای ریسورسها استفاده نماییم اما ممکن است این سؤال پیش آید که «آیا میتوان گاهی از اسامی مفرد نیز استفاده کرد؟» که پاسخ به این پرسش «آری» است به طوری که مثلاً داریم:
GET|PUT|DELETE http://example.com/api/customers/12345/configuration
با توجه به اینکه هر یوزر فقط و فقط یک کانفیگ (پیکربندی یا تنظیمات) دارا است، پس دیگر لزومی ندارد که این ریسورس را به صورت جمع و به شکل configurations
استفاده کنیم. همچنین لازم به یادآوری است با توجه به اینکه هر کاربر فقط یک کانفیگ میتواند داشته باشد، پس استفاده از متد POST
که به منظور ایجاد ریسورس جدید است برای چنین اندپوینتی میباید محدود گردد.