Hello World
Spiga

您选择简单的组合,还是完整的集成?

2009-10-28 01:09 by 老赵, 17310 visits

其实这是两种文化,很多人说前者属于Unix文化,后者属于Windows文化。前者好比是一系列分散的小工具,它们互相配合完成任务,其典型代表是Unix Shell。而后者好比是一个完整的工具箱,包含了完成某件特定工作所需的几乎全部功能,其典型代表是我们再熟悉不过的Visual Studio。当然,既然是文化,就能够互相借鉴和采纳,因此我们在Unix环境中也可以使用如Eclipse和IntelliJ IDEA,而Windows环境中也有cygwin和Powershell。

可能一下子说起这个有点过于直接了,那么我们先来看一下小例子。我们.NET开发人员一定知道,一个项目在VS里编译好以后会出现obj目录和bin目录,其中包含了编译过程中的输出和编译结果。假如我们想要把整个解决方案打包给别人的话,我们一般要把这两个目录删除,它们的体积还是很可观的。那么,你会怎么做?是一个一个进入项目目录里删除,还是用某种方便的做法?这个问法可能有些愚蠢,因为我相信大部分朋友在经历多次“手动删除”之后,都会厌烦,都会设法有什么自动化的方式。不过此时其实也有两种做法。

例如,有人开发了这么一个简单的项目:TreeTrim。这个小工具有个功能,便是在资源管理器的右键菜单中增加“清理”的功能,这样我们便可以方便地删除obj和bin目录。不过,我们也可以选择另一种方式,例如“命令行”。Windows传统的命令行功能比较弱,和Unix Shell相比简直天上地下。于是有人把Unix Shell移植到Windows平台上,是为cygwin。微软在两年前也推出了PowerShell,虽然从“已有功能”上讲远不如cygwin完整,但PowerShell毕竟是为Windows量身定制的,可能更容易被Windows程序员接受(如命令的alias,文件分隔符,.NET支持等等)。而PowerShell的关键还在于“Shell”,一个命令(cmdlet)之间通信的“工作平台”,我们需要的功能基本上都可以通过命令之间的扩展或组合表达出来。

例如在PowerShell中,我们如果要列出当前目录(及子目录)下所有的bin和obj文件夹,可以这样写:

Get-ChildItem -include obj,bin -recurse 

那么,我们又该如何将列出的目录删除呢?可以这样:

Get-ChildItem -include obj,bin -recurse | ForEach-Object { Remove-Item -path $_.FullName -recurse }

我们通过“管道”,也就是“|”符号组成一个命令。管道的作用是将前一个命令的输出,作为后一个命令的输入。例如上面的例子,Get-ChildItem命令得到的所有目录,会作为参数传递给ForEach-Object命令,后者再为每一项(即目录)执行一个RemoveItem命令进行删除(大括号中的$_即表示当前那一项)。看上去这个命令很复杂,输入很麻烦,不过好在PowerShell的命令行有自动补全功能,而且其实几乎每个命令都有一个或多个别名(alias),或者说是“简写”形式。例如上面这行命令也可以这样写:

dir -i obj,bin -r | % { del -path $_.FullName -r }

效果也是完全一样的。

其实我本来没打算谈这些,因为无论是PowerShell的使用,还是“文化”都已经被许多人嚼烂了。我今天写这个东西的原因是,我想要做的一件事情正好落入了这样的“俗套”,于是不禁“多想”了一些。这个事情便是所谓的“项目模板”。

Visual Studio很强大,支持自定义项目模板或元素模板,打个zip包丢到指定目录里就行了。使用项目模板创建项目,便可以创建出预定义好的许多内容,例如文件,程序集的引用等等。在使用模板创建项目或元素的时候,我们还可以给出一个“向导”,例如创建ASP.NET MVC项目的时候,会提示您是否创建配套的单元测试项目。之后,对项目的Views目录点击鼠标右键还会出现“Create View”选项,选择后还会有新的向导窗口,让您输入更多的配置等等。这些配置项会用来替换模板中某些文件内容里的占位符,于是生成的结果就会有所不同了。总之,ASP.NET MVC秉承了微软一贯的风格,除了没有把项目直接帮你做完,已经给了我们许许多多的帮助。于是我们很多程序员就像被父母宠坏的孩子,只想着衣来伸手饭来张口。一旦遇到问题,就开始嚷嚷微软提供的东西怎么那么差,问题那么多,又没有技术含量——也就好像不懂事的小孩遇到困难就去责怪父母没有把一切都安排好。

我不是这样的“孩子”,但有了微软这样的榜样,我也总是想着如何做好一个“父母”。比如,我最近在准备TechEd的讲座示例,也想着MvcPatch项目的使用方式,于是我也想像ASP.NET MVC那样创建一个模板。目标很简单:让用户输入基础的程序集和命名空间,然后由此确定每个项目的相关属性。但是我不会啊,我从来没有做过这个东西。记得我好像在05还是06年的MSDN Magazine里看到过相关的文章,但从来没有亲手做过任何一个模板。于是我打开了文档,琳琅满目,最后……发现这真不是一件容易的事情,又要设计文件内容,又要编写窗体。可能装了某些插件之后可以方便,但是我也真不想把时间花在这个东西上面,因为这对我来说又有什么长进呢?

不过后来我忽然想到,其实我要的功能完全只是个“项目文件”加上“占位符替换”而已,这个工作完全也可以由PowerShell命令完成:

Get-ChildItem -path src -recurse | Where-Object { $_.mode -like '*a*' } | ForEach-Object { (Get-Content $_.FullName) | ForEach-Object { $_ -replace "ProjectAssemblyNameBase", "RealWorldMvc" -replace "ProjectNamespaceBase", "TechEd.RealWorldMvc" } | Set-Content $_.FullName }

不过这样的完整写法很冗余,适合写在脚本中。如果只是单行命令,不追求长期的可读性,也可以使用它的等价简写形式:

dir -p src -r | ? { $_.mode -like '*a*' } | % { (gc $_.FullName) | % { $_ -replace "ProjectAssemblyNameBase", "RealWorldMvc" -replace "ProjectNamespaceBase", "TechEd.RealWorldMvc" } | sc $_.FullName }

就此,任务也就完成了。可能我只需要再准备的脚本,提示用户输入一些字符即可。在这样的场景下,使用复杂的项目模板的确会更加方便一些,对开发人员的支持也更好。但是从性价比角度来说,这种基于PowerShell解决方案难道不是更直接一些吗?

本来还想补充一些话,最后打算还是独立开篇吧。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

39 条回复

  1. 浪子
    *.*.*.*
    链接

    浪子 2009-10-28 01:14:00

    阿不干过这个事情,在MVC中使用T4模板,很快,很方便。比原来的导出功能强大很多。

  2. 强大的Shell[未注册用户]
    *.*.*.*
    链接

    强大的Shell[未注册用户] 2009-10-28 05:36:00

    貌似用ls代替dir看起来舒服一点,也更有unix的味道。

  3. Jake Lin
    *.*.*.*
    链接

    Jake Lin 2009-10-28 05:50:00

    习惯问题,开始做windows的时候,我也喜欢用cygwin,而且喜欢用vi,后来习惯了VS。

  4. leoxu
    *.*.*.*
    链接

    leoxu 2009-10-28 08:06:00

    晚上写文章可能会比较清晰吧,我得学着点了。

  5. DiggingDeeply
    *.*.*.*
    链接

    DiggingDeeply 2009-10-28 08:19:00

    我现在更倾向于前者,简单的组合。
    现在好多东西我觉得都“过度”复杂了,为了某些目的而貌似加大了掌握某些东西的“难度”,简单的才是最好的。

  6. wazup
    *.*.*.*
    链接

    wazup 2009-10-28 08:42:00

    对的,简单的最优雅。K.I.S.S.

  7. Windie Chai
    *.*.*.*
    链接

    Windie Chai 2009-10-28 08:42:00

    睡着了都能写这么多东西,老赵太强了。

  8. Jack Fan
    *.*.*.*
    链接

    Jack Fan 2009-10-28 08:50:00

    其实看看Sqlite的应用被推广的程度,就知道“简单组合”和“集成应用(Sql Server Express)”的利弊了。

  9. killkill
    *.*.*.*
    链接

    killkill 2009-10-28 08:58:00

    find -name "xxxxx" -exec rm -rf {} \ ;

  10. 假正经哥哥
    *.*.*.*
    链接

    假正经哥哥 2009-10-28 08:58:00

    夜猫子啊。

  11. bkkkd[未注册用户]
    *.*.*.*
    链接

    bkkkd[未注册用户] 2009-10-28 09:00:00

    标题党
    博主,你的文章我还是经常来看的,不过这一次进来后,发现有点被骗的感觉。

    标题明明是写两种文化,可就开头一段才是与两种文化有关,后面的更像功能介绍。

  12. Galactica
    *.*.*.*
    链接

    Galactica 2009-10-28 09:00:00

    UNIX和Windows本来就是定位于不同用户群体的产品,从这一点来说,盖茨不仅仅是一个技术天才,更是一个精明的商人.

    PowerShell或许是MS另一个拉拢UNIX技术人员的小伎俩,更简洁、高效的图形触摸技术才是MS的下一个目标。

  13. 老赵
    admin
    链接

    老赵 2009-10-28 09:06:00

    @bkkkd
    不是功能介绍,是心得体会,我再补充一段你就会爽了,呵呵。

  14. 老赵
    admin
    链接

    老赵 2009-10-28 09:06:00

    强大的Shell:貌似用ls代替dir看起来舒服一点,也更有unix的味道。


    我故意使用dir的,因为dir是dos command,呵呵。

  15. 老赵
    admin
    链接

    老赵 2009-10-28 09:09:00

    Jack Fan:其实看看Sqlite的应用被推广的程度,就知道“简单组合”和“集成应用(Sql Server Express)”的利弊了。


    这东西不见得可以一概而论吧,否则我可以举任意一个unix下的IDE作为反例,也可以随手用MySql来压倒sqlite,呵呵。
    这东西,各管各的,例如统一的工作用IDE,一些琐碎的就用shell。
    两者也可以集合,例如用在IDE里调用shell脚本。

  16. 老赵
    admin
    链接

    老赵 2009-10-28 09:13:00

    Galactica:
    PowerShell或许是MS另一个拉拢UNIX技术人员的小伎俩,更简洁、高效的图形触摸技术才是MS的下一个目标。


    不是拉拢,是Windows也真需要这样。
    虽然以前使用VBS也能完成常见工作,但是缺少一个好的shell,对于普通工作的支持还是很有限的。

  17. Cat Chen
    *.*.*.*
    链接

    Cat Chen 2009-10-28 09:19:00

    如果你的项目在SVN或者CVS,一般都会配置为check-in时自动忽略output目录的,否则每个人自己build一下都会产生很多output,都要占用版本号和空间。这样从SVN或者CVS check-out下来的一定是clean copy,不再需要手动去除output。

  18. 老赵
    admin
    链接

    老赵 2009-10-28 09:33:00

    @Cat Chen
    这是一定的,否则每次build都改变,那还了得,呵呵。
    不过“clean build”功能还是需要的,例如在不用svn的情况下。
    此外,即使用了svn,如果为了打包而再去check out一次也很麻烦……

  19. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-10-28 09:36:00

    自动清理直接写编译后脚本就可以了吧?

  20. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-10-28 09:42:00

    我明白了,只是要打包源代码。。。。。


    呃,,,,这个,怎么说,LS两位。。。。哎。。。。



    我的项目下面都有一个Source目录和Binary目录的,怎么好像你们把问题搞得很复杂?

    话说为什么要单独分出Binary目录正是因为我是用SVN的时候觉得排除目录很麻烦,So,直接改改项目的输出文件路径就OK了。

  21. 老赵
    admin
    链接

    老赵 2009-10-28 09:43:00

    Ivony...:自动清理直接写编译后脚本就可以了吧?


    又不是每次编译都需要清理……

  22. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-10-28 09:45:00

    Jeffrey Zhao:

    Ivony...:自动清理直接写编译后脚本就可以了吧?


    又不是每次编译都需要清理……




    “清理”这个词让我迷糊了,我以为是解决方案或项目上点击右键的清理。。。。

  23. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-10-28 09:51:00

    比如说我的项目属性里面的输出路径统一为..\..\Binaries\Debug(or Release)\

    这样同一个解决方案的项目的输出都在一起,管理起来都很方便。

    文件结构上,所有的源代码都在Source文件夹下, 所有的输出都在Binary文件夹下。

    文件结构:

    SolutionFolder
    SolutionFolder\Sources\Project1
    SolutionFolder\Sources\Project2
    SolutionFolder\Binaries\Reference
    SolutionFolder\Binaries\Debug
    SolutionFolder\Binaries\Release

  24. 老赵
    admin
    链接

    老赵 2009-10-28 09:58:00

    @Ivony...
    你说的没错,这也可以。不过VS有个bug,无论output设到哪里去,vs总是会创建一个空的obj目录……

  25. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-10-28 10:10:00

    Jeffrey Zhao:
    @Ivony...
    你说的没错,这也可以。不过VS有个bug,无论output设到哪里去,vs总是会创建一个空的obj目录……




    这就可以借助编译后脚本来搞定了。。。。

  26. 老赵
    admin
    链接

    老赵 2009-10-28 10:13:00

    @Ivony...
    嗯嗯,的确可以使用这种……workaround……

  27. Allen Zhang
    *.*.*.*
    链接

    Allen Zhang 2009-10-28 10:16:00

    PowerShell不会啊。

  28. 老赵
    admin
    链接

    老赵 2009-10-28 10:19:00

    @Allen Zhang
    不会就学啊。

  29. Cat Chen
    *.*.*.*
    链接

    Cat Chen 2009-10-28 11:05:00

    @Jeffrey Zhao
    这个就看场合喇,如果是个人或小团队开发,那从开发者机器上copy source是很正常的。但如果是使用更加严格的流程,肯定是使用自动化工具直接从SVN获取特定版本然后build -> test -> release的。

  30. toEverybody
    *.*.*.*
    链接

    toEverybody 2009-10-28 12:18:00

    于是我们很多程序员就像被父母宠坏的孩子,只想着衣来伸手饭来张口。一旦遇到问题,就开始嚷嚷微软提供的东西怎么那么差,问题那么多,又没有技术含量——也就好像不懂事的小孩遇到困难就去责怪父母没有把一切都安排好。
    -------------
    我不同意你这一说法
    一.微软的产品无法让她的孩子自由地成长, 老是封装封装再封装,好象它的孩子没有成人似的, 举个例吧
    SQl server数据库无法让程序员灵活地管理,在配置方面根本没有Oracle强大
    二.微软让它的孩子相当的累, 不断地推出所谓的新东东,让孩子学习,却又不断淘汰,再举个例吧,Winform就要被WPF代替.
    ...........太多了...累..

  31. 老赵
    admin
    链接

    老赵 2009-10-28 12:28:00

    @toEverybody
    微软只是把一堆东西准备好放在你面前,用不用随你,你想独立也可以。
    微软推出新东西相当于给小孩准备了很多玩具,你可以不玩,但说“挑花眼”了所以是父母不好,就说不过去了,呵呵。
    // SQL Server我可能不太清楚,不知道找个专家来会不会同意你的说法。其他方面我是深有感触的。

  32. OwnWaterloo
    *.*.*.*
    链接

    OwnWaterloo 2009-10-28 14:54:00

    Windows下如果需要unix shell,cygwin是个很重量级的方案。
    推荐一下unxutils或者msys或者单独的unix工具的windows版本。
    它们都比cygwin轻量许多。

  33. 緗灵
    *.*.*.*
    链接

    緗灵 2009-10-28 20:50:00

    呜呜,我还不知道powershell是什么,这些命令在哪运行。赵哥哥我该怎么学啊

  34. 老赵
    admin
    链接

    老赵 2009-10-28 20:51:00

    @緗灵
    先搜再问

  35. 緗灵
    *.*.*.*
    链接

    緗灵 2009-10-28 20:55:00

    哦好的,我有个好朋友也这么说的劳记你的明言“先搜再问”谢谢赵哥哥

  36. flyingchen
    *.*.*.*
    链接

    flyingchen 2009-10-29 00:04:00

    powershell是个好东西,我在学,准备向运维推广

  37. 老赵
    admin
    链接

    老赵 2009-10-29 00:32:00

    @flyingchen
    其实在此之前的cygwin也是不错的,呵呵。

  38. 风中灵药
    *.*.*.*
    链接

    风中灵药 2009-11-02 10:38:00

    文章内容有愧于文章标题。

  39. 老赵
    admin
    链接

    老赵 2009-11-02 10:42:00

    @风中灵药
    想不明白,我标题真起的很大吗?
    还是和“补充内容”一起看吧,呵呵。

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我