کلاسز کے ساتھ فنکشنل پاورشیل کوئی آکسیمورون نہیں ہے، میں اس کی ضمانت دیتا ہوں۔

ارے حبر! مضمون کا ترجمہ آپ کی توجہ میں پیش کرتا ہوں۔ "کلاسز کے ساتھ فنکشنل پاور شیل۔
میں وعدہ کرتا ہوں کہ یہ آکسیمورون نہیں ہے"
کرسٹوفر کیچ کے ذریعہ۔

آبجیکٹ اورینٹڈ اور فنکشنل پروگرامنگ پیراڈائمز ایک دوسرے سے متصادم لگ سکتے ہیں، لیکن پاورشیل میں دونوں کو یکساں طور پر تعاون حاصل ہے۔ تقریباً تمام پروگرامنگ زبانیں، فعال ہیں یا نہیں، میں توسیع شدہ نام کی قدر کی پابندی کے لیے سہولیات موجود ہیں۔ کلاسز، جیسے ڈھانچے اور ریکارڈ، صرف ایک نقطہ نظر ہیں۔ اگر ہم کلاسز کے اپنے استعمال کو ناموں اور اقدار کے پابند کرنے تک محدود رکھتے ہیں، اور وراثت، پولیمورفزم، یا تغیر پذیری جیسے بھاری آبجیکٹ پر مبنی پروگرامنگ تصورات سے گریز کرتے ہیں، تو ہم اپنے کوڈ کو پیچیدہ کیے بغیر ان سے فائدہ اٹھا سکتے ہیں۔ مزید، ناقابل تغیر قسم کے تبادلوں کے طریقوں کو شامل کرکے، ہم کلاسز کے ساتھ اپنے فنکشنل کوڈ کو بہتر بنا سکتے ہیں۔

ذاتوں کا جادو

ذات پاورشیل میں سب سے طاقتور خصوصیات میں سے ایک ہے۔ جب آپ کوئی قدر ڈالتے ہیں، تو آپ ان مضمر ابتدا اور توثیق کی صلاحیتوں پر انحصار کرتے ہیں جو ماحول آپ کی درخواست میں اضافہ کرتا ہے۔ مثال کے طور پر، صرف [xml] میں سٹرنگ کاسٹ کرنے سے یہ پارسر کوڈ کے ذریعے چلائے گا اور ایک مکمل XML ٹری تیار کرے گا۔ ہم اسی مقصد کے لیے اپنے کوڈ میں کلاسز استعمال کر سکتے ہیں۔

ہیش ٹیبل کاسٹ کریں۔

اگر آپ کے پاس کنسٹرکٹر نہیں ہے تو آپ اپنی کلاس کی قسم میں ہیش ٹیبل کاسٹ کر کے بغیر کسی کے جاری رکھ سکتے ہیں۔ اس پیٹرن کا پورا فائدہ اٹھانے کے لیے توثیق کی خصوصیات کو استعمال کرنا نہ بھولیں۔ ایک ہی وقت میں، ہم کلاس کی ٹائپ کردہ خصوصیات کو اور بھی گہری ابتدا اور توثیق کی منطق کو چلانے کے لیے استعمال کر سکتے ہیں۔

class Cluster {
    [ValidatePattern("^[A-z]+$")]
    [string] $Service
    [ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
    [string] $FlightingRing
    [ValidateSet("EastUS", "WestUS", "NorthEurope")]
    [string] $Region
    [ValidateRange(0, 255)]
    [int] $Index
}

[Cluster]@{
    Service       = "MyService"
    FlightingRing = "PROD"
    Region        = "EastUS"
    Index         = 2
}

اس کے علاوہ، کاسٹنگ صاف آؤٹ پٹ حاصل کرنے میں مدد کرتی ہے۔ فارمیٹ ٹیبل میں پاس ہونے والے کلسٹر ہیش ٹیبل سرنی کے آؤٹ پٹ کا موازنہ کریں اگر آپ ان ہیش ٹیبلز کو پہلے کلاس میں ڈالتے ہیں تو آپ کو کیا ملتا ہے۔ کلاس کی خصوصیات ہمیشہ اس ترتیب میں درج ہوتی ہیں جس میں وہ وہاں بیان کیے گئے ہیں۔ ان تمام خصوصیات سے پہلے پوشیدہ کلیدی لفظ شامل کرنا نہ بھولیں جو آپ نتائج میں نظر نہیں آنا چاہتے۔

کلاسز کے ساتھ فنکشنل پاورشیل کوئی آکسیمورون نہیں ہے، میں اس کی ضمانت دیتا ہوں۔

معانی کی کاسٹ

اگر آپ کے پاس ایک دلیل والا کنسٹرکٹر ہے تو، آپ کی کلاس کی قسم میں قدر کاسٹ کرنے سے وہ قدر آپ کے کنسٹرکٹر تک پہنچ جائے گی، جہاں آپ اپنی کلاس کی ایک مثال شروع کر سکتے ہیں۔

class Cluster {
    [ValidatePattern("^[A-z]+$")]
    [string] $Service
    [ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
    [string] $FlightingRing
    [ValidateSet("EastUS", "WestUS", "NorthEurope")]
    [string] $Region
    [ValidateRange(0, 255)]
    [int] $Index

    Cluster([string] $id) {
        $this.Service, $this.FlightingRing, $this.Region, $this.Index = $id -split "-"
    }
}

[Cluster]"MyService-PROD-EastUS-2"

لائن پر کاسٹ کریں۔

آپ آبجیکٹ کی سٹرنگ کی نمائندگی کے پیچھے منطق کی وضاحت کرنے کے لیے [string] ToString() کلاس طریقہ کو بھی اوور رائیڈ کر سکتے ہیں، جیسے کہ سٹرنگ انٹرپولیشن کا استعمال۔

class Cluster {
    [ValidatePattern("^[A-z]+$")]
    [string] $Service
    [ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
    [string] $FlightingRing
    [ValidateSet("EastUS", "WestUS", "NorthEurope")]
    [string] $Region
    [ValidateRange(0, 255)]
    [int] $Index

    [string] ToString() {
        return $this.Service, $this.FlightingRing, $this.Region, $this.Index -join "-"
    }
}

$cluster = [Cluster]@{
    Service       = "MyService"
    FlightingRing = "PROD"
    Region        = "EastUS"
    Index         = 2
}

Write-Host "We just created a model for '$cluster'"

سیریلائزڈ مثالیں کاسٹ کریں۔

کاسٹ محفوظ ڈیسیریلائزیشن کی اجازت دیتا ہے۔ ذیل کی مثالیں ناکام ہو جائیں گی اگر ڈیٹا کلسٹر میں ہماری تفصیلات کو پورا نہیں کرتا ہے۔

# Валидация сериализованных данных

[Cluster]$cluster = Get-Content "./my-cluster.json" | ConvertFrom-Json
[Cluster[]]$clusters = Import-Csv "./my-clusters.csv"

آپ کے فنکشنل کوڈ میں ذاتیں۔

فنکشنل پروگرام پہلے ڈیٹا ڈھانچے کی وضاحت کرتے ہیں، پھر اس پروگرام کو ناقابل تغیر ڈیٹا ڈھانچے پر تبدیلیوں کی ترتیب کے طور پر نافذ کرتے ہیں۔ متضاد تاثرات کے باوجود، کلاسیں واقعی آپ کو فنکشنل کوڈ لکھنے میں مدد کرتی ہیں جس کی بدولت تبادلوں کے طریقے ٹائپ کرتے ہیں۔

کیا میں جو پاورشیل لکھ رہا ہوں وہ فعال ہے؟

C# یا اسی طرح کے پس منظر سے آنے والے بہت سے لوگ Powershell لکھ رہے ہیں، جو C# سے ملتا جلتا ہے۔ ایسا کرنے سے، آپ فنکشنل پروگرامنگ کے تصورات کو استعمال کرنے سے دور ہو رہے ہیں اور ممکنہ طور پر پاورشیل میں آبجیکٹ اورینٹڈ پروگرامنگ میں بہت زیادہ غوطہ لگانے یا فنکشنل پروگرامنگ کے بارے میں مزید سیکھنے سے فائدہ اٹھائیں گے۔

اگر آپ پائپ لائنز (|)، Where-Object، ForEach-Object، Select-Object، Group-Object، Sort-Object، وغیرہ کا استعمال کرتے ہوئے ناقابل تغیر ڈیٹا کو تبدیل کرنے پر بہت زیادہ انحصار کرتے ہیں تو - آپ کا انداز زیادہ فعال ہے اور آپ پاورشیل کے استعمال سے فائدہ اٹھائیں گے۔ فنکشنل انداز میں کلاسز۔

کلاسوں کا فنکشنل استعمال

ذاتیں، اگرچہ وہ ایک متبادل نحو استعمال کرتی ہیں، دو ڈومینز کے درمیان صرف ایک نقشہ سازی ہیں۔ پائپ لائن میں، آپ ForEach-Object کا استعمال کرتے ہوئے قدروں کی ایک صف کا نقشہ بنا سکتے ہیں۔

نیچے دی گئی مثال میں، نوڈ کنسٹرکٹر کو ہر بار جب ڈیٹم کاسٹ کیا جاتا ہے تو اس پر عمل درآمد ہوتا ہے، اور اس سے ہمیں مناسب مقدار میں کوڈ نہ لکھنے کا موقع ملتا ہے۔ نتیجے کے طور پر، ہماری پائپ لائن اعلانیہ ڈیٹا کے استفسار اور جمع کرنے پر توجہ مرکوز کرتی ہے، جبکہ ہماری کلاسیں ڈیٹا کی تجزیہ اور توثیق کا خیال رکھتی ہیں۔

# Пример комбинирования классов с конвейерами для separation of concerns в конвейерах

class Node {
    [ValidateLength(3, 7)]
    [string] $Name
    [ValidateSet("INT", "PPE", "PROD")]
    [string] $FlightingRing
    [ValidateSet("EastUS", "WestUS", "NorthEurope", "WestEurope")]
    [string] $Region
    Node([string] $Name) {
        $Name -match "([a-z]+)(INT|PPE|PROD)([a-z]+)"
        $_, $this.Service, $this.FlightingRing, $this.Region = $Matches
        $this.Name = $Name
    }
}

class Datum {
    [string] $Name
    [int] $Value
    [Node] $Computer
    [int] Severity() {
        $this.Name -match "[0-9]+$"
        return $Matches[0]
    }
}

Write-Host "Urgent Security Audit Issues:"
Import-Csv "./audit-results.csv" `
    | ForEach-Object {[Datum]$_} `
    | Where-Object Value -gt 0 `
    | Group-Object {$_.Severity()} `
    | Where-Object Name -lt 2 `
    | ForEach-Object Group `
    | ForEach-Object Computer `
    | Where-Object FlightingRing -eq "PROD" `
    | Sort-Object Name, Region -Unique

دوبارہ استعمال کے لیے پیکیجنگ کلاس

کچھ بھی اتنا اچھا نہیں جتنا لگتا ہے۔

بدقسمتی سے، کلاسز کو ماڈیولز کے ذریعے اس طرح برآمد نہیں کیا جا سکتا جس طرح فنکشنز یا متغیرات؛ لیکن کچھ چالیں ہیں. فرض کریں کہ آپ کی کلاسز فائل ./my-classes.ps1 میں بیان کی گئی ہیں۔

  • آپ کلاسز کے ساتھ فائل کو ڈاٹ سورس کر سکتے ہیں:۔ ./my-classes.ps1۔ یہ آپ کے موجودہ دائرہ کار میں my-classes.ps1 کو انجام دے گا اور وہاں موجود فائل سے تمام کلاسز کی وضاحت کرے گا۔

  • آپ ایک Powershell ماڈیول بنا سکتے ہیں جو آپ کے تمام حسب ضرورت APIs (cmdlets) کو برآمد کرتا ہے اور اسی نتیجے کے ساتھ، آپ کے ماڈیول مینی فیسٹ میں ScriptsToProcess = "./my-classes.ps1" متغیر سیٹ کر سکتے ہیں: ./my-classes.ps1 اس میں عمل کرے گا۔ آپ کا ماحول

آپ جو بھی آپشن منتخب کریں، ذہن میں رکھیں کہ پاورشیل کا ٹائپ سسٹم مختلف جگہوں سے لوڈ کردہ ایک ہی نام کی اقسام کو حل نہیں کر سکتا۔
یہاں تک کہ اگر آپ نے مختلف جگہوں سے ایک جیسی خصوصیات کے ساتھ دو ایک جیسی کلاسیں لوڈ کی ہیں، تو آپ کو پریشانیوں میں پڑنے کا خطرہ ہے۔

آگے بڑھنے کا راستہ

قسم کے حل کے مسائل سے بچنے کا بہترین طریقہ یہ ہے کہ اپنی کلاسوں کو صارفین کے سامنے کبھی بھی ظاہر نہ کریں۔ صارف سے کلاس کی طے شدہ قسم کو درآمد کرنے کی توقع کرنے کے بجائے، اپنے ماڈیول سے ایک فنکشن برآمد کریں جو براہ راست کلاس تک رسائی کی ضرورت کو ختم کرتا ہے۔ کلسٹر کے لیے، ہم ایک نیا-کلسٹر فنکشن برآمد کر سکتے ہیں جو صارف کے موافق پیرامیٹر سیٹس کو سپورٹ کرے گا اور کلسٹر واپس کرے گا۔

class Cluster {
    [ValidatePattern("^[A-z]+$")]
    [string] $Service
    [ValidateSet("TEST", "STAGE", "CANARY", "PROD")]
    [string] $FlightingRing
    [ValidateSet("EastUS", "WestUS", "NorthEurope")]
    [string] $Region
    [ValidateRange(0, 255)]
    [int] $Index
}

function New-Cluster {
    [OutputType([Cluster])]
    Param(
        [Parameter(Mandatory, ParameterSetName = "Id", Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string] $Id,
        [Parameter(Mandatory, ParameterSetName = "Components")]
        [string] $Service,
        [Parameter(Mandatory, ParameterSetName = "Components")]
        [string] $FlightingRing,
        [Parameter(Mandatory, ParameterSetName = "Components")]
        [string] $Region,
        [Parameter(Mandatory, ParameterSetName = "Components")]
        [int] $Index
    )

    if ($Id) {
        $Service, $FlightingRing, $Region, $Index = $Id -split "-"
    }

    [Cluster]@{
        Service       = $Service
        FlightingRing = $FlightingRing
        Region        = $Region
        Index         = $Index
    }
}

Export-ModuleMember New-Cluster

اور کیا پڑھنا ہے۔

کلاسز کے بارے میں
دفاعی پاور شیل
پاور شیل میں فنکشنل پروگرامنگ

ماخذ: www.habr.com

نیا تبصرہ شامل کریں