الـ Guard Clauses في State Machines: أنظمة صلاحيات تعمل بالفعل
· 5 دقائق قراءة
منطق التفويض مبعثر في أنحاء تطبيقك؟ ماذا لو كان ببساطة... جزءاً من تعريف الحالة؟
فوضى التفويض
تتعامل معظم التطبيقات مع الصلاحيات بهذه الطريقة:
// في المكوّن
function ApproveButton({ order }) {
const { user } = useAuth();
const canApprove =
user.roleLevel >= 5 &&
!order.isFlagged &&
order.amount > 0;
return (
<button disabled={!canApprove} onClick={handleApprove}>
Approve
</button>
);
}
// في مسار الـ API
app.post('/api/orders/:id/approve', async (req, res) => {
const { user } = req;
const order = await Order.findById(req.params.id);
// نفس المنطق، مكرر!
if (user.roleLevel < 5) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
if (order.isFlagged) {
return res.status(400).json({ error: 'Order is flagged' });
}
if (order.amount <= 0) {
return res.status(400).json({ error: 'Invalid amount' });
}
// ... منطق الموافقة الفعلي
});
المشاكل:
- المنطق مكرر في الواجهة الأمامية والخلفية
- صعوبة المزامنة بينهما
- مبعثر عبر ملفات متعددة
- لا يوجد مصدر واحد للحقيقة
الـ Guards: تفويض تصريحي
في Almadar، الـ guards (شروط تتحقق قبل السماح بالـ transition) جزء من الـ state machine:
{
"from": "pending",
"to": "approved",
"event": "APPROVE",
"guard": ["and",
[">=", "@user.roleLevel", 5],
["not", "@entity.isFlagged"],
[">", "@entity.amount", 0]
],
"effects": [
["set", "@entity.status", "approved"],
["set", "@entity.approvedAt", "@now"],
["persist", "update", "Order", "@entity.id", "@entity"]
]
}
الـ guard تصريحي، قابل للتسلسل، ومُطبَّق في كل مكان.
