Сыныптары бар функционалды Powershell оксиморон емес, мен оған кепілдік беремін

Эй Хабр! Назарларыңызға мақаланың аудармасын ұсынамын «Сыныптары бар функционалды PowerShell.
Мен бұл оксиморон емес деп уәде беремін»
авторы Кристофер Куч.

Нысанға бағытталған және функционалды бағдарламалау парадигмалары бір-біріне қайшы көрінуі мүмкін, бірақ екеуіне де PowerShell бағдарламасында бірдей қолдау көрсетіледі. Функционалды немесе функционалды емес дерлік барлық бағдарламалау тілдері атау-мәнді байланыстыруды ұсынады; құрылымдар мен жазбалар сияқты сыныптар бір ғана тәсіл. Класстарды атау-мәнді байланыстыру үшін пайдалануды шектеу және мұрагерлік, полиморфизм немесе өзгергіштік сияқты ауыр салмақты нысанға бағытталған бағдарламалау тұжырымдамаларынан аулақ болу арқылы біз кодымызды қиындатпай олардың артықшылықтарын пайдалана аламыз. Сонымен қатар, түрлендірудің өзгермейтін әдістерін қосу арқылы біз функционалды кодымызды сыныптармен байыта аламыз.

Каста сиқыры

Трансляциялар PowerShell ішіндегі ең қуатты мүмкіндіктердің бірі болып табылады. Мәнді шығарған кезде, орта қолданбаға қосатын жасырын инициализация және тексеру мүмкіндіктеріне сүйенесіз. Мысалы, жай ғана жолды [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
}

Сонымен қатар, құю таза өнім шығаруға көмектеседі. Формат-кестеге берілген хэш кестелерінің кластер массивінің шығысын осы хэш кестелерді алдымен сыныпқа шығарсаңыз, алатындарыңызбен салыстырыңыз. Класс сипаттары әрқашан анықталған ретпен тізімделеді. Шығаруда көрінгіңіз келмейтін кез келген сипаттардың алдында жасырын кілт сөзді қосуды ұмытпаңыз.

Сыныптары бар функционалды Powershell оксиморон емес, мен оған кепілдік беремін

Құндылықтар кастасы

Егер сізде бір аргументі бар конструктор болса, мәнді сынып түріне шығару мәнді конструкторға береді, онда сыныптың данасын инициализациялауға болады.

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"

Функционалдық кодыңызда трансляциялар

Функционалды бағдарламалар алдымен деректер құрылымдарын анықтайды, содан кейін бағдарламаны өзгермейтін деректер құрылымдарындағы түрлендірулер тізбегі ретінде жүзеге асырады. Қарсы әсерге қарамастан, сыныптар түр түрлендіру әдістерінің арқасында функционалдық кодты жазуға көмектеседі.

Мен функционалды Powershell жазамын ба?

C# немесе ұқсас фоннан шыққан көптеген адамдар C# тіліне ұқсас PowerShell жазады. Осылайша сіз функционалдық бағдарламалау тұжырымдамаларынан бас тартасыз және PowerShell бағдарламасында объектіге бағытталған бағдарламалауды тереңірек меңгеру немесе функционалдық бағдарламалау туралы көбірек білу пайдалы болуы мүмкін.

Түтіктер (|), Қайда-Нысан, ForEach-Нысан, Таңдау-Объект, Топ-Объект, Сұрыптау-Объект, т.б. арқылы өзгермейтін деректерді түрлендіруге қатты сенсеңіз, сізде функционалдық мәнер болады және функционалдық стильдегі Powershell сыныптарын пайдаланудың пайдасын көресіз.

Сыныптардың функционалдық қолданылуы

Трансляциялар, олар баламалы синтаксисті пайдаланса да, екі домен арасындағы салыстыру болып табылады. Құбырда 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 файлын орындайды және файлдағы барлық сыныптарды анықтайды.

  • Сіз барлық теңшелетін API интерфейстерін (командлеттер) экспорттайтын Powershell модулін жасай аласыз және модульдің манифестінде ScriptsToProcess = "./my-classes.ps1" айнымалы мәнін орната аласыз, сол нәтижемен: ./my-classes.ps1 ортаңызда орындалады.

Қай опцияны таңдасаңыз да, PowerShell түрі жүйесі әртүрлі орындардан жүктелген бірдей атаудағы түрлерді шеше алмайтынын есте сақтаңыз.
Әртүрлі жерлерден бірдей сипаттары бар екі бірдей сыныпты жүктеп алсаңыз да, сізде проблемалар туындау қаупі бар.

Алға жол

Түрді ажырату мәселелерін болдырмаудың ең жақсы жолы - сыныптарыңызды ешқашан пайдаланушыларға көрсетпеу. Пайдаланушылар сыныпта анықталған түрді импорттауын күтудің орнына, сыныпқа тікелей қатынасу қажеттілігін болдырмайтын модульден функцияны экспорттаңыз. Кластер үшін пайдаланушыға ыңғайлы параметрлер жиынын қолдайтын және кластерді қайтаратын Жаңа кластер функциясын экспорттай аламыз.

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

Тағы не оқу керек

Сабақтар туралы
Қорғаныс PowerShell
PowerShell бағдарламасындағы функционалды бағдарламалау

Ақпарат көзі: www.habr.com

DDoS қорғауы бар сайттар үшін сенімді хостинг, VPS VDS серверлерін сатып алыңыз 🔥 DDoS қорғанысы, VPS VDS серверлері бар сенімді веб-сайт хостингін сатып алыңыз | ProHoster