- 浏览: 372817 次
- 性别:
- 来自: 北京
-
最新评论
-
litongke:
类比的方式总是能帮助我们快速的理解一个晦涩的理念。楼主的很厉害 ...
从面向对象到面向切面 -
snowflate_summer:
这是从数学上来论证面向对象和面向切面吗?很深奥
从面向对象到面向切面 -
奥义之舞:
我好像更迷茫了。、、、
从面向对象到面向切面 -
canonical:
很遗憾,从现在已知的物理学来看,所谓能量也只是一种偏移量而已。 ...
逆元:不存在的真实存在 -
suifeng:
关于最后一段:我也有类似的思考信息是能量的动态呈现, 也就相当 ...
逆元:不存在的真实存在
软件开发作为一种工程技术,它所研究的一个重点就是如何才能有效降低软件产品的研发成本。在这一方向上,组件技术取得了空前的成功。它所提供的基本图景是像搭积木一样从无到有的组装出最终的产品。在某种意义上,这是对现代建筑工业的模仿和致敬。新材料,预制件,框架结构,这些建筑学的进展在软件领域被一一复制,建筑工地上的民工自然也成为了程序员们学习的楷模。毕竟,在组件的世界中码代码,基本上也是一种“搬砖”的行为。
值得庆幸的是,软件开发作为一种智力活动,它天生具有一种“去民工化”的倾向。信息产品有着与物质世界产品完全不同的抽象本质。在物理空间中,建造100栋房屋,必须付出100倍的努力,老老实实的干上100遍。而在概念空间中建造100栋房屋,我们却可以说其他房屋与第一栋一模一样,加点平移旋转变换即可。一块砖填了地基就不能用来盖屋顶,而一段写好的代码却可以在任何可用的场合无损耗的被使用。一栋建好的房屋发现水管漏水要大动干戈,而在完成的软件中补个局部bug却是小菜一碟。在抽象的世界中有效的进行生产,所依赖的不应该是大干,苦干的堆砌,而应该是发现某种可用于推导的原理,基于这些原理,输入信息可以立刻转换为最终的结果,而不需要一个逐步构造的过程。即我们有可能超越组装性生产,实现某种类似于数学的原理性生产。http://canonical.iteye.com/blog/325051
代码复用是目前软件业中鼓吹降低生产成本的主要口号之一。但是在组件技术的指向下,一般所复用的只是用于构建的砖块,而并不是某种构造原理。即使在所有信息已经确定的情况下,我们仍然不可能从需求立刻得到可执行的产品。很多代码即使我们在想象中已经历历在目,却仍然需要一行行把它们誊写下来。当我们发现系统中已经没有任何组件值得抽象的时候,仍然留下来众多的工作需要机械化的执行。代码复用的理想国距离我们仍然非常的遥远。
子例程(subroutine)是最早的代码重用机制。这就像是将昨天已经完成的工作录制下来,在需要的时候重新播放。函数(function)相对于子例程更加强大。很多代码看起来并不一样,但是如果把其中的差异部分看作是变量,那么它们的结构就可以统一了。再加上一些判断和循环,很多面目迥异的东西其实是存在着大量共享信息的。面向对象技术是一次飞跃性的发展。众多相关信息被打包到一个名称(类型)中,复用的粒度和复杂度都大大提升。派生类从基类继承,可以通过重载实现对原有代码的细致调整。不过,这种方式仍然无法满足日益增长的复用需求。很多时候,一个名称并不足以标定我们最终需要的代码结构,在实际使用的时候还需要补充更多的信息。类型参数化,即泛型技术,从事后的角度看其实是一种明显的解决方案。根据参数动态的生成基类自然可以吸纳更多的变化。经历了所谓Modern C++的发展之后,我们现在已经非常明确,泛型并非仅仅能够实现类型共变,而是可以从类型参数中引入更丰富的结构信息,它的本质是一种代码生成的过程。http://canonical.iteye.com/blog/57244
认清了这一点,它的扩展就非常明显了
BaseClass<ArgClass> --> CodeGenerator<DSL>
DSL(或者某种模型对象)相对于普通的类型(Class),信息密度要大很多,它可以提供更丰富也更完整的输入信息。而CodeGenerator也不必拘泥于基础语言本身提供的各种编译机制,而是可以灵活应用各种文本生成技术。http://canonical.iteye.com/blog/309395 CodeGenerator在这里所提供的正是根据输入模型推导出完整实现代码的构造原理。
现在很多人热衷于开发自己的简易代码生成工具,这些工具也许可以在简单的情形下减轻一些体力工作,但是生成的代码一般不能直接满足需求,仍然需要手工执行大量的删改工作。当代码生成之后,它成为一种固化的物质产品,不再能够随着代码生成工具的改进而同步改进,在长期的系统演化过程中,这些工具并不一定能够减少累积的工作量。
修正过程 ==> CodeGenerator<DSL>
为了改进以上代码生产过程,一些人试图在CodeGenerator中引入越来越多的可配置性,将各种变化的可能内置在构造原理中。显然这会造成CodeGenerator的不正常的肿胀。当更多的偶然性被包含在原理中的时候,必然会破坏原理的简单性和普适性。
输入信息 + 一段用于推导的原理 + 修正补充 = 真实模型
必须存在[修正补充]这一项才能维持以上方程的持久平衡。
为了摆脱人工修正过程,将模型调整纳入到概念世界中,我们需要超越继承机制的,更加强大的,新的技术手段。其实在当前的技术背景下,这一技术已经是呼之欲出了。这就是AOP, Aspect Oriented Programming。http://canonical.iteye.com/blog/34941
Biz ==[AOP extends]==> CodeGenerator<DSL>
继承仅仅能够实现同名方法之间的简单覆盖,而AOP所代表的技术原理却是在代码结构空间中进行任意复杂的删改操作,它潜在的能力等价于人工调整。
为了实现上述生产模式,需要对编程语言,组件模型,框架设计等方面进行一系列改造。目前通用的AOP实现和元编程技术其实并不足以支持以上模式。http://canonical.iteye.com/blog/275015
这一生产模式将会如何演化,也是一个有趣的问题。按照级列理论,我们立刻可以得到如下发展方向:
Context0 + DSL1 + EXT0 = DSL0 Context1 + DSL2 + EXT1 = DSL1 ...
http://canonical.iteye.com/blog/33824
Witrix平台中BizFlow可以看作是对DaoWebAction的修正模型,但是它本身具有完整的意义,可以直观的被理解。在BizFlow的基础上可以逐步建立SeqFlow,StateFlow等模型。http://canonical.iteye.com/blog/126467
现在有些人试图深挖函数式语言,利用模式匹配之类的概念,做符号空间的全局优化。但是我们需要认识到通用的机制是很少的,能够在通用语言背景下被明确提出的问题更是很少的。只有在特定领域中,在掌握更多局部信息的情况下,我们才能提出丰富的问题,并作出一定背景下的解答。DSL的世界中待做的和可做的工作很多。http://canonical.iteye.com/blog/147065
对于程序员而言,未来将变得越来越丰富而复杂,它将持续拷问我们的洞察力。我们不是一行行的编写代码,把需求一条条的翻译到某种实现上,而是不断发明局部的生产原理,依靠自己制定的规则在抽象的空间中不断的创造新的表象。
评论
nighthawk 写道还是很欣赏canonical看待问题的视角。
我的简单理解来就是代码复用是没有问题的,路远点就远点了,得看复用到什么程度。
现在流行的框架以及你的Witrix平台不也是复用的一种体现吗。
想到个通俗的比喻:框架像是地基,他不需要我们重复劳动了,领域模型是柱子,他决定了房屋的形状。剩下的就是搬砖了。当然,搬砖砌砖也是个技术活,如果搬砖工人会点诀窍,比如AOP之类的,那会搬的更轻松。
另外,我并不看好什么CodeGenerator。那生成出来的代码与复用,是两码事。也许有CodeGenerator适合的场景,比如一些很简单通用的增删改查。但是,既然提到了简单通用,那我干吗还去用CodeGenerator,啥工具语言的上来不都是三下五除二搞定?
现有的AOP框架基本都是通过CodeGenerator实现的。
工具的本质也是代码检查器和生成器。譬如可视化编辑器定义了一个鼠标DSL,于是可以通过这个DSL产生程序代码。可是现在的工具包装得太好了,以至于人们很容易忘记它本来是什么东西……
前面我也说过,复用的第一原则是充分利用本语言的能力,其次才是CodeGenerator。
但是静态语言的缺点就是:某时候很难复用一个结构(可以是可以的,但是做出来别人看不懂),于是便衍生出各种各样的复用的通用语言——设计模式和框架。
可是回头想一想:为什么事情变得这么复杂? 走这么远是否忘记了本来的意思? 有时一个static if胜过千言万语。
而且,语言和框架只有语法检查的能力,逻辑检查还得靠自己,完成自己的CodeGenerator就更有意义了。
nighthawk你对代码生成的理解有误。CodeGenerator还有一个名字,叫做编译器。
http://en.wikipedia.org/wiki/Code_generation_(compiler)
在我看来,如果一个代码生成器,生成完代码就不管了,只着眼于“生成”,那绝对不能够令人满意。真正有用的代码生成器,要对所生成代码实现有效的管理,这种可管理性要体现在:
1 程序员无需接触到所生成的代码,各种修改都在代码生成器所提供的DSL语言中进行。
2 调试的时候,跟踪,断点等设置也主要在高级的DSL语言中进行,而不是一定要深入到所生成的代码内部。
在现代的各种程序语言中,有一个少有人注意的问题,那就是把声明式和命令式混淆在了一起,它们之间的关系也没有得到很好的清理。声明式是关于概念世界的,回答“是什么”的问题,而命令式是关于现实世界的,回答“如何做”的问题。
类是属于概念世界,具体的对象实例属于现实世界(内存)。类之间的关系,类与对象的关系,用声明式语言才适合,而对象具体的行动,却需要用命令式的语言表达。
只有在程序设计语言中融合声明式和命令式到一个整体框架中,才能够更符合程序员的需要。
我的简单理解来就是代码复用是没有问题的,路远点就远点了,得看复用到什么程度。
现在流行的框架以及你的Witrix平台不也是复用的一种体现吗。
想到个通俗的比喻:框架像是地基,他不需要我们重复劳动了,领域模型是柱子,他决定了房屋的形状。剩下的就是搬砖了。当然,搬砖砌砖也是个技术活,如果搬砖工人会点诀窍,比如AOP之类的,那会搬的更轻松。
另外,我并不看好什么CodeGenerator。那生成出来的代码与复用,是两码事。也许有CodeGenerator适合的场景,比如一些很简单通用的增删改查。但是,既然提到了简单通用,那我干吗还去用CodeGenerator,啥工具语言的上来不都是三下五除二搞定?
现有的AOP框架基本都是通过CodeGenerator实现的。
工具的本质也是代码检查器和生成器。譬如可视化编辑器定义了一个鼠标DSL,于是可以通过这个DSL产生程序代码。可是现在的工具包装得太好了,以至于人们很容易忘记它本来是什么东西……
前面我也说过,复用的第一原则是充分利用本语言的能力,其次才是CodeGenerator。
但是静态语言的缺点就是:某时候很难复用一个结构(可以是可以的,但是做出来别人看不懂),于是便衍生出各种各样的复用的通用语言——设计模式和框架。
可是回头想一想:为什么事情变得这么复杂? 走这么远是否忘记了本来的意思? 有时一个static if胜过千言万语。
而且,语言和框架只有语法检查的能力,逻辑检查还得靠自己,完成自己的CodeGenerator就更有意义了。
nighthawk你对代码生成的理解有误。CodeGenerator还有一个名字,叫做编译器。
http://en.wikipedia.org/wiki/Code_generation_(compiler)
我的简单理解来就是代码复用是没有问题的,路远点就远点了,得看复用到什么程度。
现在流行的框架以及你的Witrix平台不也是复用的一种体现吗。
想到个通俗的比喻:框架像是地基,他不需要我们重复劳动了,领域模型是柱子,他决定了房屋的形状。剩下的就是搬砖了。当然,搬砖砌砖也是个技术活,如果搬砖工人会点诀窍,比如AOP之类的,那会搬的更轻松。
另外,我并不看好什么CodeGenerator。那生成出来的代码与复用,是两码事。也许有CodeGenerator适合的场景,比如一些很简单通用的增删改查。但是,既然提到了简单通用,那我干吗还去用CodeGenerator,啥工具语言的上来不都是三下五除二搞定?
加在概念上是简单的加,非常直白。但是具体操作的时候,要找到合适的地方,具体加的时候要做的操作就需要有复杂的实现约束了。这个很难理解了吗。因为从概念上说,我手里有现成的一些代码,现在有一些增量修改,它们放在一起要合成最终我们需要的代码,这个不是很简单的吗,但是你能很简单的定义出规则来实现这个过程吗。
template可以改,没有问题啊。这说明你没有AOP的需要。而我们在大规模使用代码生成技术的时候就不能一句“非要AOP它吗”就可以解决问题的了。这就如同说所有的开发不都是写代码吗,我要抽象干吗呢。源代码当然是要重用抽象,有了AOP你才能做到更好的重用,这个很难理解吗。
手工copy当然不是CodeGenerator了。 你为什么会有这种误解呢。CodeGenerator在我的文章中外延并不大啊, 用某种技术生成的才是generate的,直接用原生语言手写的当然不是了。
A你看做一个AST就可以。
抽象重用的第一考虑应该是充分利用本语言的结构,然后才是代码生成,我玩玩动态语言生成就满足了,的确没有AOP的需要

btw:Template是我手写的,不是生成的。
老实说你写的东西码那么长字,看不下去……好意心领了。
不要怒啊,一定会有理解你支持你的人的。
加在概念上是简单的加,非常直白。但是具体操作的时候,要找到合适的地方,具体加的时候要做的操作就需要有复杂的实现约束了。这个很难理解了吗。因为从概念上说,我手里有现成的一些代码,现在有一些增量修改,它们放在一起要合成最终我们需要的代码,这个不是很简单的吗,但是你能很简单的定义出规则来实现这个过程吗。
template可以改,没有问题啊。这说明你没有AOP的需要。而我们在大规模使用代码生成技术的时候就不能一句“非要AOP它吗”就可以解决问题的了。这就如同说所有的开发不都是写代码吗,我要抽象干吗呢。源代码当然是要重用抽象,有了AOP你才能做到更好的重用,这个很难理解吗。
手工copy当然不是CodeGenerator了。 你为什么会有这种误解呢。CodeGenerator在我的文章中外延并不大啊, 用某种技术生成的才是generate的,直接用原生语言手写的当然不是了。
A你看做一个AST就可以。
Aspect本身当然也是可以由生成器生成的。
A不是函数,它是一个具体的程序结构。我们的工作本身就是这样实现,不是什么理论问题。加是一个非常复杂的操作,具体是哪个位置当然是有一系列规则确定的。
"结果不还是CodeGenerator". 这个怎么是呢? 其中有手写的部分,有生成的部分。 有重用的通用的部分, 有特殊的针对特定应用的部分。它们之间是以复杂的方式合成的。不是显得高深,而是你是否能够真正的为这些概念找到实际的应用。
请给一个应用的例子,大家都明白的那种。
老实说我不明白template犯了什么错,我就不能改它吗? 非要AOP它吗? 我就不能用对待别的源代码相同的方式对待它吗? 源代码就不能抽象重用吗?
"加是个非常复杂的操作"……你刚才还说"加就是加上"……不吐你槽了
如果你把CodeGenerator的外延定得这么宽,整个程序都是CodeGenerator了,手工copy也是CodeGenerator了……
如果你说这个A是个AST或者字符串或者一群蚂蚁,我明白。你说“一个具体的程序结构”,我就搞不懂你要表达的意思了。
Aspect本身当然也是可以由生成器生成的。
A不是函数,它是一个具体的程序结构。我们的工作本身就是这样实现,不是什么理论问题。加是一个非常复杂的操作,具体是哪个位置当然是有一系列规则确定的。
"结果不还是CodeGenerator". 这个怎么是呢? 其中有手写的部分,有生成的部分。 有重用的通用的部分, 有特殊的针对特定应用的部分。它们之间是以复杂的方式合成的。不是显得高深,而是你是否能够真正的为这些概念找到实际的应用。
你的回答其实都是要修改原先生成器本身的代码的,这是对原有抽象的破坏。
那要看你对生成器的定义范畴了,我觉得Template只是源代码的一部分,并不是生成器的一部分,输入数据更加是源代码的一部分了。
而且照你这么说,AOP也是生成器代码了。
当我们还在思考这是不是破坏了某抽象的时候,别人的伟大产品已经出炉了。
Biz =[AOP extends]=> CodeGenerator<DSL>
合成? 你的第一个式子"A=O+(A-O)" 问题就出来了:
如果A定义了一个函数f,A-O删除了f,那么g(f)是改成g(0)还是直接删掉呢?
假设改成g(0),那O+(A-O)是否要把所有0替换成f呢?
假设删掉,那么O+(A-O)如何知道要在哪个位置补上g(f)呢?
接着第二个式子,看了好一会才明白……这些符号是你自创的还是借用的?
AOP*CodeGenerator, 结果不还是CodeGenerator?
如果要给CodeGenerator分层次,我还可以定义一个级数,每次CG都更接近Biz,这样也能显得很高深。
你的回答其实都是要修改原先生成器本身的代码的,这是对原有抽象的破坏。
AOP是必要的一种技术,这一点对大多数人来说都是意识不到的。因为对大多数人来说,AOP只是偶尔使用的调剂,代码生成代码也只是系统中可有可无的部分。但是对于我们而言,代码生成是系统运行的核心,绝大多数代码都是基于生成概念的情况下,对于AOP概念的依赖就成为必然了。
“而且AOP也不能保证你修改了生成的代码之后不出任何问题吧”。AOP当然无法保证,而且事实上因为AOP技术的强大能力伴随着对系统结构的巨大破坏性,因此我们必须发展一系列的技术来规范,限制AOP的处理方式。这个其实是需要做工作的地方。
现在很多利用模板语言进行的代码生成是没有任何规范约束的,而C++和D语言中的元编程则是在严格的规范中进行的。
“问一个问题: O是任何结构? 你这里的+是什么? 证明了+运算的交换律没? ”。 这里并不是算数运算中的+, 只是合成操作的简写。加就是加上,这个很容易理解。在我的文章中有一个更加准确的公式
Biz =[AOP extends]=> CodeGenerator<DSL>
A = O + ( A - O) = O + Aspect , 这里O可以是任何结构。 Aspect仅仅是说相对于基础结构它是一个补充而已。 Aspect本身当然可以用代码生成技术等进行构造。 对于构造最终我们需要的A而言,直接用代码生成或者是使用AOP构造, 或者是代码生成结合AOP, 它们的能力都是一样的, 只是不同的策略的灵活程度,方便程度不一样而已。
问一个问题: O是任何结构? 你这里的+是什么? 证明了+运算的交换律没?
假设现在我已经写好了一段代码生成器的实现,可以生成我需要的代码,例如你上面_wnd_proc的实现。 我在几个常见的应用中也用到了,可是突然有一天有一个需求,要对一个特定的msg='my_message'的时候做一个特殊处理。现在应该如何处理呢? 是重写代码生成器,或者为代码生成器增加一个配置选项,还是利用某种AOP技术直接操作生成的代码做一点修正?
“最终的结构”和“精细的调节”不只是某种空泛的概念区别,而是对应着不同的实现策略。
“分离好生成代码和非生成代码即可”这种分离到底能做到多大的程度?是简单的代码交错,还是复杂的如同C++模板那种非常深入的编译期的递归交织。一个信息表达A到底能够以哪些方式传播到系统中的哪些部分?
第一个问题:这就体现了代码生成器用动态语言实现的好处。
如果要做一个特殊处理,做一些项目特定的微调时,不需要重写生成器,也不需要重新配置(本来这个东西就是0配置……),动态语言的元编程能力提供了强大的灵活性。
方案A:msg_listeners是分析其他文档产生的,listener函数体也在分析数据中,迭代修改msg='my_message'函数体即可(甚至连动态性都没用上……)。
方案B:修改这个模版,增加一个if(${msg}==my_message),由于编译期两者都是常量,自动被优化掉。
第二个问题:依实际情况而定了。
而且AOP也不能保证你修改了生成的代码之后不出任何问题吧。
你问的问题很好,虽然我没有这样的疑惑……我所有给编译器的源文件都是生成的……也没遇到过要改那些东西的需求。
最后,由于只对#做了手脚,代码编辑器还是认账的。
A = O + ( A - O) = O + Aspect , 这里O可以是任何结构。 Aspect仅仅是说相对于基础结构它是一个补充而已。 Aspect本身当然可以用代码生成技术等进行构造。 对于构造最终我们需要的A而言,直接用代码生成或者是使用AOP构造, 或者是代码生成结合AOP, 它们的能力都是一样的, 只是不同的策略的灵活程度,方便程度不一样而已。
假设现在我已经写好了一段代码生成器的实现,可以生成我需要的代码,例如你上面_wnd_proc的实现。 我在几个常见的应用中也用到了,可是突然有一天有一个需求,要对一个特定的msg='my_message'的时候做一个特殊处理。现在应该如何处理呢? 是重写代码生成器,或者为代码生成器增加一个配置选项,还是利用某种AOP技术直接操作生成的代码做一点修正?
“最终的结构”和“精细的调节”不只是某种空泛的概念区别,而是对应着不同的实现策略。
“分离好生成代码和非生成代码即可”这种分离到底能做到多大的程度?是简单的代码交错,还是复杂的如同C++模板那种非常深入的编译期的递归交织。一个信息表达A到底能够以哪些方式传播到系统中的哪些部分?
我的想法是不必要在“最终的结构”和“精细的调节”上面纠结,
代码生成就是编译过程,只要分离好生成代码和非生成代码即可。
新建太多概念意义也不大。
"我想基于parse tree的东西已经把事情弄得很清晰了"
确实,从概念上这些东西都是非常清楚的. AOP就是一种定位组装技术,元编程就是一种代码生成. 但是概念上很清楚不代表你找到了新的应用方式. 除了别人已经做好的例子, 你能否想出什么复杂的应用实例? 如何具体应用这些概念?
举几个自己应用代码生成的例子,虽然写得不怎么样,但是觉得比用AOP容易得多
下面是一个消息处理函数的生成模版,msg_listeners通过解析其他文件得到。
(写这段函数的初衷是不需要Thunk Hack也能避免产生庞大的虚函数表)
在VC里设置了Prebuild event,每次build之前先Generate一趟(用ant,make,rake也差不多)。
一点说明:C的宏就是一种元编程,这里扩展了macro的语法,'#'开始的行除了原有的C macro之外,都被当做是ruby代码处理。这种处理方式也非常容易重用。
'${}'为嵌入相应对象的值。
#static: LRESULT CALLBACK _wnd_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { LRESULT result = 0; switch(message) { #msg_listeners.each do |msg,listeners| case ${msg}: #listeners.each do |listener| if(${fname_base}.${listener}) return result; #end break; #end //generate mouseover and leave events case WM_NCHITTEST: if(window_base::h_mouseover != hwnd) { SendMessage(window_base::h_mouseover, WM_MOUSELEAVE, 0, 0); SendMessage(hwnd, WM_MOUSEHOVER, 0, 0); window_base::h_mouseover = hwnd; return 0; } break; } //reflect unprocessed notify if (message == WM_NOTIFY) { return SendMessage(((LPNMHDR)lparam)->hwndFrom, WM_RNOTIFY, wparam, lparam); } #if child_window return CallWindowProc( _old_proc, hwnd, message, wparam, lparam ); #else return DefWindowProc( hwnd, message, wparam, lparam ); #end }
下面是根据Scintilla.iface生成Ruby extension接口的Erb模版的一部分
(Scintilla的接口太多了,一个个写肯定累死人,有些细节还是不能依赖swig完成,只好自己写了)
Can AOP do this ?
<% strres_funs.each do |f| %> static VALUE _x_<%= f[:fun] %>(<%= proto(f[:p1],f[:p2]) %>) { VALUE v; int len = _SEND(<%= f[:code] %>, <%= cval(f[:p1]) || '0' %>, 0); char* buf = _x_arena_alloc(len); _SEND(<%= f[:code] %>, <%= cval(f[:p1]) || 'len' %>, buf); v = rb_str_new(buf, (len>0 ? len-1 : 0)); rb_funcall(v, id_force_encoding, 1, string_utf_8); return v; } <% end %>
动态类型,动态方法的好处是:它们都非常直观。
而AOP?什么是advice?什么是pointcut?我需要学习这些才能修改它们么?
举个例子,升级到ruby1.9,很多gem都报错:找不到"xxx".each方法。那么很简单:
class String alias each each_byte end
打开类修改,定义一个别名,问题解决
可能我举的例子过于简单,但是问题没办法变得更复杂……
或者设想一个庞大的工程,需要大量补镬的场景? 那么应用AST做点剪枝工作吧,我觉得ANTLR官网上很多文章都不错的。
这样生成也有缺点:不能改生成的目标代码。
但是,代码生成就是一个编译的过程,正如人们应该修改.java文件,而不是去修改.class文件,如果要改,就应该改源文件。
"我想基于parse tree的东西已经把事情弄得很清晰了"
确实,从概念上这些东西都是非常清楚的. AOP就是一种定位组装技术,元编程就是一种代码生成. 但是概念上很清楚不代表你找到了新的应用方式. 除了别人已经做好的例子, 你能否想出什么复杂的应用实例? 如何具体应用这些概念?
但是不好意思,当我提到AOP的时候,我所指的就是像AspectXXX那样的东西……
对于你说的AOP,再次不好意思,我抽象思维能力比较弱……不是很明白为什么这么多东西都被AOP(如果我没记错,面向方面编程?)覆盖了?
现有的元编程技术已经非常强大了吧?
像boost.spirit,就可以动态添加语法规则;
动态语言实现的DSL也可以玩一个无穷序列,甚至还可以用DSL生成DSL生成DSL……
至于如何划分边界,我想基于parse tree的东西已经把事情弄得很清晰了。
如果要说谁更牛逼一点,我想可以证明它们是等价的……
动态语言代码生成最后所提供的效果也在AOP所涵盖的范畴之内。 AOP就是对程序代码结构的一种动态修正技术.
代码生成决不仅是代码生成工具,或者是动态脚本代码生成,或者是动态字节码代码生成,或者是JIT代码生成. 我对代码生成的关注重点在于生成的过程中如何保持概念边界,如何将它作为模型定义和转换的手段.
发表评论
-
从面向对象到面向切面
2011-05-08 12:01 18431. C语言抽象出了软件所在的领域(domain): 由变量v ... -
业务架构平台的自举问题
2011-02-11 14:00 1563业务架构平台的设 ... -
模型驱动的数学原理
2011-02-07 02:45 1942一种技术思想如果 ... -
结构的稳定性
2009-12-06 12:17 2677结构的稳定性,直 ... -
结构的自足性
2009-10-07 16:59 2464说到软件建模,一 ... -
行为聚集
2009-07-11 21:34 1312软件开发技术的技术本质在于对代码结构的有效控制. 我们 ... -
信道构建
2009-03-22 21:05 1450分层是最常见的软 ... -
同构与同态:认识同一性
2009-02-28 16:52 3258现代数学是建立在等价类这一概念的基础之上的。同构是对等 ... -
类型化:形而上学的信仰
2009-02-21 19:38 1638有一个心理 ... -
逆元:不存在的真实存在
2009-02-07 22:12 4331负数没有直接 ... -
文本化
2009-01-04 00:51 2078软件技术的发展是 ... -
关于代码生成和DSL
2008-11-23 11:52 5773代码生成(Code Ge ... -
软件不同于建筑
2008-09-01 23:26 1381软件系统的构建之所以与建筑工程不同,无法达到建筑工程的精 ... -
AOP on XML Tag
2008-07-07 00:09 1701AOP(Apsect Oriented Programm ... -
主从分解而不是正交分解
2008-05-26 00:36 2450说到分解,很多人心中的意象大概只有正交分解。正交分解无疑是 ... -
不完全的计算
2008-03-16 15:20 1662在与一些年岁较大的C程序员接触的过程中,可以比较明显的感 ... -
WebMVC之前世.今生
2008-02-18 22:23 1914所谓WebMVC即Model2模型是目前Web开发领域的主 ... -
关系模型与ORM
2008-01-06 19:20 2041关系数据库模型在理论上主要解决的是消除数据冗余的问题。 ... -
代码之外的结构
2007-12-15 19:49 1793我在各种场合一直都在强调结构问题是独立的,在程序语言之 ... -
结构的独立性
2007-12-11 00:00 2351设计考虑的是最终 ...
相关推荐
内容概要:本文详细介绍了如何利用威纶通触摸屏及其配套软件EasyBuilder Pro构建一个水箱液位控制的PID仿真程序。主要内容涵盖触摸屏界面设计、PID算法实现、通信配置以及仿真模型搭建等方面。文中不仅提供了具体的代码示例,还分享了许多调试经验和优化技巧,如抗积分饱和处理、通信同步设置等。此外,作者还强调了实际应用中的注意事项,例如参数范围限制、突发情况模拟等。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对PID控制器有一定了解并希望深入掌握其实际应用的人群。 使用场景及目标:适用于需要进行水箱液位控制系统设计、调试和优化的工作环境。主要目标是帮助读者理解和掌握PID控制的基本原理及其在实际工程项目中的具体实现方法。 其他说明:附带完整的工程文件可供下载,便于读者快速上手实践。文中提到的所有代码片段均经过实际验证,确保可靠性和实用性。
内容概要:《2024年中国城市低空经济发展指数报告》由36氪研究院发布,指出低空经济作为新质生产力的代表,已成为中国经济新的增长点。报告从发展环境、资金投入、创新能力、基础支撑和发展成效五个维度构建了综合指数评价体系,评估了全国重点城市的低空经济发展状况。北京和深圳在总指数中名列前茅,分别以91.26和84.53的得分领先,展现出强大的资金投入、创新能力和基础支撑。低空经济主要涉及无人机、eVTOL(电动垂直起降飞行器)和直升机等产品,广泛应用于农业、物流、交通、应急救援等领域。政策支持、市场需求和技术进步共同推动了低空经济的快速发展,预计到2026年市场规模将突破万亿元。 适用人群:对低空经济发展感兴趣的政策制定者、投资者、企业和研究人员。 使用场景及目标:①了解低空经济的定义、分类和发展驱动力;②掌握低空经济的主要应用场景和市场规模预测;③评估各城市在低空经济发展中的表现和潜力;④为政策制定、投资决策和企业发展提供参考依据。 其他说明:报告强调了政策监管、产业生态建设和区域融合错位的重要性,提出了加强法律法规建设、人才储备和基础设施建设等建议。低空经济正加速向网络化、智能化、规模化和集聚化方向发展,各地应找准自身比较优势,实现差异化发展。
内容概要:本文详细介绍了多智能体协同编队控制的技术原理及其Python实现。首先通过生动形象的例子解释了编队控制的核心概念,如一致性算法、虚拟结构法、预测补偿等。接着深入探讨了编队形状的设计方法,包括如何利用虚拟结构法生成特定编队形状,并讨论了通信质量和参数调试的重要性。此外,还涉及了避障策略、动态权重分配以及故障检测等实际应用中的挑战和解决方案。最后,通过具体实例展示了如何将理论应用于实际项目中,如无人机编队表演、自动驾驶车队等。 适用人群:对多智能体系统、编队控制感兴趣的科研人员、工程师及高校师生。 使用场景及目标:适用于研究和开发多智能体协同编队控制系统的场景,旨在帮助读者理解并掌握相关技术和实现方法,提高系统的稳定性和可靠性。 其他说明:文中不仅提供了详细的代码示例,还分享了许多实践经验和技术细节,有助于读者更好地理解和应用这些技术。同时强调了参数调试、通信质量、预测补偿等方面的关键因素对于系统性能的影响。
内容概要:本文详细介绍了名为'MPC_ACC_2020-master'的四旋翼飞行器模型预测跟踪控制器(Matlab实现)。四旋翼飞行器由于其高度非线性和强耦合特性,在复杂环境中难以实现精准控制。模型预测控制(MPC)通过预测未来状态并在每一步进行在线优化,解决了这一难题。文中展示了关键代码片段,解释了系统参数定义、初始化、预测模型构建、成本函数构建、优化求解及控制输入的应用。此外,还探讨了MPC_ACC_2020-master如何通过精心设计的成本函数和优化算法确保四旋翼飞行器状态收敛到设定点。 适合人群:从事飞行器控制领域的研究人员和技术爱好者,尤其是对模型预测控制感兴趣的开发者。 使用场景及目标:适用于四旋翼飞行器的轨迹跟踪任务,旨在提高飞行器在复杂环境下的稳定性与准确性。具体应用场景包括但不限于无人机竞速、自动巡航、物流配送等。 其他说明:尽管该项目主要用于科研目的,但其简洁高效的代码结构也为实际工程应用提供了良好借鉴。同时,项目中存在一些待改进之处,如状态估计部分未考虑真实情况下的噪声干扰,后续版本计划移植到C++并集成进ROS系统。
内容概要:本文探讨了基于MATLAB2020b平台,采用CNN-LSTM模型结合人工大猩猩部队(GTO)算法进行电力负荷预测的方法。首先介绍了CNN-LSTM模型的基本结构及其在处理多变量输入(如历史负荷和气象数据)方面的优势。随后详细解释了如何通过GTO算法优化超参数选择,提高模型预测精度。文中展示了具体的MATLAB代码示例,包括数据预处理、网络层搭建、训练选项设定等方面的内容,并分享了一些实践经验和技术细节。此外,还讨论了模型的实际应用效果,特别是在某省级电网数据上的测试结果。 适合人群:从事电力系统数据分析的研究人员、工程师,以及对深度学习应用于时间序列预测感兴趣的开发者。 使用场景及目标:适用于需要精确预测未来电力负荷的情况,旨在帮助电力公司更好地规划发电计划,优化资源配置,保障电网安全稳定运行。通过本研究可以学习到如何构建高效的CNN-LSTM模型,并掌握利用GTO算法进行超参数优化的具体步骤。 其他说明:文中提到的一些技巧和注意事项有助于避免常见错误,提高模型性能。例如,合理的数据预处理方式、适当的超参数范围设定等都能显著改善最终的预测效果。
数据集一个高质量的医学图像数据集,专门用于脑肿瘤的检测和分类研究以下是关于这个数据集的详细介绍:该数据集包含5249张脑部MRI图像,分为训练集和验证集。每张图像都标注了边界框(Bounding Boxes),并按照脑肿瘤的类型分为四个类别:胶质瘤(Glioma)、脑膜瘤(Meningioma)、无肿瘤(No Tumor)和垂体瘤(Pituitary)。这些图像涵盖了不同的MRI扫描角度,包括矢状面、轴面和冠状面,能够全面覆盖脑部解剖结构,为模型训练提供了丰富多样的数据基础。高质量标注:边界框是通过LabelImg工具手动标注的,标注过程严谨,确保了标注的准确性和可靠性。多角度覆盖:图像从不同的MRI扫描角度拍摄,包括矢状面、轴面和冠状面,能够全面覆盖脑部解剖结构。数据清洗与筛选:数据集在创建过程中经过了彻底的清洗,去除了噪声、错误标注和质量不佳的图像,保证了数据的高质量。该数据集非常适合用于训练和验证深度学习模型,以实现脑肿瘤的检测和分类。它为开发医学图像处理中的计算机视觉应用提供了坚实的基础,能够帮助研究人员和开发人员构建更准确、更可靠的脑肿瘤诊断系统。这个数据集为脑肿瘤检测和分类的研究提供了宝贵的资源,能够帮助研究人员开发出更准确、更高效的诊断工具,从而为脑肿瘤患者的早期诊断和治疗规划提供支持。
内容概要:本文详细介绍了STM32F103的CAN通讯和IAP升级Bootloader的源码实现及其硬件设计。首先,针对CAN通讯部分,文章深入探讨了CAN外设的初始化配置,包括波特率、位时间、过滤器等重要参数的设置方法,并提供了一段完整的初始化代码示例。接着,对于IAP升级Bootloader,文中讲解了通过CAN总线接收HEX文件并写入Flash的具体实现步骤,以及如何安全地从Bootloader跳转到应用程序。此外,文章还附上了原理图和PCB文件,有助于理解和优化硬件设计。最后,作者分享了一些实用的调试技巧和注意事项,如终端电阻的正确使用、CRC校验的应用等。 适合人群:嵌入式系统开发者、硬件工程师、从事STM32开发的技术人员。 使用场景及目标:适用于正在开发STM32相关项目的工程师,尤其是那些需要实现CAN通讯和固件在线升级功能的人群。通过学习本文提供的源码和技术要点,可以帮助他们快速掌握相关技能,提高开发效率。 其他说明:本文不仅提供了详细的代码示例,还包含了丰富的实践经验分享,能够帮助读者更好地理解和解决实际开发中遇到的问题。
工具集语音、监控、摄像头、画笔等功能于一体!清晰语音录入,确保声画同步;监控级画面录制,操作细节无遗漏;摄像头多视角呈现,让内容更生动。录制时,画笔可标注重点,快速传递关键信息。自带视频播放,无需第三方;快捷键操作便捷,录制高效。强大解码器兼容多格式,不同设备随心播放。无论是教学、办公还是创作
内容概要:本文详细介绍了西门子S7-1500 PLC在制药厂洁净空调建筑管理系统(BMS)中的应用案例。重点讨论了硬件配置(1500 CPU + ET200SP分布式IO)、温湿度控制策略(串级PID、分程调节)、以及具体的编程实现(SCL语言)。文中分享了多个技术细节,如PT100温度采集、PID控制算法优化、报警管理和HMI界面设计等。此外,作者还提到了一些调试过程中遇到的问题及其解决方案,如PID_Compact块的手动模式设定值跳变问题、博图V15.1的兼容性问题等。 适合人群:从事工业自动化领域的工程师和技术人员,特别是那些对PLC编程、温湿度控制和洁净空调系统感兴趣的读者。 使用场景及目标:适用于制药厂或其他对温湿度控制要求严格的行业。主要目标是确保洁净空调系统的高效运行,将温湿度波动控制在极小范围内,保障生产环境的安全性和稳定性。 其他说明:本文不仅提供了详细的编程代码和硬件配置指南,还分享了许多实践经验,帮助读者更好地理解和应用相关技术。同时,强调了在实际项目中需要注意的关键点和潜在问题。
2025年6G近场技术白皮书2.0.pdf
少儿编程scratch项目源代码文件案例素材-Frogeon.zip
2025年感知技术十大趋势深度分析报告.pdf
内容概要:本文详细介绍了一种用于解决车间调度问题的遗传算法(Matlab实现),即JSPGA。文章首先介绍了遗传算法的基本概念及其在车间调度问题中的应用场景。接着,作者展示了完整的Matlab源码,包括参数设置、种群初始化、选择、交叉、变异、适应度计算以及结果输出等模块。文中还特别强调了适应度计算方法的选择,采用了最大完工时间的倒数作为适应度值,并通过三维甘特图和迭代曲线直观展示算法性能。此外,文章提供了多个调参技巧和改进方向,帮助读者更好地理解和应用该算法。 适合人群:对遗传算法感兴趣的研究人员、工程师以及希望深入理解车间调度问题求解方法的技术爱好者。 使用场景及目标:适用于需要优化多台机器、多个工件加工顺序与分配的实际工业生产环境。主要目标是通过遗传算法找到最优或近似最优的调度方案,从而减少最大完工时间,提高生产效率。 其他说明:文章不仅提供了详细的理论解释和技术细节,还包括了大量实用的代码片段和图表,使读者能够轻松复现实验结果。同时,作者还分享了一些个人经验和建议,为后续研究提供了有价值的参考。
内容概要:本文深入探讨了永磁同步电机(PMSM)的最大转矩电流比(MTPA)控制算法,并详细介绍了基于Simulink的仿真模型设计。首先,文章阐述了PMSM的数学模型,包括电压方程和磁链方程,这是理解控制算法的基础。接着,解释了矢量控制原理,通过将定子电流分解为励磁电流和转矩电流分量,实现对电机的有效控制。随后,重点讨论了MTPA控制的目标和方法,即在限定电流条件下最大化转矩输出。此外,文章还涉及了前馈补偿、弱磁控制和SVPWM调制等关键技术,提供了具体的实现代码和仿真思路。最后,通过一系列实验验证了各控制策略的效果。 适合人群:从事电机控制系统设计的研究人员和技术人员,尤其是对永磁同步电机和Simulink仿真感兴趣的工程师。 使用场景及目标:适用于希望深入了解PMSM控制算法并在Simulink环境中进行仿真的技术人员。主要目标是掌握MTPA控制的核心原理,学会构建高效的仿真模型,优化电机性能。 其他说明:文中不仅提供了详细的理论推导,还有丰富的代码示例和实践经验,有助于读者快速理解和应用相关技术。同时,强调了实际工程中常见的问题及解决方案,如负载扰动、弱磁控制和SVPWM调制等。
内容概要:本文详细介绍了三机并联的风光储混合系统在Matlab中的仿真方法及其关键技术。首先,针对光伏阵列模型,讨论了其核心二极管方程以及MPPT(最大功率点跟踪)算法的应用,强调了环境参数对输出特性的影响。接着,探讨了永磁同步风机的矢量控制,尤其是转速追踪和MPPT控制策略。对于混合储能系统,则深入讲解了超级电容和蓄电池的充放电策略,以及它们之间的协调机制。此外,还涉及了PQ控制的具体实现,包括双闭环结构的设计和锁相环的优化。最后,提供了仿真过程中常见的问题及解决方案,如求解器选择、参数敏感性和系统稳定性等。 适合人群:从事电力电子、新能源系统设计与仿真的工程师和技术人员,以及相关专业的研究生。 使用场景及目标:适用于希望深入了解风光储混合系统工作原理的研究人员,旨在帮助他们掌握Matlab仿真技巧,提高系统设计和优化的能力。 其他说明:文中不仅提供了详细的理论推导和代码示例,还分享了许多实践经验,有助于读者更好地理解和应用所学知识。
本书由国际发展研究中心(IDRC)和东南亚研究院(ISEAS)联合出版,旨在探讨亚洲背景下电子商务的发展与实践。IDRC自1970年起,致力于通过科学技术解决发展中国家的社会、经济和环境问题。书中详细介绍了IDRC的ICT4D项目,以及如何通过项目如Acacia、泛亚网络和泛美项目,在非洲、亚洲和拉丁美洲推动信息通信技术(ICTs)的影响力。特别强调了IDRC在弥合数字鸿沟方面所作出的贡献,如美洲连通性研究所和非洲连通性项目。ISEAS作为东南亚区域研究中心,专注于研究该地区的发展趋势,其出版物广泛传播东南亚的研究成果。本书还收录了电子商务在亚洲不同国家的具体案例研究,包括小型工匠和开发组织的电子商务行动研究、通过互联网直接营销手工艺品、电子营销人员的创新方法以及越南电子商务发展的政策影响。
2025工业5G终端设备发展报告.pdf
内容概要:本文档《Java经典面试笔试题及答案.docx》涵盖了广泛的Java基础知识和技术要点,通过一系列面试题的形式,深入浅出地讲解了Java的核心概念。文档内容包括但不限于:变量的声明与定义、对象序列化、值传递与引用传递、接口与抽象类的区别、继承的意义、方法重载的优势、集合框架的结构、异常处理机制、线程同步、泛型的应用、多态的概念、输入输出流的使用、JVM的工作原理等。此外,还涉及了诸如线程、GUI事件处理、类与接口的设计原则等高级主题。文档不仅解释了各个知识点的基本概念,还提供了实际应用场景中的注意事项和最佳实践。 适合人群:具备一定Java编程基础的学习者或开发者,特别是准备参加Java相关岗位面试的求职者。 使用场景及目标:①帮助读者巩固Java基础知识,提升对Java核心技术的理解;②为面试做准备,提供常见面试题及其详细解答;③指导开发者在实际项目中应用Java的最佳实践,优化代码质量和性能。 其他说明:文档内容详实,涵盖了Java开发中的多个方面,从基础语法到高级特性均有涉及。建议读者在学习过程中结合实际编程练习,加深对各个知识点的理解和掌握。同时,对于复杂的概念和技术,可以通过查阅官方文档或参考书籍进一步学习。
内容概要:本文详细介绍了如何利用MATLAB将预训练的深度学习模型(如ResNet50、YOLOv2和LaneNet)转化为高效的C++代码,并部署到嵌入式系统中。首先,通过ResNet50展示了图像分类任务的代码生成流程,强调了输入图像的预处理和归一化步骤。接着,YOLOv2用于车辆检测,讨论了anchor box的可视化及其优化方法,特别是在Jetson Nano平台上实现了显著的速度提升。最后,LaneNet应用于车道线识别,探讨了实例分割和聚类算法的实现细节,以及如何通过OpenMP和CUDA进行性能优化。文中还提供了多个实用技巧,如选择合适的编译器版本、处理自定义层和支持动态输入等。 适合人群:具有一定MATLAB和深度学习基础的研发人员,尤其是关注嵌入式系统和高性能计算的应用开发者。 使用场景及目标:适用于希望将深度学习模型高效部署到嵌入式设备的研究人员和工程师。主要目标是提高模型推理速度、降低内存占用,并确保代码的可移植性和易维护性。 其他说明:文中不仅提供了详细的代码示例和技术细节,还分享了许多实践经验,帮助读者避免常见的陷阱。此外,还提到了一些高级优化技巧,如SIMD指令集应用和内存管理策略,进一步提升了生成代码的性能。
内容概要:本文详细介绍了如何利用MATLAB进行综合能源系统的优化建模,特别是将需求响应和碳交易机制融入其中。首先,文章展示了购能成本计算、燃气锅炉成本以及需求响应(包括价格型和替代型)的具体实现方法。接着,深入探讨了碳交易机制的实现,如碳配额分配、实际碳排放计算及其成本核算。此外,文章还提供了四个典型场景的实现方法,通过调整不同的边界条件来模拟各种实际情况。最后,讨论了一些常见的编程技巧和注意事项,如使用YALMIP工具箱、CPLEX求解器的配置等。 适用人群:适用于从事综合能源系统研究和技术开发的专业人士,尤其是那些对MATLAB编程有一定基础的研究人员和工程师。 使用场景及目标:①帮助研究人员理解和实现综合能源系统的优化模型;②探索需求响应和碳交易机制对能源系统调度的影响;③提供实用的编程技巧和优化建议,提高模型的准确性和求解效率。 其他说明:文中提供的代码片段和编程技巧对于实际工程项目具有很高的参考价值,能够显著提升模型的灵活性和实用性。同时,文章还提到了一些潜在的改进方向,如引入更多类型的能源转换设备和优化算法。