-
Notifications
You must be signed in to change notification settings - Fork 288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to deal with a module that contains multiple interdependent classes? #185
Comments
Single file is the best practice, due to all the issues involved with classes that likely will never be fixed because classes were originally intended just as a framework to make implementing DSC resources easier and not meant to be general purpose. If you use a tool like VSCode, you have the ability to jump to definition and use the Outline view to more effectively manage this single file. In PowerShell, you should generally use classes just for object modeling and intellisense, and only add methods that:
Everything else should be done in functions, do not put business logic into methods. If this is what you want to do, write it in C#/F# and import it to your module as an assembly instead. |
@JustinGrote, thanks for you guidelines, the "class issues" and the VSCode Outline View referral.
Meanwhile I have 4 ( Anyways, I don't have enough knowledge of C# (and zero of F#) to do the same in one of these languages 😞. |
Yeah, like Justin said, at runtime, any PowerShell classes that you want to expose outside your module (whether as parameters or outputs) basically have to be defined within the root module -- the main psm1 file. You don't necessarily have to author them that way, if you merge them for publishing -- the discussion in #59 (which we moved to #171) resulted in the PoshCode/ModuleBuilder project, which works well for that. However, the PowerShell editor in VSCode still doesn't automatically see types from other files (even when you open a folder), and the way they run PSScriptAnalyzer means it will complain about it, if your classes reference each other... |
While I don't have any facts to back this up I would be surprised if there was any major difference between a cmdlet and a PowerShell class method. When you define a PowerShell class the underlying .NET IL code is essentially just invoking the ScriptBlock of the method which is essentially what a function is. For example class MyClass {
[string]Method([string]$Foo) {
return $Foo
}
}
$c = [MyClass]::new()
$c.Method('test') Calling $sbk = {
param([string]$Foo)
return $Foo
}
$sbk.Invoke('test') It is definitely more complicated than that psuedo code but the general workflow applies. A function is a scriptblock so it has a very similar behaviour when it comes to invoking them. If you have recursion you should probably want to avoid that type of logic in favour of things like stacks/queues/loops. |
$Iterations = 10
$MaxDepth = 6
class MyClass {
static $Iterations = 10
static $MaxDepth = 6
Method([int]$Depth) {
if ($Depth -ge [MyClass]::MaxDepth) { return }
$NewDepth = $Depth + 1
for ($i = 0; $i -lt [MyClass]::Iterations; $i++) {
# Write-Host $i 'Depth:' $Depth
$this.Method($NewDepth)
}
}
}
@{
Class = (Measure-Command {
[MyClass]::Iterations = $Iterations
[MyClass]::MaxDepth = $MaxDepth
$c = [MyClass]::new()
$c.Method(0)
}).TotalMilliseconds
}
$sbk = {
param([int]$Depth)
if ($Depth -ge $MaxDepth) { return }
$NewDepth = $Depth + 1
for ($i = 0; $i -lt $Iterations; $i++) {
# Write-Host $i 'Depth:' $Depth
$sbk.Invoke($NewDepth)
}
}
@{
ScriptBlock = (Measure-Command {
$sbk.Invoke(0)
}).TotalMilliseconds
} Name Value
---- -----
Class 2797.1561
ScriptBlock 4784.1456 Both examples iterate |
Correct, WikiPedia quote:
Meaning that for complex problems you not only need to handle the call stack but also isolate the variables in the current function scope (as the |
Related to issue #59, for my ObjectGraphTools project, I would like to separate my interdependent classes contained by a single file over multiple files to make my module better manageable.
Is there any recommended best practice for this issue?
For details, see: https://stackoverflow.com/questions/68657692/is-it-possible-to-declare-two-interdependent-classes-each-in-a-separate-file
The text was updated successfully, but these errors were encountered: