代码里充斥着过程式编程的搞法:比如这里 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 重新设计,它应该围绕一个容纳关系的虚拟文件系统展开。任何可以实现这个虚拟文件系统的协议都可以挂载,包括 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 代码中硬编码极多的远程访问问题也就轻松解决了。
建议推到重来。