ویرگول
ورودثبت نام
ابوالفضل وکیلی
ابوالفضل وکیلیinstagram : @a_vakily7
ابوالفضل وکیلی
ابوالفضل وکیلی
خواندن ۹ دقیقه·۶ ماه پیش

چگونه API ها را نسخه بندی کنیم؟

این روزها APIها در همه‌جا حضور دارند و اگر بخواهید سیستمی بسازید، بی‌تردید به موفقیت شما گره خورده‌اند. اما وقتی API تغییر می‌کند یا یکی از مصرف‌کنندگان درخواست افزودن قابلیت جدیدی را مطرح می‌کند چه اتفاقی می‌افتد؟ اینجاست که موضوع نسخه‌بندی (Versioning) به میان می‌آید.

سرفصل‌ها به این شرح‌اند:

  • چرا و چه زمانی باید APIهایتان را نسخه‌بندی کنید؟

  • استراتژی‌های نسخه‌بندی

  • روش‌های پیاده‌سازی

  • نسخه‌بندی معنایی (Semantic Versioning)

  • مدیریت چرخه عمر API

  • ابزارها


چرا و چه زمانی باید APIهایتان را نسخه‌بندی کنید؟

با رشد و تکامل یک نرم‌افزار، ناگزیر نیاز خواهید داشت تغییراتی در APIهای خود ایجاد کنید؛ افزودن قابلیت‌های جدید، رفع باگ‌ها، یا بهبود عملکرد. اما به‌محض اینکه توسعه‌دهندگان دیگر شروع به ساختن اپلیکیشن‌هایی کنند که به API شما وابسته است، هر تغییری ممکن است کدهای آن‌ها را مختل کند. اینجاست که نسخه‌بندی API اهمیت حیاتی پیدا می‌کند.

تصور کنید API‌ای ساخته‌اید که بسیاری از وب‌سایت‌ها برای نمایش داده‌های مالی روی داشبوردهایشان از آن استفاده می‌کنند. فعلاً مقادیر را به دلار (USD) بازمی‌گرداند، اما تصمیم گرفته‌اید واحد یورو (EUR) را هم اضافه کنید. اگر بدون نسخه‌بندی، فرمت پاسخ را تغییر دهید، ممکن است اپلیکیشن‌هایی که به فرمت قبلی وابسته‌اند دچار مشکل شوند.

البته، لازم نیست با هر تغییر کوچک، یک نسخه جدید از API ارائه دهید. اما برای تغییرات مخربی که می‌تواند اپلیکیشن‌های موجود را بشکند، حتماً باید نسخه جدیدی تعریف کنید. نمونه‌هایی از این تغییرات عبارت‌اند از: حذف یا تغییر نام فیلدهای پاسخ، اضافه کردن پارامترهای اجباری جدید، یا تغییر نحوه عملکرد اساسی یک endpoint.

از سوی دیگر، تغییراتی که باعث شکستن API نمی‌شوند، نیازمند نسخه‌بندی نیستند؛ مثل اضافه کردن فیلدهای اختیاری به پاسخ یا بهینه‌سازی عملکرد API بدون تغییر در نحوه استفاده کلاینت‌ها.

در مثال API مالی، اضافه کردن یک فیلد اختیاری برای یورو (EUR) آسیبی به اپلیکیشن‌های موجود که فقط از دلار استفاده می‌کنند نمی‌زند. اما اگر فیلد Dollars را به «currency» تغییر دهید، اپلیکیشن‌هایی که به نام قبلی وابسته‌اند دچار مشکل خواهند شد.

البته نسخه‌بندی بی‌رویه هم دردسرساز است. نگهداری هر نسخه جدید هزینه‌های توسعه و تست را افزایش می‌دهد و تعدد نسخه‌ها ممکن است توسعه‌دهندگان را در انتخاب نسخه مناسب سردرگم کند.

پس باید رویکرد نسخه‌بندی دقیقی داشته باشید؛ رویکردی که تعادل میان ثبات و قابلیت‌های جدید را برقرار کند. هدف این است که API خود را ارتقاء دهید بدون آنکه کاربران را در این مسیر به دردسر بیندازید.


استراتژی‌های نسخه‌بندی

برای مدیریت تغییرات در APIها معمولاً دو رویکرد اصلی وجود دارد: استراتژی تغییرات افزایشی (Additive Change) و استراتژی نسخه‌بندی صریح (Explicit Versioning).

استراتژی تغییرات افزایشی:

در این روش، شما صرفاً ویژگی‌ها و فیلدهای جدیدی به API اضافه می‌کنید، بدون آنکه به ساختار فعلی آسیبی وارد شود. تغییراتی که باعث ناسازگاری با نسخه‌های قبلی می‌شود (مثل حذف یا تغییر نام فیلدها، تغییر نوع داده‌ها یا کدهای خطا، یا تغییر اساسی در رفتار endpointها) ممنوع است.

کارهایی که مجاز هستند شامل موارد زیر می‌شود:

  • افزودن فیلدهای جدید (مشروط به اینکه اختیاری باشند)

  • اضافه کردن endpointهای جدید

  • افزودن پارامترهای opt-in برای فعال کردن قابلیت‌های جدید

بیایید با یک مثال ببینیم چطور این روش عمل می‌کند. فرض کنید API مالی شما چنین پاسخی برمی‌گرداند:

{ "stock": "AAPL", "price": ۱۵۰.۲۵, "currency": "USD", "market_cap": ۲۵۰۰۰۰۰۰۰۰ }

بعد از مدتی متوجه می‌شوید که برخی کاربران به اطلاعات ارزش بازار (market_cap) نیازی ندارند و این فیلد باعث بار اضافه روی شبکه آن‌ها می‌شود. طبق استراتژی افزایشی نمی‌توانید این فیلد را حذف کنید، چون برخی کلاینت‌ها به آن وابسته‌اند.

اما می‌توانید یک پارامتر اختیاری مثل exclude_market_cap=true اضافه کنید. در این حالت، کلاینت‌هایی که می‌خواهند بار شبکه را کاهش دهند می‌توانند از این پارامتر استفاده کنند و دیگران لازم نیست تغییری بدهند.

استراتژی افزایشی برای APIهای کوچک که تغییرات زیادی ندارند مناسب است. اما هرچه API بزرگ‌تر و پیچیده‌تر شود، حفظ سازگاری به این روش سخت‌تر خواهد شد.

استراتژی نسخه‌بندی صریح:

در این رویکرد، شما نسخه‌های مختلفی از API را به‌طور هم‌زمان نگهداری می‌کنید. هرگاه نیاز به ایجاد تغییرات مخرب داشتید، نسخه جدیدی منتشر می‌کنید. این روش آزادی عمل بیشتری برای توسعه API به شما می‌دهد.

نسخه‌بندی صریح برای اپلیکیشن‌های سازمانی و محصولاتی که نیاز به تکامل گسترده در طول زمان دارند، بسیار مناسب است. شرکت‌هایی مانند Stripe و Slack از این رویکرد استفاده می‌کنند، چون انعطاف‌پذیری لازم برای بهبودهای اساسی را در اختیارشان می‌گذارد و در عین حال، کاربران نسخه‌های قبلی را نیز پشتیبانی می‌کنند.

در بخش بعدی، به روش‌های پیاده‌سازی نسخه‌بندی صریح خواهیم پرداخت.


روش‌های پیاده‌سازی نسخه‌بندی

سه روش اصلی وجود دارد که کاربران می‌توانند از طریق آن‌ها مشخص کنند می‌خواهند از کدام نسخه API استفاده کنند.

رایج‌ترین روش، نسخه‌بندی در مسیر URL (URL Path Versioning) است. در این روش، نسخه را به مسیر URL اضافه می‌کنید، مانند مثال‌های زیر:

https://api.example.com/v1/stocks https://api.example.com/v2/stocks

در اینجا شناسه نسخه (مثل v1 یا v2) قبل از نام منبع (resource name) قرار می‌گیرد. این کار باعث می‌شود نسخه مشخص‌شده به همه منابع و متدهای آن نسخه اعمال شود. مزیت این روش در سادگی و وضوح آن است. هنگام دیباگ کردن، بلافاصله نسخه API را در هر درخواست می‌بینید. همچنین با ابزارهای مستندسازی و تست API نیز به‌خوبی سازگار است.

اما ایرادی که دارد این است که با هر تغییر نسخه، آدرس URL منبع تغییر می‌کند. این موضوع وقتی مشکل‌ساز می‌شود که بخواهید URLها به‌عنوان لینک‌های دائمی (permalinks) استفاده شوند. با وجود این، بسیاری از APIهای معروف مثل GitHub و Stripe همین روش را به‌کار می‌گیرند.

روش دوم، استفاده از هدر سفارشی HTTP (Custom HTTP Header) برای مشخص کردن نسخه است. در این روش، به‌جای تغییر URL، نسخه را در هدر درخواست تعریف می‌کنید:

GET /stocks HTTP/1.1 Host: api.example.com Api-Version: 2

این رویکرد باعث می‌شود URLها تمیز و ثابت باقی بمانند و با این ایده هم‌راستا است که URL باید هویت منبع را مشخص کند، نه نحوه نمایش آن را. با این حال، استفاده از هدر سفارشی پیاده‌سازی پیچیده‌تری برای مصرف‌کنندگان API دارد و اگر به‌درستی مدیریت نشود، ممکن است مشکلاتی در کشینگ (Caching) ایجاد کند.

سومین روش، استفاده از پارامترهای پرس‌وجو (Query Parameters) برای تعیین نسخه است. در این حالت نسخه به‌عنوان یک پارامتر در URL نوشته می‌شود. این روش راه‌اندازی ساده‌ای دارد و ساختار پایه URL را تغییر نمی‌دهد. اما مشکلش این است که پارامترهای پرس‌وجو معمولاً برای فیلتر کردن استفاده می‌شوند، نه نسخه‌بندی. همین موضوع ممکن است باعث شود که مستندات API به آن‌ها اشاره نکند یا با پارامترهای دیگر تداخل پیدا کند. این روش کمتر رایج است، اما برخی APIها (مثل بعضی از سرویس‌های Google) از آن استفاده می‌کنند.

هر یک از این روش‌ها مزایا و معایب خود را دارند، اما مهم‌ترین نکته، یکدستی و ثبات در انتخاب روش است. بیشتر APIهای بزرگ از نسخه‌بندی در مسیر URL استفاده می‌کنند چون روشی شفاف و ساده است. با این وجود، برخی سرویس‌ها برای پوشش سناریوهای مختلف، چندین روش نسخه‌بندی را به کاربران پیشنهاد می‌دهند.


نسخه‌بندی معنایی (Semantic Versioning)

هنگام نسخه‌بندی APIها، نیاز به یک سیستم شفاف برای نام‌گذاری نسخه‌ها دارید. یکی از رویکردهای محبوب در این زمینه، نسخه‌بندی معنایی (Semantic Versioning یا SemVer) است که از یک فرمت عددی سه‌قسمتی استفاده می‌کند: نسخه اصلی (Major)، نسخه فرعی (Minor) و وصله (Patch).

فرض کنید API شما در نسخه ۲.۰.۰ قرار دارد. معنای هر بخش به این صورت است:

  • نسخه اصلی (Major Version) – عدد اول (۲): زمانی تغییر می‌کند که تغییراتی ناسازگار با نسخه‌های قبلی ایجاد کنید؛ مثل حذف یا تغییر نام فیلدها یا تغییر رفتار یک endpoint. وقتی یک توسعه‌دهنده می‌بیند API از ۲.۰.۰ به ۳.۰.۰ رسیده، می‌داند که باید در کد خود تغییراتی بدهد.

  • نسخه فرعی (Minor Version) – عدد دوم (۰): زمانی افزایش پیدا می‌کند که قابلیت‌های جدیدی به API اضافه می‌کنید که همچنان با نسخه‌های قبلی سازگارند. مثلاً افزودن یک endpoint جدید یا یک فیلد اختیاری. حرکت از ۲.۰.۰ به ۲.۱.۰ به توسعه‌دهندگان اجازه می‌دهد از ویژگی‌های جدید بهره‌مند شوند بدون اینکه نیاز به تغییر کدهای قبلی داشته باشند.

  • وصله (Patch Version) – عدد سوم (۰): برای رفع باگ‌ها و تغییرات جزئی که قابلیت جدیدی اضافه نمی‌کنند اما مشکلات موجود را برطرف می‌کنند. ارتقاء از ۲.۱.۰ به ۲.۱.۱ باید برای تمام کاربران بی‌خطر باشد و نیازی به تغییر در کدهای کلاینت نباشد.

استفاده از نسخه‌بندی معنایی باعث می‌شود توسعه‌دهندگان دقیقاً بدانند چه نوع تغییراتی در API رخ داده است. افزایش نسخه اصلی نشانه نیاز به تغییرات در کد است، در حالی که نسخه‌های فرعی و وصله‌ها (Minor و Patch) باید بدون ایجاد مشکل قابل استفاده باشند.


مدیریت چرخه عمر API

با تغییرات مداوم در API و انتشار نسخه‌های جدید، در نهایت باید نسخه‌های قدیمی‌تر را کنار بگذارید. زمانی که یک نسخه اصلی (Major Version) جدید منتشر می‌کنید، باید برای پشتیبانی از نسخه‌های قبلی یک بازه زمانی مشخص تعریف کنید. مثلاً وقتی نسخه ۴ را ارائه می‌دهید، اعلام می‌کنید که نسخه ۱ به‌زودی از پشتیبانی خارج خواهد شد.

به طور معمول، اگر به توسعه‌دهندگان ۶ تا ۱۲ ماه زمان برای مهاجرت به نسخه‌های جدید بدهید، فرصت کافی برای برنامه‌ریزی و پیاده‌سازی تغییرات را خواهند داشت، بدون آنکه در فشار و عجله قرار بگیرند.

یکی از روش‌های عملی و مؤثر برای اطلاع‌رسانی توقف پشتیبانی (Deprecation) استفاده از هدر Sunset در پاسخ‌های API است. این هدر به توسعه‌دهندگان می‌گوید که یک نسخه یا endpoint خاص تا چه زمانی در دسترس خواهد بود:

Sunset: Sat, 31 Dec 2025 23:59:59 GMT

به‌محض اینکه یک توسعه‌دهنده این هدر را در پاسخ API ببیند، متوجه می‌شود که باید رابط کاربری خود را به‌روزرسانی کند. پس از رسیدن به تاریخ sunset، درخواست‌هایی که به آن نسخه ارسال می‌شوند یا باید پیغام خطا دریافت کنند، یا به نسخه جدید ریدایرکت شوند.


ابزارها

مدیریت نسخه‌های API به صورت دستی، خیلی زود تبدیل به کاری پیچیده و پرخطا می‌شود. خوشبختانه ابزارها و کتابخانه‌هایی وجود دارند که دقیقاً برای همین منظور طراحی شده‌اند و به کمک شما می‌آیند.

OpenAPI Specification که قبلاً با نام Swagger شناخته می‌شد، یکی از بهترین روش‌ها برای توصیف و طراحی APIهاست. این استاندارد مزایای بسیاری در زمینه نسخه‌بندی دارد:

  • به‌راحتی می‌توانید تغییرات هر نسخه را در فایل‌های تعریف جداگانه مستندسازی و ردیابی کنید.

  • مستندات تعاملی (Interactive Documentation) به توسعه‌دهندگان کمک می‌کند تا به‌سرعت تفاوت‌های هر نسخه را ببینند.

  • ابزارهایی وجود دارند که می‌توانید با آن‌ها نسخه‌های مختلف API خود را با یکدیگر مقایسه کرده و تغییرات مخربی (Breaking Changes) که ممکن است باعث بروز خطا شوند را شناسایی کنید.

برای مثال، ابزار openapi-diff به شما این امکان را می‌دهد که دو مشخصات API (Specification) را با هم مقایسه کنید و بفهمید کجاها ناسازگاری ایجاد شده است:

openapi-diff original.json updated.json

خروجی ممکن است چیزی شبیه به این باشد:

GET /stocks Return Type: - Changed 200 OK Media types: - Changed application/json Schema: Broken compatibility Missing property: price (number)

این گزارش به شما می‌گوید که حذف فیلد "price" یک تغییر ناسازگار است که نیازمند انتشار یک نسخه اصلی جدید می‌باشد.

علاوه بر مقایسه مشخصات (Specification Comparison)، ابزارهای دیگری نیز وجود دارند که به مدیریت نسخه‌بندی کمک می‌کنند. مثلاً API Gatewayهایی مثل Amazon API Gateway، Azure API Management یا Kong می‌توانند نسخه‌بندی را به‌صورت خودکار برای شما مدیریت کنند. این ابزارها با توجه به اطلاعات نسخه در URL یا هدرها، درخواست‌ها را به backend مناسب هدایت می‌کنند.

ممکن است نسخه‌بندی API در ابتدا کاری زمان‌بر و پرزحمت به نظر برسد، اما در واقع یک سرمایه‌گذاری بلندمدت برای موفقیت API و رضایت کاربران است. رویکردی دقیق و ثابت در طول زمان به توسعه‌دهندگان نشان می‌دهد که برای کار آن‌ها ارزش قائلید و این اعتماد را حفظ می‌کند؛ حتی زمانی که API شما تغییر می‌کند.

با افتخار از

https://newsletter.francofernando.com/p/apis-versioning?utm_source=%2Fsearch%2FElasticsearch&utm_medium=reader2&hide_intro_popup=true

api
۲
۰
ابوالفضل وکیلی
ابوالفضل وکیلی
instagram : @a_vakily7
شاید از این پست‌ها خوشتان بیاید