大型网站开发考试,怎么建网站站点,app开发团队公司,宝应县天宇建设网站这里先从声明式#xff08;Declarative#xff09;编程谈起。 目前我们在编写软件时大量使用的是命令式#xff08;Imperative#xff09;编程语言#xff0c;例如C##xff0c;Java或是C等等。这些语言的特征在于#xff0c;写出的代码除了表现出“什么#xff08;Wha… 这里先从声明式Declarative编程谈起。 目前我们在编写软件时大量使用的是命令式Imperative编程语言例如C#Java或是C等等。这些语言的特征在于写出的代码除了表现出“什么What”是你想做的事情之外更多的代码则表现出实现的细节也就是“如何How”完成工作。这部分代码有时候多到掩盖了我们原来问题的解决方案。比如你会在代码里写for循环if语句a等于bi加一等等这体现出机器是如何处理数据。首先这种做法让代码变得冗余而且它也很难让执行代码的基础设施更聪明地判断该如何去执行代码。当你写出这样的命令是代码然后把编译后的中间语言交给虚拟机去执行此时虚拟机并没有多少空间可以影响代码的执行方式它只能根据指令一条一条老老实实地去执行。例如我们现在想要并行地执行程序就很困难了因为更高层次的一些信息已经丢失了。这样我们只能在代码里给出“How”而不能体现出“What”的信息。 有多种方式可以将“What”转化为更为“声明式”的编程风格我们只要能够在代码中体现出更多“What”而不是“How”的信息这样执行环境便可以更加聪明地去适应当前的执行要求。例如它可以决定投入多少CPU进行计算你的当前硬件是什么样的等等。 我之前提到过现在有两种比较重要的成果一是DSLDomain Specific Language领域特定语言另一个则是函数式编程。 其实DSL不是什么新鲜的玩意儿我们平时一直在用类似的东西比如SQLCSS正则表达式有的可能更加专注于一个方面例如MathematicaLOGO等等。这些语言的目标都是特定的领域与之相对的则是GPPLGeneral Purpose Programming Language通用目的编程语言。 对于DSL而言其实并没有一个明确的定义在这里我也不打算为它下个定义例如UML甚至根本没有特定的语法。不过我这里会谈一些我觉得比较重要的东西。 Martin Fowler提出DSL应该分为外部DSL及内部DSL两种我认为这种划分方式还是比较有意义的。外部DSL是自我包含的语言它们有自己特定语法、解析器和词法分析器等等它往往是一种小型的编程语言甚至不会像GPPL那样需要源文件。与之相对的则是内部DSL。内部DSL其实更像是种别称它代表一类特别API及使用模式。这里我会给你们看一些示例。 这些是我们平时会遇到的一些外部DSL如这张幻灯片上表现的XSLTSQL或是Unix脚本。外部DSL的特点是你在构建这种DSL时其实扮演的是编程语言设计者的角色这个工作并不会交给普通人去做。外部DSL一般会直接针对特定的领域设计而不考虑其他东西。James Gosling曾经说过这样的话每个配置文件最终都会变成一门编程语言。你一开始可能只会用它表示一点点东西然后慢慢你便会想要一些规则而这些规则则变成了表达式可能你还会定义变量进行条件判断等等。而最终它就变成了一种奇怪的编程语言这样的情况屡见不鲜。 事实上现在有一些公司也在关注DSL的开发。例如以前在微软工作的Charles Simonyi提出了Intentional Programming的概念还有一个叫做JetBrains的公司提供一个叫做MPSMeta Programming System的产品。最近微软也提出了自己的Oslo项目而在Eclipse世界里也有个叫做Xtext的东西所以其实在这方面现在也有不少人在尝试。 我在观察外部DSL时往往会关注它的语法到底提供了多少空间例如一种XML的方言利用XML方言的好处在于有不少现成的工具可用这样可以更快地定义自己的语法。 而内部DSL正像我之前说的那样它其实只是一系列特别的API及使用模式的别称。这里则是一些LINQ查询语句Ruby on Rails以及jQuery代码。内部DSL的特点是它其实只是一系列API但是你可以“假装”它们一种DSL。内部DSL往往会利用一些“流畅化”的技巧例如像这里的LINQ或jQuery那样把一些方法通过“点”连接起来。有些则利用了元编程的方式如这里的Ruby on Rails就涉及到了一些元编程。这种DSL可以访问语言中的代码或变量以及利用如代码补全重构等母语言的所有特性。 现在我会花几分钟时间演示一下我所创建的DSL也就是LINQ。我相信你们也已经用过不少LINQ了不过这里我还是快速的展示一下我所表达的更为“声明式”的编程方式。 public class Product{ public int ProductID { get; set; } public string ProductName { get; set; } public string CategoryName { get; set; } public int UnitPrice { get; set; } public static ListProduct GetProducts() { /* ... */ }
}public partial class _Default : System.Web.UI.Page{ protected void Page_Load(object sender, EventArgs e){ ListProduct products Product.GetProducts(); ListProduct result new ListProduct(); foreach (Product p in products){ if (p.UnitPrice 20) result.Add(p);}GridView1.DataSource result;GridView1.DataBind();}
} 这里有许多Product对象那么现在我要筛选出所有单价大于20的那些 再把他们显示在一个GridView中。传统的做法就是这样我先得到所有的Product对象然后foreach遍历每个对象再判断每个对象的单价最终把数据绑定到GridView里。运行这个程序……打开页面这就是就能得到结果。 好那么现在我要做一些稍微复杂的事情。可能我不是要展示单价超过20的Product对象而是要查看每个分类中究竟有多少个单价超过20的对象然后根据数量进行排序。如果不用DSL完成这个工作那么我可能会先定义一个对象来表示结果 class Grouping{ public string CategoryName { get; set; } public int ProductCount { get; set; }
} 这是个表示分组的对象用于保存分类的名称和产品数量。然后我们就会写一些十分丑陋的代码 Dictionarystring, Grouping groups new Dictionarystring, Grouping();foreach (Product p in products)
{ if (p.UnitPrice 20){ if (!groups.ContainsKey(p.CategoryName)){ Grouping r new Grouping();r.CategoryName p.CategoryName;r.ProductCount 0;groups[p.CategoryName] r;}groups[p.CategoryName].ProductCount;}
}ListGrouping result new ListGrouping(groups.Values);
result.Sort(delegate(Grouping x, Grouping y)
{ return x.ProductCount y.ProductCount ? -1 :x.ProductCount y.ProductCount ? 1 :0;
}); 我先创建一个新的字典用于保存分类名称到分组的对应关系。然后我遍历每个Product对象对于每个单价大于20的对象如果字典中还没有保存对应的分组则创建一个然后将数量加一。然后为了排序我调用Sort方法于是我要提供一个委托作为排序方法然后blablablabla……执行之后……打开页面我自然可以得到想要的结果。 但是首先这些代码写起来需要花费一些时间很显然。然后仔细观察你会发现这写代码几乎都是在表示“How”而“What”基本已经丢失了。假设我离开了现在新来了一个程序员要维护这段代码他会需要一点时间才能完整理解这段代码因为他无法直接看清代码的目标。 不过如果这里我们使用DSL也就是LINQ就像这样 var result products.Where(p p.UnitPrice 20).GroupBy(p p.CategoryName).OrderByDescending(g g.Count()).Select(g new { CategoryName g.Key, ProductCount g.Count() }); products……先调用Where……blablabla……再GroupBy等等。由于我们这里可以使用DSL来表示高阶的术语用以体现我们想做的事情。于是这段代码则更加关注于“What”而不是“How”。我这里不会明确地指示我想要过滤的方式我也不会明确地说我要建立字典和分类这样基础结构就可以聪明地或者说更加聪明地去确定具体的执行方式。你可能比较容易想到我们可以并行地执行这段代码因为我没有显式地指定做事方式我只是表示出我的意图。 我们打开页面……打开页面很显然我们得到了相同的结果。 这里比较有趣的是内部DSL是如何设计进C#语法中的为此我们为C# 3.0添加了一系列的特性例如Lambda表达式扩展方法类型推断等等。这些特性统一起来之后我们就可以设计出更为丰富的API组合之后便成为一种内部DSL就像这里的LINQ查询语言。 除了使用API的形式之外我们还可以这样做 var result from p in products where p.UnitPrice 20 group p by p.CategoryName into g orderby g.Count() descendingselect new { CategoryName g.Key, ProductCount g.Count() }; 编译器会简单地将这种形式转化为前一种形式。不过这里我认为有意思的地方在于你完全可以创建一门和领域编程语言完全无关的语法然后等这种语法和API变得流行且丰富起来之后再来创一种新的表现形式就如这里的LINQ查询语法。我颇为中意这种语言设计的交流方式。 OK现在我们回到下面的内容。 原文链接http://blog.zhaojie.me/2010/04/trends-and-future-directions-in-programming-languages-by-anders-2-declarative-programming-and-dsl.html .NET社区新闻深度好文微信中搜索dotNET跨平台或扫描二维码关注