Begin/Process/End or Process only. No Process/End, Begin/End, Begin/Process. #182
Replies: 8 comments 1 reply
-
The documentation is incorrect and that should be fixed, not this guide. The documentation also contradicts itself a bit on this point, which to my mind reinforces the need to correct the documentation. It includes the following assertion:
Raised PR: MicrosoftDocs/PowerShell-Docs#10521 |
Beta Was this translation helpful? Give feedback.
-
The documentation may be incorrect about what is technically possible, but that does not mean that is not stylistically ideal. Why would you only have an end block? Would it not be better to just have no begin/process/end blocks in that case? Why would you only have a begin block? Would it not be better to just have no begin/process/end blocks in that case? Supposedly you need a process block to iterate pipeline objects (happy to be wrong there) and that is the minimum of what is needed, but you don't have to define begin/end blocks to use a function nor do they add meaningful clarity if used by themselves. There are many things that are technically possible but not stylistically ideal. |
Beta Was this translation helpful? Give feedback.
-
I don't really understand your point. But I do want to be clear at the outset I'm treating this as a problem of two halves:
1. Changes to suggested styleI strongly suggest you highlight the part of this guide you think should change, and comment based on that. You cite MS docs, but not really how it applies to the guide, or really what you want changed in this guide. Is your comment directed at this statement? It is fine to disagree with the style guide and to propose change. Style is inherently opinionated. We (or others) may end up not agreeing, but that's the nature of opinion and that outcome is fine.
I regard this as fair comment. I would, personally, not have an
I have no use case for this, but they are not technically equivalent. I cannot imagine a use-case for this, but I would not seek to restrict based on my lack of imagination. But I cannot find any part of the guide that asserts use of
You can technically do it all in Are you suggesting that when I have 2. The about_ documentAbout documents are technical documents, not style guides. The highlighted assertion, which I have corrected by the (merged) PR linked above, is:
This is framed as a technical requirement ("requires that you"), not a style choice. It tells me that if I want to do this: function Write-Number {
param (
[Parameter(ValueFromPipeline)]
[int]
$Number
)
process {
Write-Host $Number
}
} That I would in fact have to do this: function Write-Number {
param (
[Parameter(ValueFromPipeline)]
[int]
$Number
)
begin {}
process {
Write-Host $Number
}
end {}
} Implying my first block would not work because I had omitted the two blocks I wasn't using. Since this asserted technical requirement is incorrect I raised a (now merged) fix for that. |
Beta Was this translation helpful? Give feedback.
-
Let's refer back to the document a few times then I'll go with some examples. If you do not use any blocks then everything is automatically put into an end block. This is stated in the document:
So we know we do not need to use an end block if we do not need to use other blocks.
The process block is required for processing objects via the pipeline. It does not require begin/end blocks. What does this mean? This means that this is redundant for a regular function: function Write-Number {
param (
[int]$Number
)
end {
Write-Host $Number
}
} And this is more straightforward for a regular function: function Write-Number {
param (
[int]$Number
)
Write-Host $Number
} You would also never do this: function Write-Number {
param (
[int]$Number
)
begin {
Write-Host $Number
}
} For processing items via the pipeline, your first example is ideal for the minimum needed for a function for pipeline input: function Write-Number {
param (
[Parameter(ValueFromPipeline)]
[int]$Number
)
process {
Write-Host $Number
}
} However if you're going to use begin/end blocks then you would likely be setting something up to either return or tear down later like: function Write-Number {
param (
[Parameter(ValueFromPipeline)]
[int]$Number
)
begin {
$Numbers = @()
process {
$Numbers += $Number
}
end {
return $Numbers
}
} The order of preference for the blocks should be: The last one is the one most easily debatable. I hope I have shown why you usually would not want to use begin/end blocks and if you do then they should be used with process, but process can be used all by itself. It usually should be. |
Beta Was this translation helpful? Give feedback.
-
You need to associate the comments above with the parts of the guide that you'd like to see changed. As I said above, it's fine to suggest change where you have a good case for that. However, someone needs to write that change into the guide. Having an idea of what specifically should change is critical. You can, of course, raise a pull request of your own to suggest change. I personally would disagree with the order of preference as written (the final "All blocks"). For example, I might contrive a function whose only job is to add a value to the end of a pipeline: function Write-Number {
param (
[Parameter(ValueFromPipeline)]
[int]$Number
)
process {
$Number
}
end {
9999
}
} I don't wish to pretend this is a good function, but I don't need Similarly, I might want to include My own guidance would therefore be:
I have custom script analyzer rules that check for use of That's my own though, it is how I write my code now. My own preference does not necessarily need to line up with the style guide and does necessarily affect suggestions you might make. |
Beta Was this translation helpful? Give feedback.
-
I'm not sure what the debate is now. The original quote was simply, factually, wrong:
For what it's worth, I agree that there is probably no reason to write just a begin block instead of just an end block -- but if you don't handle pipeline input, it basically makes no difference. I also agree with @indented-automation that I prefer using the implicit blocks -- although my sense is that the PowerShell community tends to prefer explicit blocks "for clarity," and for the sake of people unfamiliar with the |
Beta Was this translation helpful? Give feedback.
-
I agree with @indented-automation and @Jaykul. It sounds like the only reason to require a begin block if you have an end block is because the most of the scenarios (that we can imagine) need it...
So it's a moot point. If it helps though, an example scenario where we may want a begin or end block without the other would be logging. E.g. Function Invoke-Example {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[string]$TextTemplate
,
[Parameter(ValueFromPipeline)]
[int[]]$Number
)
Begin {
Write-Verbose "Invoke-Example called with TextTemplate: [$TextTemplate]"
}
Process {
foreach ($aNumber in $Number) {
$TextTemplate -f $aNumber
}
}
} There is already a rule stating that we should always have a process block. That seems reasonable as if we're taking pipeline input, we'll generally want to process it. There are cases where we may have a function taht only cares about the last item in the pipeline; but those are rare enough that it's not worth debating existing guideline. If we want to put any additional style guide rules here, maybe a good rule is "Always use a named block rather than relying on the default block behaviour".
However, whilst we have the rule that we should always have an explicit |
Beta Was this translation helpful? Give feedback.
-
I personally Always use all 3 blocks BEGIN {} Adding all 3 blocks aren't that big a deal. It makes it more readable, and as the documentation says,it is used for "advanced function" and is not needed if it is just a "function" |
Beta Was this translation helpful? Give feedback.
-
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced_methods?view=powershell-7.3
Pretty straight forward. Microsoft states:
The examples in the style guide do not fit Microsoft's recommendation.
Beta Was this translation helpful? Give feedback.
All reactions