我总是认为自己是一个Powershell纯粹主义者。用PowerShell编写的DSL(特定于域的语言)滥用我所养成的所有规则。我最近发现自己构建一个由作为DSL实现的模块,我真的很喜欢它是如何结果的。不仅如此,而且我也很开心写它。
这是一个系列中的第一篇文章,涵盖了DSL是什么以及如何编写一个。
- 第1部分:介绍域的语言(这篇文章)
- 第2部分: 为RDC Manager写一个DSL
- 第3部分: DSL设计模式
- 第4部分: 编写一个类型伸张的DSL
- 第5部分: 写一个替代的TypeeExtension DSL
指数
什么是DSL?
“特定于域的语言(DSL)是一种专门用于特定应用程序域的计算机语言。这与通用语言(GPL)相反,这在域中广泛适用,并且缺乏特定域的专业功能。“ - 维基百科
再说一次?
应用程序域可以专门用于它具有描述事物的自己的语言。有时,这对我们正在使用的工具并不好。我们有很多方法可以接近这些问题并使用DSL是其中之一。
任何好的例子?
HTML. ,CSS,XML和SQL都是DSL。这是一些基本片段。
HTML.
<html>
<body>
<h1>My heading</h1>
A basic page of html
</body>
</html>
CSS.
p {
color: red;
text-align: center;
}
XML.
<persons>
<person first="Kevin" last="Marquette" />
<persons>
SQL.
Select Name From tablePerson Where ID = 1
在每种情况下,他们都有自己的术语和模式领域。我们现在也有几个良好的榜样。 DSC, 纠缠 , Psake. 和 Psgraph.. 全部实施为DSL。
DSC.
Configuration myConfig {
Node 'localhost' {
File 'tools' {
Destination = 'c:\tools'
}
}
}
纠缠
Describe "Unit Test" {
It "Does something" {
"Something" | Should -Be "Something"
}
}
Psake.
Task default -Depends Test
Task Test -Depends Compile {
"This is a test"
}
Task Compile {
"Compile"
}
invokebuild.
Task Default Test
Task Test Compile,{
"This is a test"
}
Task Compile {
"Compile"
}
Psgraph..
Graph {
Node @{shape='rectangle'}
Edge start -To end
}
PowerShell中的一个DSL
创建DSL有两种方法。第一个使用数据部分来限制可用的命令。另一个滥用参数的机制。值得学习,因为它们可以混合在一起。
数据部分
电源外壳 中有一点已知关键字,可让您定义一个 数据部分 。这是一个脚本块,其唯一包含数据,除非您否则指定。
Data {'Hellow Wolrd'}
It can handle some basic logic but most cmdlets are not allowed to be executed in a data section. If you have some special commands that you want to include, then you need specify them as -SupportedCommands
.
DATA -SupportedCommand Format-XML {
Format-XML -strings string1, string2, string3
}
在实践中
I went looking for examples in Github. The common use case I saw for this was when importing a text file that contained their specific DSL. The -SuppportedCommand
was used to limit the text file to only data and their DSL commands.
这是它是如何使用的例子:
$Content = Get-Conent -Path $Path
Invoke-Expression -Command "DATA -SupportedCommand Import-DscConfigurationData,Import-PSEncryptedCredential,Import-PSEncryptedData {$($Content)}"
The pattern was to import the contents of a file into a string like the one above and either Invoke-Expression
on it or create a [scriptblock]
和 run invoke()
.
原始DSL功能
在跟踪一些早期谈论PowerShell可以用于创建一个DSL之后,我觉得这是他们正在谈论的功能。我认为使用CDMLETS为DSL的方式我在下一节中描述的方式是出乎意料的,当他们第一次到达现场时出乎意料。
基于CMDLET的DSL示例
我们在PowerShell实现的自定义DSL中最常见的方式是使用cmdlet。它们往往不要使用名词 - 动词结构,并且它们大量使用位置参数。让我们看看纠缠纠纷的一个例子。
Describe "Unit Test" {
It "Does something" {
"Something" | Should Be "Something"
}
}
乍一看,看起来与PowerShell一样。让我翻译成传统的力量。
Describe -Name "Unit Test" -Fixture {
It -Name "Does Something" -Fixture {
Should -ActualValue "Something" -Be -ExpectedContent "Something"
}
}
This looks a little more like the Powershell we know, but it still takes advantage of the [scriptblock]
in a less common way. Here is one more translation that don’t nest the [scriptblock]
.
$TestScript = {
Should -ActualValue "Something" -Be -ExpectedContent "Something"
}
$DescribeScript = {
It -Name "Does Something" -Fixture $TestScript
}
Describe -Name "Unit Test" -Fixture $DescribeScript
如果您不得不编写所有测试,就像用正常的PowerShell写下你的测试就会更容易。希望有助于显示写入良好的DSL的价值。
下一步是什么?
下周我们将构建基于DSL的cmdlet,为Microsoft的远程桌面连接管理器生成RDG文件。我不能说我们需要一个DSL,但这将是一个简单的示例,介绍了一些不同的技术。
继续第2部分: 为RDC Manager写一个DSL
测试