SDK و هدفگیری Feature Flag
استفاده از identify، operatorهای شرط و APIهای React و Vanilla برای ارزیابی Feature Flag.
هدفگیری Feature Flag در آلفانا بر اساس ویژگیهایی انجام میشود که برای Visitor در اختیار SDK قرار گرفتهاند. این ویژگیها معمولاً از طریق identify() ثبت میشوند و هنگام ارزیابی Flag با Conditionهای تعریفشده در داشبورد مقایسه میشوند.
اگر یک Feature Flag بیش از یک Condition داشته باشد، تمام Conditionهای آن با منطق AND ترکیب میشوند. یعنی برای فعال شدن Flag، همه شرطهای تعریفشده باید همزمان برقرار باشند.
برای مثال، اگر Flag فقط برای کاربران Plan Pro در کشور ایران تعریف شده باشد، Visitor باید هر دو شرط را داشته باشد تا نتیجه ارزیابی true شود.
Operatorهای شرط#
Backend در نسخه فعلی از Operatorهای زیر برای ارزیابی Conditionها پشتیبانی میکند:
| operator | معنی |
|---|---|
equals | بررسی برابری رشتهای بدون حساسیت به بزرگی یا کوچکی حروف |
contains | بررسی میکند مقدار Visitor شامل رشته موردنظر باشد |
is_in | بررسی میکند مقدار Visitor داخل فهرست comma-separated تعریفشده قرار داشته باشد |
هر Condition یک property از Visitor را با مقدار تعریفشده برای Flag مقایسه میکند.
برای اینکه نتیجه Targeting قابلپیشبینی بماند، بهتر است propertyهایی که در Conditionها استفاده میشوند با Naming ثابت در کل محصول ارسال شوند.
ثبت ویژگیهای Visitor#
ویژگیهای موردنیاز برای Targeting را میتوانید با identify() ثبت کنید:
tracker.identify({
email: "user@example.com",
plan: "pro",
country: "IR",
});identify() ویژگیهای جدید Visitor را در اختیار Tracker قرار میدهد و میتواند باعث refresh شدن ارزیابی Feature Flagها شود.
در نسخه فعلی، identify() فقط مقدارهایی با ساختار زیر میپذیرد:
Record<string, string>;بنابراین اگر مقدار موردنظر عددی یا boolean است، آن را قبل از ارسال به string تبدیل کنید.
برای مثال:
tracker.identify({
age: String(user.age),
isTrial: String(user.isTrial),
});Operator equals#
equals برای زمانی مناسب است که مقدار property باید با مقدار Condition برابر باشد.
برای مثال، اگر Condition به این شکل تعریف شده باشد:
property: plan
operator: equals
value: proVisitor زیر شرط را پاس میکند:
tracker.identify({
plan: "pro",
});مقایسه equals نسبت به بزرگی و کوچکی حروف حساس نیست. بنابراین مقدارهای زیر از نظر این Operator برابر در نظر گرفته میشوند:
pro
Pro
PROبا این حال، بهتر است در دادههای واقعی همچنان یک Naming Convention ثابت داشته باشید تا همان propertyها در Segmentها، گزارشها و سایر بخشهای محصول نیز یکدست باقی بمانند.
Operator contains#
contains بررسی میکند آیا مقدار property شامل رشته تعریفشده در Condition هست یا نه.
برای مثال، اگر Condition برای email تعریف شده باشد:
property: email
operator: contains
value: @example.comمقدار زیر میتواند شرط را برقرار کند:
user@example.comاین Operator برای شرایطی مناسب است که تطبیق کامل مقدار لازم نیست و فقط وجود بخشی از رشته اهمیت دارد.
Operator is_in#
is_in برای مقایسه یک property با چند مقدار مجاز استفاده میشود.
مقادیر Condition بهصورت یک فهرست comma-separated تعریف میشوند.
برای مثال:
property: country
operator: is_in
value: IR,TR,AEاگر مقدار country برای Visitor یکی از این موارد باشد، Condition برقرار میشود.
برای مثال:
tracker.identify({
country: "IR",
});این Operator زمانی مناسب است که یک Flag باید برای چند گروه مشخص با یک property مشترک فعال باشد.
ترکیب چند Condition#
اگر Flag بیش از یک Condition داشته باشد، همه آنها باید برقرار باشند.
برای مثال:
plan equals pro
country is_in IR,AE
email contains @company.comبرای فعال شدن این Flag، Visitor باید:
- Plan برابر
proداشته باشد - Country او
IRیاAEباشد - Email او شامل
@company.comباشد
اگر حتی یکی از این Conditionها برقرار نباشد، نتیجه Flag false خواهد بود.
این رفتار بر اساس منطق AND انجام میشود و در نسخه فعلی Conditionهای یک Flag با OR ترکیب نمیشوند.
ارزیابی Flag در Vanilla SDK#
بعد از ثبت ویژگیهای Visitor میتوانید Flagها را refresh کنید و وضعیت یک Flag مشخص را بخوانید:
tracker.identify({
email: "user@example.com",
plan: "pro",
country: "IR",
});
await tracker.fetchFlags();
if (tracker.isFeatureEnabled("new-checkout")) {
showNewCheckout();
}در این مثال:
- ویژگیهای Visitor با
identify()ثبت میشوند. fetchFlags()ارزیابی جدید Flagها را از Backend دریافت میکند.isFeatureEnabled()وضعیت فعلی Flag موردنظر را از snapshot Tracker میخواند.
در بسیاری از سناریوها، identify() خودش باعث refresh شدن Flagها میشود. بنابراین لازم نیست بعد از هر بار identify() حتماً fetchFlags() را جداگانه اجرا کنید، مگر اینکه بخواهید زمان refresh را بهصورت مستقیم کنترل کنید.
خواندن همه Flagها#
برای دریافت snapshot فعلی همه Feature Flagها میتوانید از getFlags() استفاده کنید:
const flags = tracker.getFlags();این متد آخرین وضعیت موجود در Tracker را برمیگرداند و درخواست شبکه جدیدی ایجاد نمیکند.
اگر فقط وضعیت یک Flag مشخص مهم است، استفاده از isFeatureEnabled() خواناتر است:
const enabled = tracker.isFeatureEnabled("new-checkout");دنبال کردن تغییر Flagها#
اگر بخشی از برنامه باید هنگام تغییر نتیجه Feature Flag واکنش نشان دهد، میتوانید از onFlagsChange() استفاده کنید.
برای مثال:
const unsubscribe = tracker.onFlagsChange((flags) => {
console.log(flags);
});این callback زمانی اجرا میشود که snapshot Feature Flagها تغییر کند.
در پایان lifecycle مربوط به subscription، اگر API برگشتی امکان unsubscribe داشته باشد، آن را مطابق قرارداد همان نسخه اجرا کنید تا listener اضافی باقی نماند.
استفاده در React#
در React معمولاً نیازی نیست مستقیماً با getFlags() یا onFlagsChange() کار کنید. Hookهای React snapshot و rerender مرتبط با تغییر Feature Flagها را مدیریت میکنند.
برای بررسی یک Flag مشخص:
import { useFeatureFlag, useFeatureFlags } from "alphana-sdk/react";
function Checkout() {
const enabled = useFeatureFlag("new-checkout");
const allFlags = useFeatureFlags();
return enabled ? <NewCheckout /> : <CurrentCheckout />;
}useFeatureFlag(key) مقدار boolean مربوط به Flag مشخصشده را برمیگرداند.
useFeatureFlags() نیز map فعلی تمام Feature Flagهای ارزیابیشده را در اختیار Component قرار میدهد.
وقتی Flagها refresh شوند، Hookهای مرتبط میتوانند Component را با snapshot جدید دوباره Render کنند.
Targeting بعد از Login#
یکی از زمانهای مهم برای اجرای identify() بعد از Login است.
پیش از شناسایی کاربر، Tracker ممکن است فقط اطلاعات عمومی Visitor را در اختیار داشته باشد. بعد از Login میتوانید propertyهایی مثل Plan، Role یا Country را ثبت کنید تا Targeting با context دقیقتری انجام شود.
برای مثال:
tracker.identify({
plan: user.plan,
role: user.role,
country: user.country,
});اگر Feature Flag بر اساس یکی از این propertyها Condition داشته باشد، ارزیابی بعدی میتواند نتیجه متفاوتی نسبت به قبل از Login داشته باشد.
Naming ویژگیها#
Propertyهایی که برای Feature Flag Targeting استفاده میکنید بهتر است در کل محصول ساختار ثابتی داشته باشند.
برای مثال، برای Plan یکی از این الگوها را انتخاب کنید:
free
pro
enterpriseو همان الگو را همیشه حفظ کنید.
ارسال مقدارهای متفاوت مثل:
pro
Pro Plan
professionalبرای یک مفهوم یکسان میتواند Targeting و تحلیل Audience را پیچیدهتر کند.
همین اصل برای نام propertyها نیز برقرار است. اگر در Condition از country استفاده میکنید، در بخش دیگری همان داده را با نامی مثل user_country ارسال نکنید مگر اینکه عمداً دو مفهوم متفاوت باشند.
Feature Flag جایگزین Authorization نیست#
Feature Flag میتواند مشخص کند چه تجربهای به یک کاربر نمایش داده شود، اما نباید بهعنوان مکانیزم امنیتی یا Authorization استفاده شود.
برای مثال، اگر یک قابلیت فقط برای کاربران Enterprise مجاز است، مخفی کردن UI با Feature Flag کافی نیست.
Backend همچنان باید دسترسی واقعی به عملیات حساس را بر اساس Authentication و Authorization خودش بررسی کند.
Feature Flag بیشتر برای کنترل rollout، تجربه محصول، Targeting و Kill Switch مناسب است.