Jump to content

PS - Schlüsselwort OutputType


Direkt zur Lösung Gelöst von cj_berlin,

Empfohlene Beiträge

Zur Zeit lese ich das Buch Building Better PowerShell Code. Im Kapitel 9 schreibt der Autor, dass man immer den Ausgabetypen einer Funktion definieren soll. Der tatsächliche Ausgabetyp kann sich doch von meiner Definition unterscheiden. Deshalb verstehe ich absolut nicht, warum diese Vorgehensweise empfohlen wird. Mich verwirrt es eher anstatt das es hilft, weil der Rückgabewert ein anderer sein kann als den ich erwarte.

 

Vielleicht kann mir jemand erklären, warum die Definition eines Outputtyps zu den Best Practice gehört. Siehe auch Function Structure

 

Beispiel aus dem Buch

function Get-File {
    [OutputType([System.String])]
    param(
        [Parameter()]
        [string]$FilePath
    )

    Get-Item -Path $FilePath
}

(Get-File -FilePath C:\foo.txt).GetType().FullName
# Output: System.IO.FileInfo

(Get-Command Get-File).OutputType.Name
# Output: System.String

(Get-File -FilePath C:\foo.txt).<tab>
# Tabvervollständig listet die Eigenschaften und Methoden der Stringklasse auf

 

Link zu diesem Kommentar
  • Beste Lösung

Moin,

 

erstens, bei all seinen Verdiensten für die PowerShell-Community, ist nicht alles, was Adam Bertram sich überlegt hat, als "best practice" zu bezeichnen. Zweitens, es gibt sehr viele Entwickler, die zu PowerShell nicht von CMD/VBS/bash, sondern von C++/C#/etc. gekommen sind, wo starke Typdefinitionen vorgeschrieben sind. Diese Leute versuchen, das Bekannte auch in PowerShell durchzusetzen, meistens mit mäßigem Erfolg, weil PowerShell sich strikt weigert, ein "strongly typed language" zu werden.

 

WENN Deine Funktion immer denselben Typ zurückgibt, kann es IntelliSense verbessern, wie Du auch bemerkt hast, wenn Du diesen auch in der Definition der Funktion angibst.

 

Wer funktionale Programmierung lange und in großem Stil betrieben hat, wird vermutlich zustimmen, dass es an sich eine sehr gute Idee ist, wenn jede Funktion immer den gleichen Ergebnistyp zurückgibt. Das schreibt auch Uncle Bob irgendwo in "Clean Code", wenn ich mich recht erinnere. Nur ist es in Skriptsprachen in der Regel eher hinderlich, solche Restriktionen aufzuerlegen. Aber wenn Dein Skript- oder Moduldesign das hergibt, gibt es Dir ein zusätzliches Quentchen Sicherheit, wenn Du weißt, was Du von welcher Funktion zurück bekommst.

bearbeitet von cj_berlin
Link zu diesem Kommentar

@cj_berlin

Vielen Dank für Deine ausführliche Erklärung. Man merkt sehr gut, dass bei der Entwicklung von PowerShell darauf geachtet wurde, Administratoren und Entwickler gleicher Maßen anzusprechen. 

 

Also muss ich als Entwickler der Funktion sicherstellen, dass der/die richtige(n) Rückgabetype(n) bei OutputType angegeben wird/werden. Eine Überprüfung findet (leider) durch den PowerShell-Interpreter nicht statt. 

 

Da ich in unserem Team der Einzige bin, der PowerShell nutzt, möchte ich möglichst viele Best Practice umsetzen und den Code möglichst sicher machen. Zum Beispiel typisiere ich bereits alle Variablen. Was leider etwas zur Lasten der Lesbarkeit geht, wenn die Typennamen besonders lang sind. Da muss ich noch einen vernünftigen Mittelweg finden.

Link zu diesem Kommentar

Das Typisieren hat Vor- und Nachteile. Einer der größten Vorteile - für mich und wenn möglich - ist das Typisieren von Input-Parametern. Wenn Du da passende Enums findest, gibt es Intellisense vom feinsten :-)  Leider muss aber ggf. das passende Asssembly vorher geladen sein. Alles nicht so einfach 😂 Und bei den Outputs, ja ein wenig Intellisense gibt es da dann auch dazu.

 

Die Typ-Namen kannst Du - wenn erforderlich - durch using-Direktiven verkürzen, aber das verbessert die Lesbarkeit nur teilweise, weil man jetzt halt wissen muss, zu welchem Namespace der Typ gehört.

Link zu diesem Kommentar
vor 13 Stunden schrieb daabm:

ist das Typisieren von Input-Parametern.

Ich dachte immer, dass es ein Muss ist, die Input-Parameter zu typisieren. Ich glaube, dass ich noch nie ein Beispiel ohne Parametertypisierung gesehen habe.

 

vor 13 Stunden schrieb daabm:

Die Typ-Namen kannst Du - wenn erforderlich - durch using-Direktiven verkürzen, aber das verbessert die Lesbarkeit nur teilweise, weil man jetzt halt wissen muss, zu welchem Namespace der Typ gehört.

Vielen Dank. Die using-Anweisung kannte ich nur im Zusammenhang, um eine lokale Variable in einem Remotebefehl zu verwenden.

Link zu diesem Kommentar

Naja, kommt drauf an was Du unter "Typisieren" da genau verstehst :-) Ich seh oft [String] oder vielleicht noch [Int], das ist für mich keine echte Typisierung.

Ich mach viel mit GPOs, in manchen Skripts/Funktionen gibt es da Parameter wie

[Microsoft.GroupPolicy.GPOStatus] $Status

Der Typ ist ein Enum, und das hat dann echten Mehrwert (Tab-Expansion und automatisches ValidateSet). Und bei echten Objekten wie

[Microsoft.GroupPolicy.GPO] $SourceGPO

natürlich auch. Zweiteres würden die meisten aber wohl als [String] machen.

bearbeitet von daabm
Link zu diesem Kommentar
Am 6.12.2024 um 18:19 schrieb daabm:

Naja, kommt drauf an was Du unter "Typisieren" da genau verstehst :-)

Unter Typsisien verstehe ich, dass ich der Variable bzw. dem Paramteter den korrekten Datentypen zuweise.  In der Regel mache ich mir die Mühe, den "richtigen" Datentypen zu ermitteln. Hierfür verwende ich die Eigenschaft <Object>.GetType().Fullname oder schaue in die Online-.NET Dokumentation nach.

 

Mir ist es schon wichtig den "richtigen" Datentypen zu verwenden. GPO-Objekt an eine Funktion übergebe, die einen [String] erwartet, und das übergebene GPO-Objekt fehlerfrei in eine Zeichenkette konvertiert werden konnte, dann fehlen mir alle Eigenschaften und Methoden des GPO-Klasse und ich habe "nur" noch eine Zeichenkette.

 

Link zu diesem Kommentar

Dann machst Du da schon mal mehr als ganz viele andere :-) Gut so!

 

Das korrekte Typing hat ja mehr Vorteile als nur "alle Objekteigenschaften" - es ist die erste "Hürde" der Parameter Validation, und wenn die genommen ist (das Input-Objekt hat den richtigen Typ), ist auch die zweite Validierung (z.B. auf korrekte Inhalte bestimmter Properties oder deren Übereinstimmung mit bestimmten Enums) deutlich einfacher als wenn da einfach nur ein String daherkommt.

 

Und weil ich oft mit AD-Objekten zu tun habe. Es erspart einem auch das Holen des "eigentlichen" Objekts, nur weil ein AD-User als [String] typisiert wurde und dadurch zum Distinguished Name degradiert, zu dem ich dann _noch mal_ das vollständige Objekt aus AD holen muss.

Link zu diesem Kommentar

Schreibe einen Kommentar

Du kannst jetzt antworten und Dich später registrieren. Falls Du bereits ein Mitglied bist, logge Dich jetzt ein.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor-Fenster leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...