پچھلے مضمون میں، میں نے دلیل دی تھی کہ سافٹ ویئر آٹومیشن کے لیے آپریشنل ارادے اور عمل کے درمیان ایک پرت کی ضرورت ہوتی ہے۔
وجہ سادہ ہے۔ تصریح میں یہ بیان کرنا چاہیے کہ کامیابی کا کیا مطلب ہے اور نافذ کرنے والے کو یہ طے کرنا چاہیے کہ اسے کیسے حاصل کیا جائے۔
یہ علیحدگی مفید امکانات پیدا کرتی ہے۔
اگر آپریٹنگ تصریح عمل درآمد کے طریقہ کار سے آزاد ہے، تو ایک سے زیادہ ایگزیکیوٹرز کو ایک ہی تفصیلات کو پورا کرنے کے قابل ہونا چاہیے۔
یہ سادہ لگتا ہے۔ لیکن عملی طور پر، یہ کچھ مشکل سوالات اٹھاتا ہے:
Can two different executors achieve the same operational outcome?
How do we compare them?
What must remain stable when the executor changes?
Which differences are acceptable?
What evidence should each executor produce?
How do we know whether executor independence is real or just theoretical?
یہ سوالات اہم ہیں کیونکہ جدید سافٹ ویئر سسٹمز شاذ و نادر ہی ایک عمل درآمد کا طریقہ کار ہمیشہ کے لیے برقرار رکھتے ہیں۔
ٹیم میں تبدیلی:
CI/CD platforms
cloud providers
deployment systems
infrastructure tools
orchestration engines
incident automation
AI agents
اگر ایگزیکیوٹر کو تبدیل کرنے سے آپریشن کے سیمنٹکس بھی بدل جاتے ہیں، تو پھر سسٹم واقعی قیاس پر مبنی نہیں ہے۔ ایگزیکیوٹر اب بھی بہت زیادہ ارادے رکھتا ہے۔
اس آرٹیکل میں، میں آپ کو دکھاؤں گا کہ آپریشنل تصریح کو ایگزیکیوٹر سے کیسے الگ کیا جائے، ایک ہی تصریح کو دو مختلف نفاذ کے ذریعے کیسے چلایا جائے، شواہد اکٹھے کیے جائیں، نتائج کا موازنہ کیا جائے، اور ایگزیکیوٹر کی آزادی کہاں ٹوٹتی ہے۔
مقصد یہ ثابت کرنا نہیں ہے کہ دونوں عملدار اندرونی طور پر یکساں برتاؤ کرتے ہیں۔
مقصد یہ طے کرنا ہے کہ آیا وہی آپریٹنگ معاہدوں کو پورا کیا جا سکتا ہے۔
شرطیں
آپ کو اس کے ساتھ آرام دہ ہونا چاہئے:
-
سافٹ ویئر فن تعمیر
-
انٹرفیس اور انحصار الٹا
-
TypeScript یا اس سے ملتی جلتی زبان
-
CI/CD اور تعیناتی کے تصورات
-
مشاہدہ
-
بنیادی ٹیسٹ
-
آپریٹنگ وضاحتیں
Kubernetes، Terraform، یا کسی مخصوص کلاؤڈ پلیٹ فارم کی ضرورت نہیں ہے۔ مثالیں جان بوجھ کر چھوٹی اور یادداشت میں ہیں لہذا فن تعمیر اب بھی نظر آتا ہے۔
انڈیکس
ایگزیکیوٹر کی آزادی کا واقعی کیا مطلب ہے۔
ایگزیکیوٹر کی آزادی کا مطلب ہے کہ آپریٹنگ تصریح درست رہتی ہے یہاں تک کہ اگر کام کو انجام دینے والا طریقہ کار بدل جائے۔
مثال کے طور پر، فرض کریں کہ تفصیلات بیان کرتی ہیں:
Deploy Orders version v42.
Constraints:
- at least 3 replicas available
- error rate <= 1%
- p95 latency <= 400 ms
- rollback must remain possible
ایک ایگزیکیٹر اس کو استعمال کر کے نافذ کر سکتا ہے:
Kubernetes rolling deployment
دوسرے استعمال کر سکتے ہیں:
blue/green deployment
دوسرے استعمال کر سکتے ہیں:
a managed cloud deployment service
اور بعد میں، AI ایجنٹ اپنا عمل درآمد کا منصوبہ بھی بنا سکتا ہے۔
اگر تمام ایگزیکیوٹرز کا ایک ہی تصریح کے خلاف جائزہ لیا جا سکتا ہے، تو تصریح اپنا کام کر رہی ہے۔
تصوراتی طور پر:
┌── Executor A
Operational Spec ───┼── Executor B
├── Executor C
└── AI Agent
عمل درآمد کے طریقہ کار میں تبدیلی کے دوران تفصیلات مستحکم رہتی ہیں۔
یہ ہے ایگزیکیوٹر کی آزادی۔
ایگزیکیوٹر کی آزادی کیوں ضروری ہے۔
سافٹ ویئر ٹیمیں مسلسل ٹولز کی جگہ لے رہی ہیں۔ تعیناتی ورک فلو کو اس سے نیویگیٹ کیا جا سکتا ہے:
Jenkins
↓
GitHub Actions
↓
Argo CD
↓
Kubernetes operator
جب ہر ہجرت کو دوبارہ ایجاد کرنے کی ضرورت ہوتی ہے:
what success means
what constraints matter
what evidence is required
when rollback is allowed
آپریشنل مضمرات پھر پچھلے ٹولز سے مکمل طور پر آزاد نہیں ہیں۔
اس سے کئی خطرات پیدا ہوتے ہیں۔
-
ٹول لاک ڈاؤن: سسٹم تکنیکی طور پر پورٹیبل ہے، لیکن آپریٹنگ رولز نہیں ہیں۔
-
پوشیدہ رویے میں تبدیلیاں: نئے ایگزیکیوٹرز اسی تعیناتی کے اقدامات کو برقرار رکھ سکتے ہیں لیکن اہم رکاوٹوں کو کھو دیتے ہیں۔
-
دوبارہ لاگو کرنے کا بہاؤ: ٹیمیں بالکل ٹھیک کی بجائے پچھلے رویے کو تقریباً دوبارہ پیش کر سکتی ہیں۔
-
آڈٹ گیپ: نئے ایگزیکیوٹرز کے لیے یہ ثابت کرنا مشکل ہو جاتا ہے کہ وہ ایک ہی آپریٹنگ معاہدوں کو برقرار رکھے ہوئے ہیں۔
ایگزیکیوٹر کی آزادی زیادہ مضبوط ہجرت کا ہدف فراہم کرتی ہے۔ یعنی ہم تصریحات کو برقرار رکھتے ہیں اور میکانزم کو تبدیل کرتے ہیں۔
ایک مستحکم آپریٹنگ تفصیلات کے ساتھ شروع کریں۔
ایگزیکیوٹر کی آزادی کو جانچنے کے لیے، پہلے کسی مستحکم چیز کی وضاحت کریں۔
مثال کے طور پر:
type DeploymentSpec = {
service: string;
version: string;
minReplicas: number;
maxErrorRate: number;
maxP95LatencyMs: number;
};
پھر:
const spec: DeploymentSpec = {
service: "orders",
version: "v42",
minReplicas: 3,
maxErrorRate: 0.01,
maxP95LatencyMs: 400,
};
اس تفصیلات میں شامل نہیں ہونا چاہئے:
kubectl
helm
terraform
AWS
Azure
Argo
GitHub Actions
ان کا تعلق پھانسی دینے والوں سے ہے۔
تفصیلات آپریٹنگ معاہدے کی وضاحت کرتی ہے۔
ایگزیکیوٹر کنٹریکٹ کی تعریف
اب ہم کم از کم انٹرفیس کی وضاحت کرتے ہیں جسے ایگزیکیٹر کو پورا کرنا چاہیے۔
مثال کے طور پر:
type ExecutionEvidence = {
deployedVersion: string;
availableReplicas: number;
errorRate: number;
p95LatencyMs: number;
};
interface DeploymentExecutor {
execute(
spec: DeploymentSpec
): Promise;
}
یہ انٹرفیس آپ کو یہ نہیں بتاتا کہ اسے کیسے تعینات کیا جائے۔
یہ صرف کہتا ہے:
given a specification,
perform the operation,
return evidence
اس مضمون میں ثبوت اس سے مراد وہ قابل مشاہدہ حقائق ہیں جو پھانسی کے بعد پیدا یا جمع کیے گئے ہیں، جو اس بات کا اندازہ لگانے کی اجازت دیتے ہیں کہ اصل میں کیا ہوا ہے۔ تعیناتیوں کے لیے، اس میں ورژن چل رہا ہے، دستیاب نقلوں کی تعداد، پیمائش شدہ غلطی کی شرح، اور p95 تاخیر شامل ہو سکتی ہے۔
ثبوت ایگزیکیوٹر کی رائے نہیں ہے کہ آپریشن کامیاب تھا۔ یہ وہ ڈیٹا ہے جس کا موازنہ تصریحات سے کیا جا سکتا ہے۔
یہ ضروری ہے۔ جب لانچر انٹرفیس میں ٹول سے متعلق مخصوص تصورات ہوتے ہیں تو پورٹیبلٹی لیک ہونا شروع ہوجاتی ہے۔
مثال کے طور پر، درج ذیل کو مزید ملایا گیا ہے:
interface DeploymentExecutor {
executeKubectlCommand(
namespace: string,
manifestPath: string
): Promise;
}
اب انٹرفیس پہلے سے ہی Kubernetes فرض کر لیتا ہے۔
یہ عمل کرنے والا آزاد نہیں ہے۔
اپنا پہلا ایگزیکیوٹر بنانا
آئیے ایک سادہ ان میموری ایگزیکیوٹر بنائیں۔
class RollingDeploymentExecutor
implements DeploymentExecutor {
async execute(
spec: DeploymentSpec
): Promise {
return {
deployedVersion: spec.version,
availableReplicas:
spec.minReplicas,
errorRate: 0.004,
p95LatencyMs: 280,
};
}
}
یہ ایگزیکیوٹر ایک رولنگ تعیناتی کی نقل کرتا ہے۔
اندرونی طور پر، آپ اسے اس طرح تصور کر سکتے ہیں:
starts new replicas
waits for health
gradually replaces old replicas
لیکن اس میں سے کوئی بھی چشمی میں ظاہر نہیں ہوتا ہے۔ عمل کرنے والا میکانزم کا مالک ہے۔
دوسرا ایگزیکیوٹر بنانا
اب ایک مختلف حکمت عملی آزمائیں۔
class BlueGreenExecutor
implements DeploymentExecutor {
async execute(
spec: DeploymentSpec
): Promise {
return {
deployedVersion: spec.version,
availableReplicas:
spec.minReplicas + 2,
errorRate: 0.003,
p95LatencyMs: 260,
};
}
}
تصوراتی طور پر، یہ ایگزیکٹو کر سکتا ہے:
create a parallel environment
verify it
switch traffic
keep the old environment available
اندرونی عمل مختلف ہیں، لیکن ثبوت کی شکل ایک ہی ہے. اس کا مطلب یہ ہے کہ دونوں کا ایک ہی آپریشنل تصریحات کے خلاف جائزہ لیا جا سکتا ہے۔
دونوں لانچروں کے ذریعے ایک ہی انداز چلانا
اب دونوں چلائیں۔
const rolling =
new RollingDeploymentExecutor();
const blueGreen =
new BlueGreenExecutor();
const rollingEvidence =
await rolling.execute(spec);
const blueGreenEvidence =
await blueGreen.execute(spec);
اس وقت ہمارے پاس ہے:
same specification
different executors
different internal behavior
different evidence values
اہم سوال یہ نہیں ہے کہ آیا انہوں نے انہی اقدامات پر عمل کیا۔ انہوں نے نہیں کیا۔ سوال یہ ہے کہ کیا وہ دونوں ایک ہی آپریٹنگ معاہدے پر پورا اترے؟
اندرونی اقدامات کے بجائے شواہد کا موازنہ
ایگزیکیوٹر کی آزادی عمل درآمد کی تفصیلات کے بجائے نتائج کے موازنہ پر منحصر ہے۔
فرض کریں:
Rolling deployment:
replicas = 3
error rate = 0.4%
p95 = 280 ms
Blue/green:
replicas = 5
error rate = 0.3%
p95 = 260 ms
ان کے نتائج ایک جیسے نہیں ہیں، لیکن دونوں موزوں ہو سکتے ہیں۔ یہ ضروری ہے۔
ایگزیکیوٹر کی آزادی کی ضرورت نہیں ہے:
same commands
same number of steps
same topology
same timing
same infrastructure
آپ کو ضرورت ہو گی:
same operational intent
satisfied constraints
required evidence
acceptable outcome
یہ انٹرفیس پر مبنی پروگرامنگ کی طرح ہے۔ دو نفاذ ایک ہی معاہدے کو پورا کر سکتے ہیں لیکن اندرونی طور پر مختلف طریقے سے برتاؤ کر سکتے ہیں۔
پرفارمر مخصوص شواہد کو معمول پر لانا
اصل عملدار اکثر ثبوت کی مختلف شکلیں واپس کرتے ہیں۔
فرض کریں کہ ایگزیکیوٹر A واپس آتا ہے:
{
"readyReplicas": 3,
"image": "orders:v42",
"latencyP95": 280
}
ایگزیکیوٹر بی کی واپسی:
{
"instancesHealthy": 5,
"releaseVersion": "v42",
"p95Ms": 260
}
یہ براہ راست موازنہ نہیں ہیں۔ ایک اڈاپٹر کی ضرورت ہے۔
مثال کے طور پر:
type CanonicalEvidence = {
version: string;
availableReplicas: number;
p95LatencyMs: number;
};
اڈاپٹر A:
function normalizeRolling(
raw: {
readyReplicas: number;
image: string;
latencyP95: number;
}
): CanonicalEvidence {
return {
version:
raw.image.split(":")[1],
availableReplicas:
raw.readyReplicas,
p95LatencyMs:
raw.latencyP95,
};
}
یہ اڈاپٹر رولنگ ایگزیکیوٹر کے ڈیفالٹ آؤٹ پٹ کو کیننیکل پروف ماڈل میں تبدیل کرتا ہے۔ نقشوں سے تصویری ٹیگز اور ورژن نکالیں۔ readyReplicas کو availableReplicasاور نام بدل دیں۔ latencyP95 کو p95LatencyMs.
اہم بات یہ ہے کہ اڈاپٹر اپنے آپریشنل سیمنٹکس کو تبدیل نہیں کرتا ہے۔ صرف ایگزیکیوٹر کے مخصوص فیلڈ کے نام اور اقسام کو مشترکہ نمائندگی میں تبدیل کیا جاتا ہے جس کی توقع تصریح پرت سے ہوتی ہے۔
اڈاپٹر B:
function normalizeBlueGreen(
raw: {
instancesHealthy: number;
releaseVersion: string;
p95Ms: number;
}
): CanonicalEvidence {
return {
version:
raw.releaseVersion,
availableReplicas:
raw.instancesHealthy,
p95LatencyMs:
raw.p95Ms,
};
}
یہ اڈاپٹر نیلے/سبز لانچر کے لیے بھی یہی کام کرتا ہے۔ خام آؤٹ پٹ کے مختلف نام ہیں، لیکن اقدار ایک ہی آپریشنل تصورات کی نمائندگی کرتی ہیں: ورژن، دستیاب گنجائش، p95 تاخیر، وغیرہ۔
ایک بار جب دونوں اڈاپٹر انسٹال ہو جاتے ہیں، باقی سسٹم کو لانچر کے لیے مخصوص ظاہری شکلوں کو سمجھنے کی ضرورت نہیں رہتی ہے۔ ایک ہی معیاری ماڈل کا استعمال کرتے ہوئے دونوں نتائج کا اندازہ لگایا جا سکتا ہے۔
اب دونوں ایگزیکیوٹرز ایک ہی ماڈل کا استعمال کرتے ہوئے ثبوت تیار کرتے ہیں جن کا اندازہ لگایا جا سکتا ہے۔
یہ ایک اہم تعمیراتی حدود ہے۔ ایگزیکیوٹر کے مخصوص ثبوتوں کو ایگزیکیوٹر کے پاس رکھا جاتا ہے، جبکہ کینونیکل ثبوت تصریح کی پرت سے تعلق رکھتے ہیں۔
تعمیل اور الگ کارکردگی کا ثبوت
عمل کرنے والے کو ثبوت پیش کرنا ہوں گے۔ وضاحتیں اس بات کا تعین نہیں کرنا چاہئے کہ آپریشن کامیاب تھا یا نہیں۔
یہ فرق اتحاد کی دوسری شکل کو روکتا ہے۔
مثال کے طور پر، بچیں:
return {
success: true,
};
عام کامیابی کے جھنڈے ہمیں بہت کم بتاتے ہیں۔
اس کے بجائے ثبوت واپس کریں۔
return {
deployedVersion: "v42",
availableReplicas: 3,
errorRate: 0.004,
p95LatencyMs: 280,
};
پھر ان کا الگ سے جائزہ لیں۔
type ConformanceResult = {
conformant: boolean;
failures: string[];
};
function evaluateConformance(
spec: DeploymentSpec,
evidence: ExecutionEvidence
): ConformanceResult {
const failures: string[] = [];
if (
evidence.deployedVersion !==
spec.version
) {
failures.push(
"wrong-version"
);
}
if (
evidence.availableReplicas <
spec.minReplicas
) {
failures.push(
"insufficient-replicas"
);
}
if (
evidence.errorRate >
spec.maxErrorRate
) {
failures.push(
"error-rate-too-high"
);
}
if (
evidence.p95LatencyMs >
spec.maxP95LatencyMs
) {
failures.push(
"latency-too-high"
);
}
return {
conformant:
failures.length === 0,
failures,
};
}
جائزہ لینے والے کو دو چیزیں دی جاتی ہیں: ایک تصریح جو اس بات کی وضاحت کرتی ہے کہ کیا سچ ہونا چاہیے، اور ثبوت جو اس بات کی وضاحت کرتا ہے کہ اصل میں کیا دیکھا گیا تھا۔
ہر رکاوٹ کو آزادانہ طور پر چیک کیا جاتا ہے۔ ایک غلط ورژن شامل کیا گیا تھا۔ wrong-versionبہت کم نقلیں شامل کی گئی ہیں۔ insufficient-replicasخرابی کی شرح اور تاخیر کی جانچ اسی طرح کام کرتی ہے۔
آخر کار conformant ہے true صرف اس صورت میں جب کوئی ناکامی ریکارڈ نہ ہو۔ انفرادی ناکامی کے ناموں کو واپس کرنا مفید ہے کیونکہ یہ وضاحتی ہے۔ کیوں ہر چیز کو عمومیت پر لانے کے بجائے عمل درآمد پر عمل نہیں کیا گیا۔ false.
اس لیے ایگزیکیوٹر کو حتمی فیصلے کے بجائے حقائق کو واپس کرنا چاہیے۔ اسی شواہد کا بعد کی تاریخ میں دوبارہ جائزہ لیا جا سکتا ہے اگر وضاحتیں تبدیل ہو جائیں، آڈٹ کے لیے تنظیم نو کے فیصلوں کی ضرورت ہو، یا آپ بالکل ایک جیسے اصولوں کا استعمال کرتے ہوئے متعدد ایگزیکیوٹرز کا موازنہ کرنا چاہتے ہوں۔
اب:
executor → evidence
specification + evidence → conformance
یہ علیحدگی بعد میں اہم ہو جاتی ہے۔
مساوی پھانسی کیا سمجھا جاتا ہے؟
یہ ضروری نہیں کہ دو عملدار ایک ہی ثبوت پیش کریں۔ اسے ایسے ثبوت پیش کرنے چاہئیں جو انہی وضاحتوں کو پورا کرتے ہوں۔
فرض کریں:
Executor A
replicas: 3
error rate: 0.4%
latency: 280 ms
Executor B
replicas: 5
error rate: 0.3%
latency: 260 ms
دونوں پاس ہو سکتے ہیں۔
اب فرض کریں کہ ایگزیکٹو بی تیار کرتا ہے:
replicas: 2
error rate: 0.3%
latency: 260 ms
ایک پابندی ناکام ہوجاتی ہے۔
اس کا مطلب ہے:
Executor A:
conformant
Executor B:
non-conformant
ایگزیکیوٹرز اب بھی عمل درآمد کرنے سے آزاد ہیں، لیکن صرف ایک نے اس عمل درآمد کی تفصیلات کو پورا کیا ہے۔
یہ فرق اہم ہے۔
ایگزیکیوٹر کی آزادی ایگزیکیوٹر کی درستگی کی ضمانت نہیں دیتی۔ یہ صرف مستحکم معاہدے فراہم کرتا ہے جن کی درستگی کا اندازہ لگایا جا سکتا ہے۔
جہاں عام طور پر ایگزیکیوٹر کی آزادی ٹوٹ جاتی ہے۔
ناکامی کے کئی عام طریقے ہیں:
تصریحات میں ٹول مخصوص فیلڈز
مثال کے طور پر:
kubernetesNamespace: production
helmChart: orders
اگر یہ واقعی عمل درآمد کی تفصیل ہے، تو یہ آپریشنل تفصیلات میں نہیں ہونی چاہیے۔
ایگزیکیوٹر کی ملکیت میں کامیابی کے اصول
اگر ہر ایگزیکیوٹر اپنی اپنی حد کی وضاحت کرتا ہے، تو تصریح اب قابل اعتبار نہیں رہتی۔
لاپتہ ثبوت کو معمول بنانا
مختلف پریکٹیشنرز مختلف تصورات کو بے نقاب کر سکتے ہیں جو ایک عام ماڈل کا نقشہ نہیں بناتے ہیں۔
پوشیدہ شرائط
ایگزیکٹو A منظوری کی درخواست کر سکتا ہے۔ ایگزیکیوٹر بی نہیں کر سکتا۔
اگر اجازت آپریشنل ارادے کا حصہ ہے، تو اصول صرف ایک ایگزیکیوٹر کے اندر موجود نہیں ہونا چاہیے۔
پوشیدہ بحالی کا سلوک
ایک ایگزیکیوٹر خود بخود پیچھے ہٹ سکتا ہے جبکہ دوسرا ایگزیکیوٹر ناکام حالت کو چلا سکتا ہے۔
اگر بحالی کا رویہ اہم ہے، تو اس توقع کا اظہار تفصیلات میں کیا جانا چاہیے۔
مطلب بے مماثلت
دونوں ٹولز ایک ہی لفظ کو مختلف طریقے سے استعمال کر سکتے ہیں۔
مثال کے طور پر:
healthy
ready
available
running
ان تصورات کو واضح تعریف کی ضرورت ہے۔ بصورت دیگر، ایگزیکیوٹر پورٹیبلٹی سطحی ہے۔
ایگزیکیوٹر پورٹیبلٹی کی جانچ کیسے کریں۔
آپ واضح طور پر ایگزیکیوٹر کی آزادی کی جانچ کر سکتے ہیں۔
وضاحتیں کے ایک سیٹ کے ساتھ شروع کریں۔
مثال کے طور پر:
const cases: DeploymentSpec[] = [
{
service: "orders",
version: "v42",
minReplicas: 3,
maxErrorRate: 0.01,
maxP95LatencyMs: 400,
},
{
service: "payments",
version: "v18",
minReplicas: 5,
maxErrorRate: 0.005,
maxP95LatencyMs: 250,
},
];
اس کے بعد ہم ہر تصریح کو تمام ایگزیکیوٹرز کے خلاف چلاتے ہیں۔
const executors:
DeploymentExecutor[] = [
new RollingDeploymentExecutor(),
new BlueGreenExecutor(),
];
for (const spec of cases) {
for (const executor of executors) {
const evidence =
await executor.execute(spec);
const result =
evaluateConformance(
spec,
evidence
);
console.log({
spec: spec.service,
executor:
executor.constructor.name,
result,
});
}
}
یہ ایک مفید میٹرکس پیدا کرتا ہے۔
Rolling BlueGreen
Orders v42 PASS PASS
Payments v18 PASS FAIL
اب ایگزیکیوٹر پورٹیبلٹی کے ثبوت موجود ہیں۔
یہ فرض کرنے سے کہیں زیادہ طاقتور ہے کہ دونوں ٹولز ایک جیسے ہیں کیونکہ وہ دونوں تعیناتی کی حمایت کرتے ہیں۔
یہ AI ایجنٹوں کے لیے کیوں اہم ہے۔
AI ایجنٹس ایگزیکیوٹر کی آزادی کو مزید دلچسپ بناتے ہیں۔
AI ایجنٹ ہر بار نئے منصوبے بنا سکتے ہیں۔
مثال کے طور پر:
Execution 1:
scale
deploy
verify
route
Execution 2:
create parallel environment
verify
switch traffic
Execution 3:
deploy canary
observe
expand rollout
منصوبے مختلف ہیں اور عمل کرنے والے کا رویہ متحرک ہے۔ یہ قدم بہ قدم مساوات کو غیر حقیقی بناتا ہے۔
تاہم، وضاحتیں اب بھی مستحکم رہ سکتی ہیں۔
مثال کے طور پر:
Deploy Orders v42.
Constraints:
replicas >= 3
error rate <= 1%
latency <= 400 ms
Evidence:
running version
replicas
error rate
latency
AI ایجنٹ ایک قابل قبول پلان کا انتخاب کر سکتا ہے اور اسی معاہدے کا استعمال کرتے ہوئے نتائج کا جائزہ لیا جائے گا۔
اس سے مضبوط سرحدیں بنتی ہیں۔
agent autonomy
inside
operational constraints
ایجنٹ عملدرآمد کو بہتر بنا سکتے ہیں۔ آپ خاموشی سے کامیابی کی نئی تعریف نہیں کر سکتے۔
چھوٹی مثال سے آخر تک
آئیے ٹکڑوں کو ایک ساتھ رکھیں۔
چشمی کے ساتھ شروع کریں.
const spec: DeploymentSpec = {
service: "orders",
version: "v42",
minReplicas: 3,
maxErrorRate: 0.01,
maxP95LatencyMs: 400,
};
دو ایگزیکیوٹرز بنائیں:
const executors:
DeploymentExecutor[] = [
new RollingDeploymentExecutor(),
new BlueGreenExecutor(),
];
چلائیں:
for (const executor of executors) {
const evidence =
await executor.execute(spec);
const conformance =
evaluateConformance(
spec,
evidence
);
console.log(
executor.constructor.name,
evidence,
conformance
);
}
ممکنہ نتائج:
RollingDeploymentExecutor
evidence:
version = v42
replicas = 3
error rate = 0.004
p95 = 280
conformance:
PASS
اور:
BlueGreenExecutor
evidence:
version = v42
replicas = 5
error rate = 0.003
p95 = 260
conformance:
PASS
ایگزیکیوٹرز نے ایسا نہیں کیا، اور انہیں کرنے کی ضرورت نہیں تھی۔ انہوں نے اسی آپریشنل تصریحات کو پورا کیا۔
اب تصور کریں کہ دوسرا ایگزیکیٹر رپورٹ کرتا ہے:
replicas = 2
نتائج درج ذیل ہیں:
BlueGreenExecutor
conformance:
FAIL
reason:
insufficient-replicas
یہ بالکل وہی ہے جو ہم چاہتے ہیں. تفصیلات مستحکم رہتی ہیں اور قابل عمل پروگرام بدل جاتا ہے۔
شواہد سے پتہ چلتا ہے کہ آیا عملدرآمد معاہدے پر پورا اترتا ہے۔
عملی ورک فلو
ایک حقیقی نظام میں ایگزیکیوٹر کی آزادی کو جانچنے کے لیے اس ترتیب کا استعمال کریں۔
1. ایک کام کا انتخاب کریں۔
مثال کے طور پر:
deploy service
restore backup
rotate certificate
scale worker pool
تعریف:
objective
constraints
evidence requirements
recovery expectations
3. ٹول کے ذریعے زبان کو ہٹا دیں۔
تلاش کریں:
kubectl
Terraform
GitHub Actions
AWS CLI
specific resource IDs
صرف وہی رکھیں جو دراصل آپ کے آپریشنل ارادے کا حصہ ہیں۔
4. ایگزیکیوٹر انٹرفیس کی وضاحت کریں۔
اپنے ایگزیکٹو کو ذمہ دار بنائیں:
performing the operation
producing evidence
5. اپنا پہلا اڈاپٹر بنانا
موجودہ نفاذ کو لپیٹیں اور اسے دوبارہ نہ لکھیں۔
6. دوسرا ایگزیکیوٹر بنانا
استعمال کریں:
another tool
another deployment strategy
a simulator
a test double
an AI agent
7. ثبوت کو معمول بنانا
پریکٹیشنر کے مخصوص مشاہدات کو باقاعدہ ثبوت کے ماڈل کے لیے نقشہ بنائیں۔
8. الگ الگ مناسبیت کا اندازہ کریں۔
ایگزیکیوٹر کو یہ فیصلہ نہ کرنے دیں کہ آیا پاس کرنا ہے یا نہیں۔
9. پورٹیبلٹی موازنہ
ایک سے زیادہ ایگزیکیوٹرز کے ذریعے ایک ہی تفصیلات چلائیں۔
10. اختلافات کی چھان بین کریں۔
پوچھیں:
Is the executor wrong?
Is the specification incomplete?
Is evidence missing?
Are the concepts actually equivalent?
یہ اختلافات مفید ہیں۔ پوشیدہ بانڈز کو بے نقاب کریں۔
ایگزیکٹو کی آزادی کا کیا مطلب نہیں ہے۔
ایگزیکیوٹر کی آزادی کا مطلب یہ نہیں ہے کہ تمام ٹولز قابل تبادلہ ہیں۔
ایگزیکیوٹر سے ایگزیکیوٹر میں درج ذیل مختلف ہو سکتے ہیں۔
capabilities
costs
latency
failure modes
security models
operational complexity
تصریح کے لیے فعالیت کی ضرورت ہو سکتی ہے جو ایک واحد قابل عمل پروگرام فراہم نہیں کر سکتا۔
مثال کے طور پر:
zero-downtime deployment
جو ایک پلیٹ فارم پر ممکن ہو سکتا ہے دوسرے پلیٹ فارم پر ممکن نہ ہو۔
یہ تصریح کی ناکامی نہیں ہے۔ یہ مفید معلومات ہے۔ عملدرآمد کنٹریکٹ کو نافذ نہیں کر سکتا۔
ایگزیکیوٹر کی آزادی کا مطلب یہ بھی نہیں ہے کہ نفاذ کی تفصیلات کو نظر انداز کیا جائے۔ نفاذ کی تفصیلات اب بھی اہم ہیں جب:
performance
security
cost
reliability
maintainability
نقطہ تنگ ہے۔ آپریشنل سیمنٹکس کو کسی ایک خاص عمل کے طریقہ کار پر انحصار نہیں کرنا چاہئے۔
سافٹ ویئر کا بنیادی ڈھانچہ مسلسل بدل رہا ہے۔
ٹولز آتے جاتے رہتے ہیں، عمل درآمد کی حکمت عملی تیار ہوتی ہے، کلاؤڈ پلیٹ فارم تبدیل ہوتے ہیں، اور ایجنٹ زیادہ قابل ہو جاتے ہیں۔
آپریشنل ارادے کے ساتھ ہر ایک ایگزیکیوٹر کے اندر سرایت کرنے کے ساتھ، اس بات کا خطرہ ہے کہ کوئی بھی تبدیلی سیمنٹک ہجرت بن جائے گی۔
تاہم، اگر ارادے کا اظہار آزادانہ طور پر کیا جائے:
Operational specification
↓
stable contract
↓
replaceable executor
اس سے نظام کو تیار کرنا آسان ہو جاتا ہے۔
یہ ہمیں کچھ اور بھی دیتا ہے:
evidence from multiple executors
evaluated against the same specification
اس وقت آپ اگلا سوال پوچھنا بند کر سکتے ہیں۔
کیا ٹول ختم ہو گیا ہے؟
اور سوال پوچھنا شروع کریں:
یہ عمل درآمد تصریحات کے مطابق کس حد تک ہوا؟
یہ اگلا مسئلہ ہے۔
نتیجہ
ایگزیکیوٹر کی آزادی کا مطلب یہ نہیں کہ تمام ٹولز ایک جیسے ہیں۔ عمل درآمد کے انحراف سے آپریشنل ارادے کی حفاظت.
تفصیلات وضاحت کرتی ہے:
what should happen
what constraints must hold
what evidence is required
عمل کرنے والا فیصلہ کرتا ہے:
how to make it happen
پھانسی پھر ثبوت پیش کرتی ہے۔ اور شواہد کا آزادانہ اندازہ لگایا جا سکتا ہے۔
یہ ہمیں دیتا ہے:
Specification
↓
Executor A ──→ Evidence A
Executor B ──→ Evidence B
↓
Evaluation
دو عملدرآمد کرنے والے مکمل طور پر مختلف حکمت عملی استعمال کر سکتے ہیں اور پھر بھی ایک ہی آپریٹنگ معاہدے کو پورا کر سکتے ہیں۔
یہ عام آٹومیشن کے لیے ایک مفید پراپرٹی ہے۔
یہ اور بھی اہم ہو جاتا ہے اگر ایگزیکیوٹر ایک خود مختار ایجنٹ ہے جس کا اندرونی منصوبہ ایک عملدرآمد سے دوسرے میں بدل سکتا ہے۔
تاہم، جب متعدد ایگزیکیوٹرز ایک ہی تصریح پر کام کر سکتے ہیں، تو نئے سوالات ناگزیر ہو جاتے ہیں۔
ہم تصریحات کے درمیان فٹ کی پیمائش کیسے کرتے ہیں اور اصل میں کیا ہوتا ہے؟
اسی جگہ میں آگے جانا چاہتا ہوں۔