سیاست نسخهبندی رابط برنامهنویسی
این سند برای چه کسی است
این سند برای توسعهدهندهای است که دارد سامانه خودش را به رابط برنامهنویسی سگمنتیک وصل میکند. میگوید نسخه کجاست، چه تغییری اتصال شما را میشکند و چه تغییری نمیشکند، پیش از یک تغییر شکننده چقدر وقت دارید، و کد شما باید چطور نوشته شود تا با تغییرهای معمولی ما از کار نیفتد.
هرچه اینجا نوشته شده وضع امروز است. جایی که چیزی را هنوز نساختهایم همان را میگوییم و بهجایش میگوییم امروز چه چیزی استفاده میشود. سیاستی که ماشینی را توصیف کند که وجود ندارد، از نبود سیاست بدتر است، چون یکپارچهسازی شما منتظر سیگنالی میماند که هرگز نمیآید.
تبصره ۱: همه فراخوانهای این رابط روی زیرساخت داخل ایران پاسخ داده میشود و دادهای که با آن میفرستید از کشور بیرون نمیرود.
ماده ۱نسخه یک بخش از مسیر است
نسخه رابط عمومی یک بخش از مسیر نشانی است و امروز `v1` است، مثلاً `/api/v1/events`.
جای دیگری نسخه نگه نمیداریم. هدر نسخه و `Accept` سفارشی خوانده نمیشود، پارامتر پرسوجوی نسخه خوانده نمیشود، و بازبینی تاریخمحور نداریم. اگر نسخه را جایی جز مسیر بفرستید، بیصدا نادیده گرفته میشود.
دلیل این انتخاب ساده است: یک بخش از مسیر در لاگ، در گزارش خطا و در تنظیمات پراکسی دیده میشود، ولی هدر دیده نمیشود و در مسیر عبور گم میشود.
تبصره ۲: تا امروز فقط یک نسخه منتشر شده است. `v2` وجود ندارد و تاریخی هم برایش اعلام نشده است.
ماده ۲چه وقت نسخه عوض میشود
قاعده خانگی ما یک جمله است: نسخه فقط وقتی عوض میشود که شکل پاسخ طوری تغییر کند که یک یکپارچهسازی موجود متوجه آن بشود.
یعنی معیار، اندازه تغییر سمت ما نیست. معیار این است که کدی که دیروز کار میکرد امروز هم کار میکند یا نه. بازنویسی کامل یک بخش درونی، اگر پاسخ همان شکل قبلی را داشته باشد، نسخه را عوض نمیکند. حذف یک کلید کوچک، عوض میکند.
ماده ۳تغییر شکننده چیست
اینها شکنندهاند و بدون عوض شدن نسخه انجام نمیشوند:
- حذف یک کلید از پاسخ
- عوض شدن نوع یک کلید، مثلاً از رشته به عدد یا از مقدار ساده به شیء
- حذف یک نقطه پایانی یا تغییر مسیر آن
- اجباری شدن فیلدی که تا دیروز اختیاری بود
- تنگتر شدن مقدارهای پذیرفتهشده یک ورودی
- عوض شدن معنای یک کلید، وقتی نام و نوعش سر جایش میماند
- عوض شدن مقدار پیشفرض یک پارامتر، طوری که خروجی فرق کند
- عوض شدن کد وضعیت پاسخ برای حالتی که از قبل وجود داشت
خطرناکترین مورد این فهرست ششمی است. حذف یک کلید پرصدا از کار میافتد و شما همان روز میفهمید. عوض شدن معنای یک کلید بیصدا اشتباه میشود و ممکن است هفتهها بعد در گزارش شما پیدا شود. به همین دلیل آن را همسنگ حذف حساب میکنیم.
ماده ۴تغییر شکننده چه چیزی نیست
اینها هر زمان، بدون اعلام قبلی و بدون عوض شدن نسخه انجام میشوند:
- افزودن یک کلید تازه به پاسخ
- افزودن یک فیلد اختیاری تازه به ورودی
- افزودن یک نقطه پایانی تازه
- افزودن یک مقدار تازه به فهرست مقدارهای مجاز یک فیلد
- افزودن یک هدر تازه به پاسخ
- عوض شدن ترتیب کلیدها در شیء JSON
- رفع اشکالی که پاسخ را با مستندات هماهنگ میکند
- تغییر سرعت پاسخ و جزئیات درونی پیادهسازی
دو مورد از این فهرست معمولاً یکپارچهسازیها را غافلگیر میکند: مقدار تازه در یک فیلد شمارشی، و کلید تازه در پاسخ. ما هر دو را غیرشکننده حساب میکنیم، پس کد شما باید هر دو را تحمل کند. بند «فیلد ناشناخته» پایینتر همین را میگوید.
ماده ۵کلید تازه کنار کلید قدیمی
وقتی میخواهیم پاسخ کاملتری بدهیم، پاسخ کاملتر را زیر یک کلید تازه کنار کلید قدیمی میگذاریم و شکل کلید قدیمی را دست نمیزنیم.
مثال: فرض کنید `count` یک عدد است و بعداً لازم میشود تفکیک آن عدد هم برگردانده شود. کاری که نمیکنیم این است که `count` را به یک شیء تبدیل کنیم. کاری که میکنیم این است که `count_breakdown` را کنارش اضافه کنیم. `count` همان عدد میماند، با همان معنا.
بیشتر فشارهایی که بهنظر میرسد «نسخه تازه لازم است»، در واقع «باید بیشتر برگردانیم» است، و بیشتر، کنار قدیمی جا میشود. عمر طولانی `v1` نتیجه همین یک قاعده است.
هزینه این قاعده را هم پنهان نمیکنیم. پاسخها با گذشت زمان بزرگتر و شلوغتر میشوند و چند کلید در آنها یادگاری گذشتهاند. این را در برابر شکستن اتصال مشتری پذیرفتهایم.
ماده ۶نقطه پایانی توانمندیها
یک نقطه پایانی توانمندیها (capabilities) وجود دارد که میگوید این نصب امروز چه چیزی را پشتیبانی میکند: کدام کانالها فعالاند، کدام قابلیتها روشناند و کدام محدودیتها اعمال میشود.
این تنها ساز و کار سازگاری رو به جلوی ماست. بهجای اینکه فهرست قابلیتها را در کد خودتان ثابت بنویسید، آن را از همین نقطه پایانی بپرسید. قابلیتی که بعداً اضافه شود، بدون عوض شدن نسخه در همین پاسخ ظاهر میشود و یکپارچهسازی شما بدون تغییر کد آن را میبیند.
دو نکته دربارهاش:
- این پاسخ را در زمان راهاندازی بخوانید و مدتی نگه دارید. خواندنش پیش از هر فراخوان، بار بیجهت است.
- این نقطه پایانی توانمندی را اعلام میکند، نه شکل داده را. مذاکره نسخه نیست و شکل پاسخ نقاط پایانی دیگر را عوض نمیکند.
ماده ۷فیلد ناشناخته را نادیده بگیرید
یکپارچهسازی شما باید کلید ناشناخته در پاسخ را نادیده بگیرد، نه اینکه با آن خطا بدهد. چون افزودن کلید از نظر ما شکننده نیست، بدون اعلام قبلی انجام میشود. اگر تجزیهگر JSON شما سختگیر باشد، یک تغییر بیضرر سمت ما به قطعی سمت شما تبدیل میشود.
بهطور مشخص:
- در Go، `DisallowUnknownFields` را روشن نکنید
- در Java و Jackson، `FAIL_ON_UNKNOWN_PROPERTIES` را خاموش بگذارید
- در هر زبان دیگری، اعتبارسنجی سختگیر شمای پاسخ را روی مسیر اصلی نگذارید
سه عادت دیگر هم اتصال را شکننده میکند و از سمت ما قابل جبران نیست:
- تکیه بر ترتیب کلیدها در JSON
- تکیه بر نبودن یک کلید، بهجای بررسی مقدار آن
- خواندن تاریخ با بریدن رشته، بهجای تجزیه کامل آن
تبصره ۳: برای فیلدهای شمارشی، مقدار ناشناخته باید به شاخه پیشفرض برود. اگر وضعیت تازهای اضافه شود و کد شما فقط وضعیتهای امروز را بشناسد، باید بیخطر رد شود نه اینکه بیفتد.
ماده ۸مهلت پیش از یک تغییر شکننده
هر تغییر شکننده دست کم شش ماه پیش از اجرایی شدن اعلام میشود.
اعلام از دو راه انجام میشود: صفحه تغییرات در مستندات، و رایانامه به رابط فنی هر حسابی که آن نقطه پایانی را در همان دوره فراخوانده باشد. یعنی اگر از بخشی استفاده نمیکنید، بابت آن رایانامه نمیگیرید.
تبصره ۴: رفع یک آسیبپذیری امنیتی میتواند این مهلت را کوتاه کند. در آن صورت علت و دامنه تغییر در همان اعلام نوشته میشود.
ماده ۹عمر نسخه قدیمی
بعد از انتشار یک نسخه تازه، نسخه قبلی دست کم یک سال زنده میماند و به فراخوانها پاسخ میدهد.
در این بازه، نسخه قدیمی فقط رفع اشکال و اصلاح امنیتی میگیرد و قابلیت تازه روی آن اضافه نمیشود. قابلیت تازه فقط روی نسخه جاری میآید و همین، خودش دلیل مهاجرت است.
بعد از پایان این بازه، فراخوان به مسیر نسخه بازنشسته با خطای `410` رد میشود. عمداً به نسخه تازه هدایت نمیشود، چون هدایت خاموش یک فراخوان قدیمی به پاسخی با شکل تازه، بدتر از خطاست. خطا را همان لحظه میبینید، داده بدشکل را ممکن است هرگز نبینید.
ماده ۱۰هدر غروب امروز فرستاده نمیشود
امروز هیچ هدر ماشینخوانی برای منسوخسازی نمیفرستیم. نه هدر `Sunset`، نه هدر `Deprecation`، نه `Warning` روی پاسخ نقطه پایانی در حال منسوخ شدن.
جایش دو چیز است که بالاتر گفته شد: صفحه تغییرات مستندات، و رایانامه به رابط فنی حساب. غیر از این دو، سیگنال دیگری وجود ندارد.
این را روشن مینویسیم چون خلافش گران تمام میشود. اگر کسی با این تصور کد بنویسد که سامانه پیش از قطع شدن یک هشدار ماشینخوان میفرستد، آن هشدار هرگز نمیآید و پایش او هیچوقت زنگ نمیزند.
اگر روزی این هدرها اضافه شوند، خودش یک تغییر افزایشی است، بدون عوض شدن نسخه انجام میشود و همین سند بهروز میشود.
ماده ۱۱تغییر این سند
تغییر این سند دست کم ۶۰ روز پیش از اجرایی شدن اعلام میشود. نسخههای پیشین بایگانی میشوند تا بشود دید در روزی که یک یکپارچهسازی نوشته شده، تعهد ما چه بوده است.
تبصره ۵: این سند یک تعهد عملیاتی عمومی است و جای قرارداد خدمات را نمیگیرد. اگر جایی از این سند با قرارداد امضاشده تعارض داشت، قرارداد حاکم است.
تماس
پرسش فنی درباره این سند: support@segmentic.net
کارگستران نسل جوان باختر https://segmentic.net