در بسیاری از مواقع هنگام طراحی API برای پروژه، توسعه دهندگان اهمیت زیادی به تمیز بودن ساختار طراحی، مفهومی بودن و مقیاس پذیری آن نمی دهند. اما در طولانی مدت و با بزرگ تر شدن پروژه این موضوع باعث به وجود آمدن مشکلاتی خواهد شد.
فرض کنید زمان آن رسیده است که API های نوشته شده را برای کاربران به اشتراک بگذارید تا از آن ها استفاده کنند. چطور می توانید مطمئن باشید که آن ها دقیقا همان چیزی که مد نظر شماست را مشاهده می کنند؟ این مساله نه تنها برای کاربران بلکه برای توسعه دهندگانی که قصد توسعه API های نوشته شده توسط شما را دارند صدق می کند. بنابراین ضروری است که در ابتدای ساخت API ها الگوی طراحی مناسبی برای این کار انتخاب شود تا تمامی افراد (کاربران و توسعه دهندگان) از آن پیروی کنند.
در این مقاله به بررسی چند نکته کاربردی برای توسعه هرچه بهتر این API ها می پردازیم.
1. استفاده از متدهای HTTP برای معنا دادن به endpoint ها:
REST API ما را تشویق می کند تا از متدهای HTTP
برای ساخت هر کدام از عملیات های مربوط به CRUD استفاده کنیم. در میان این متدها، مواردی مانند GET
، POST
، PUT
، PATCH
، DELETE
معنای خاصی به endpoint های ما می دهد و به طور مثال مشخص می کند که این endpoint مربوط به ساخت یک موجودیت جدید است یا حذف یک موجودیت از پیش ساخته شده. همچنین با استفاده از این متدها دیگر نیازی به مشخص کردن عملیات در هنگام تعریف نام برای endpoint ها نیست. مثال زیر گویای مزایای استفاده از این متدهاست.
- GET /get_cats
- POST /insert_cats
- PUT /modify_cats
- DELETE /delete_cats
+ GET /cats
+ POST /cats
+ PUT /cats
+ DELETE /cats
2. استفاده از کدهای status مربوط به HTTP بر اساس نتیجه ی درخواست ارسالی:
یکی از مهم ترین موارد در طراحی API ها استفاده درست از status code
بر اساس نتیجه ی درخواست ارسالی است. این بدان معنی است که هنگامی که عملیات موفقیت آمیز بوده یا با خطا روبرو شود می توان با استفاده از status code
ها این مفهوم را به کاربر منتقل کرد.
برای مثال اگر ما 200 را به عنوان status code
دریافت کنیم، می توان فهمید که نتیجه ی عملیات درخواستی موفقیت آمیز بوده است و اگر 400 را دریافت کنیم، عملیات مورد نظر با خطا روبرو شده است.
بنابراین مهم است که با status code
های مختلف آشنایی داشته و از هرکدام در زمان مناسب با توجه به نتیجه ی عملیات استفاده شود چرا که در غیر این صورت باعث سردرگمی کاربران و توسعه دهندگان و در برخی موارد باعث استفاده نادرست از آن می شود. به طور مثال نمونه استفاده ی درست و نادرست از status code
در زیر ذکر شده است.
// Bad, we return status code 200 (Success)
// associated with an error object
{
"status": 200,
"error": {...}
}
// Good
{
"status": 200,
"data": [...]
}
3. پشتیبانی از filter، sort و pagination:
در بسیاری از مواقع نیاز است تا تعداد اطلاعات دریافتی از API محدود شود. این محدودیت می تواند به دلایلی مانند بهبود سرعت انجام عملیات ها، کاهش تعداد اطلاعات دریافتی، جستجوی دریافت اطلاعات خاص و ... باشد.
افزودن filter
، sort
و pagination
علاوه بر دستیابی به کاربرد خاص خودشان، می تواند باعث کاهش فشار بر روی سرور شود.
به طور مثال فرض کنید در پایگاه داده، میلیون ها داده داریم، حال اگر کاربر تمام این اطلاعات را یک جا درخواست کند به یقین سرور فشار زیادی را متحمل می شود! اما با استفاده از ساختارهای sort
و filter
و pagination
این مشکل مرتفع خواهد شد. به طور مثال می توان به صورت زیر از این عملیات ها استفاده کرد:
- GET /cats?page=2
- GET /cats?page=3&per_page=20
- GET /cats?page=2&sort=desc
4. نام گذاری endpoint ها به صورت جمعی:
از آنجایی که معمولا resource
ها دارای یک داده نیستند و بیشتر مواقع آن ها به صورت جمعی هستند بهتر است از نام جمعی برای endpoint ها استفاده شود.
- GET /cat
- GET /cat/:id
+ GET /cats
+ GET /cats/:id
5. نام گذاری endpoint ها را بر اساس resource:
اگر یک route پروژه عملیاتی را روی resource
خاصی انجام می دهد، باید نام endpoint
مربوط به آن با نام resource
مورد نظر یکی باشد. این مسئله باعث ثبات و منظم بودن پروژه خواهد شد. بنابراین هنگامی که یک کاربر یا توسعه دهنده از API های ما استفاده کند متوجه کاربرد هر یک از route ها خواهد شد. به طور مثال اگر یک route قرار است عملیات مربوط به موجودیت Cat
را انجام دهد نباید به صورت /dogs
تعریف شود.
6. استفاده از route های سلسله مراتبی برای عملیات مربوط به روابط بین موجودیت ها:
فرض کنید بین موجودیت های مختلف در پروژه رابطه وجود دارد. به طور مثال اگر بخواهیم لیست موجودیت های (مثلا posts) مربوط به یک موجودیت دیگر (مثلا user) را دریافت کنیم دو گزینه پیش رو خواهیم داشت. یکی استفاده از ساختار سلسله مراتبی و دیگری استفاده از query string
:
GET /users/alireza/posts/post-about-api-design
GET /posts?user=alireza&name=post-about-api-design
این روش ها در پروژه های مختلفی استفاده می شوند و استفاده از هر دو روش صحیح است. روش اول باعث استفاده بهتر از ساختار route ها می شود اما در زمانی که تعداد روابط زیاد باشد روش اول باعث طولانی شدن نام مسیرها شده و روش دوم عملکرد بهتری خواهد داشت. این بستگی به ساختار پروژه شما دارد که از کدام روش بهتر است استفاده کنید.
7. نسخه گذاری API ها:
به عنوان توسعه دهنده مهم است تا API هایی تعریف کنیم که بدون خطا باشند و به درستی کار کنند. فرض کنید API خود را طراحی کرده ایم و بر روی یک سرور قرار داده ایم. تعداد زیادی از کاربران از این API ها استفاده می کنند. حال چه اتفاقی خواهد افتاد اگر نیاز باشد تا بخشی از داده های این API را تغییر داده، اضافه یا کم کنید؟ احتمالا با این کار شما تعداد زیادی از کاربران دیگر قادر به استفاده از API شما نخواهند بود. بنابراین نیاز است تا برای API خود نسخه بندی در نظر بگیرید. روش های مختلفی برای نسخه گذاری API وجود دارد که می توان برای مثال به موارد زیر اشاره کرد:
// URI versioning v[x] syntax
GET /v1/cats
GET /v2/dogs
GET /v3/birds
8. استفاده از سیستم caching:
یکی از ویژگی های مثبت هر API، سرعت پاسخ دهی بالای آن است. برای دست یابی به آن می توان از caching
استفاده کرد. این کار نه تنها باعث افزایش سرعت پاسخ دهی API می شود، بلکه فشار روی سرور را نیز کاهش می دهد. چرا که با این کار نیاز به دست یابی به دیتابیس برای دریافت داده های تکراری کمتر خواهد شد. سرویس های بسیاری برای این کار وجود دارد که یکی از محبوب ترین آن ها Redis
است.
این کار ممکن است باعث افزایش هزینه نگه داری API ها شود اما این مسئله یک نقص نیست! چرا که هزینه ی دست یابی به اطلاعات دیتابیس ممکن است در مواردی بیشتر از هزینه caching
باشد. از طرفی می توان با کم کردن زمان caching
این مسئله را بهبود داد.
9. مستندسازی:
یکی از بهترین سلاح ها و در کنار آن منفورترین کارها! در بین توسعه دهندگان مستندسازی است. در این میان مستندسازی API مستثنا نیست و یکی از ضروریات در طراحی API، مستندسازی آن است. با مستندسازی کاربران این امکان را خواهند داشت تا درباره ی API اطلاعاتی را به دست آورند که این اطلاعات شامل نوع دسترسی به آن (accessibility)، نوع درخواست و اطلاعات آن (request)، نوع پاسخ و اطلاعات آن(response)، مثال ها و ... باشد.
• دسترسی: یکی از مهم ترین ویژگی های مستند نحوه دسترسی به آن است. بهترین روش برای مستندسازی، ساخت یک مستند و ارائه آن بر روی اینترنت است. با این روش تمام کاربران قادر به مشاهده مستندها خواهند بود.
• درخواست و پاسخ: اطلاعاتی که در این قسمت قرار می گیرد باید نوع و اطلاعات موجود در درخواست و پاسخ را مشخص کند.
• مثال ها: اگر برای کاربران مثال هایی برای استفاده از هر یک از API ها آورده شود بسیار مفید خواهد بود.
نتیجه گیری:
در نظر داشته باشید که API طراحی شده، راه ارتباطی کاربران با سرویس ساخته شده توسط backend است. در این صورت باید دقت کرد که در طراحی آن بهترین اصول را رعایت کنیم تا کاربران به راحتی بتوانند از آن استفاده کنند. حتی اگر در حال توسعه یک پروژه شخصی هستید پیشنهاد می شود که این اصول را در پروژه خود به کار ببرید. چرا که هزینه ی نگه داری و توسعه ی آن در آینده کاهش پیدا می کند. همچنین این کار باعث تمرین بیشتر شما برای مشارکت در پروژه های بزرگ تر خواهد شد.
سکان آکادمی امیدوار است این مقاله مورد استفاده شما قرار گرفته باشد و از این پس در طراحی سرویس های خود، تجربه بهتری داشته باشید.
پاینده و سربلند باشید