Powershell 源码批判

代码里充斥着过程式编程的搞法:比如这里 Utils.PathIsUnc,分散的到处都是

internal static IEnumerable<string> GetDefaultAvailableModuleFiles(string topDirectoryToCheck)
        {
            if (!Directory.Exists(topDirectoryToCheck)) { yield break; }

            var options = Utils.PathIsUnc(topDirectoryToCheck) ? s_uncPathEnumerationOptions : s_defaultEnumerationOptions;

面向对象架构打的很烂。powershell 的 purpose 本来很棒,像 provider 的设计思路究竟根本,悟到了产品的核心。源码中解释器这一部分也很老练,非常漂亮。但可能因为是团队作业,部分看起来简单的活交给了一帮水平一般的人,可能是实习生,导致整体拉跨。

powershell 由于不能像 linux 一样建立在一个什么都是文件的基础上,转而提出了 provider,provider 提供 LisAllDrives GetChildItem 等动作,以支持 cd ls 等命令,比 linux shell 更进一步,powershell 的这些 provider 可以让一切都是对象。但是这个 provider 是以一组过程的形式提供的,像 FileSystemProvider 甚至硬编码到了程序中,而 Environment 之类也不固定由 EnvironmentProvider 提供,事实上,源码中操作这些 Provider 的手段非常蹩脚。这些 Provider 是面向最终产品的,而不是某个框架的组件,导致它们几乎只能用于 Powershell 用户。

问题出在哪儿呢,如果换我上,powershell 的设计应当围绕虚拟文件系统展开。

对,就是虚拟文件系统这个词。往往就是一个词,就可以击中问题核心,这是因为这个词表达的概念提炼了问题的本质。很多产品的设计,要点都是那么一两个核心概念,相信真正做过设计的人都深有体会,而很多不懂行的人却觉得这个不值钱,没有价值,谁知道差以毫厘谬以千里,缺乏哲学性的思考终将导致大量耗损。

如果 powershell 重新设计,它应该围绕一个容纳关系的虚拟文件系统展开。任何可以实现这个虚拟文件系统的协议都可以挂载,包括 webdac, ftp, sftp 等等,虚拟文件系统提供 url 访问,和 linux 不同的是 URL 指称的是对象。基于虚拟文件系统,所有概念都将变得非常简单。

  • 比如 Environment,可以通过 Session.Mount(EnvironProvider) 挂载,挂载后可以通过 Session.VFS["env:USERPROFILE"] 访问环境变量
  • 通过 Session.VFS["reg:/HKLM/XXX"] 可以访问注册表
  • 通过 Session.VFS["file:C:\Windows"] 可以访问文件/文件夹对象
  • 通过 Session.VFS["file:C:\Windows"].GetChildren("System32") 访问子文件
    • 通过 Session.VFS["file:C:\Windows"].GetChildren("System32/cmd.exe").Content 访问文件内容,
    • 通过 .Run() 执行

这样这个产品中框架+语言充分解耦,解释器依赖框架,而框架可以不依赖解释器。这也就意味着虚拟文件系统这套框架可以单独工作,因此框架也就可以轻松的用于其它基于 .net 的脚本语言————如果接上 RPC,甚至采用任何语言都可以。powershell 代码中硬编码极多的远程访问问题也就迎刃而解了。

考虑到这个虚拟文件系统存放的已经不只是文件,叫它层次化对象系统更妥当————都是树。

建议推到重来。 😃

posted @ 2021-07-04 16:47  Inshua  阅读(99)  评论(0编辑  收藏  举报