代码自动生成和抽象

18、佩特里网自动抽象细化与异步通信机制合成方法 本文研究了佩特里网的自动抽象细化方法及其在异步通信机制(ACM)合成中的应用。通过使用 C 语言实现算法 2,结合符号数据结构和模型检查器,有效降低了佩特里网的维度,提高了验证效率。实验结果表明,该方法在参数化系统和有界佩特里网中均表现出色,能够发现手工难以找到的约简。同时,提出了一种基于佩特里网的 ACM 自动合成方法,采用模块化方式生成模型,避免了状态空间爆炸问题,并通过模型检查确保连贯性和新鲜度属性。最后,文章展望了未来在算法优化和 ACM 类型扩展方面的研究方向。 阅读详情

代码自动生成和抽象

Hoping (原作)

 

基本概念

抽象在软件开发中的重要性是不言而喻的。如果一个系统有了正确的抽象,那么这个系统就更容易理解,更容易维护,开发起来也更为高效,最为重要的是也更容易把事情作对。Grady Booch甚至认为抽象是应对软件复杂性最为有效的手段。在面临一个复杂的系统时,往往只要再提升一层抽象层次(当然要是正确的抽象),那么该系统就会立即变得清晰、简单,理解、开发、维护起来也更为容易一些。不过,值得注意的是,虽然有了一个正确的抽象后,可以大大降低理解、开发和维护的难度,但是要想得到一个正确、合适的抽象却是非常困难的。

 

提起代码自动生成,可能大多数人立即会想到这样一种情形:只要获取了系统的需求,那么就会自动地从这些需求生成系统的代码。这种想法固然很好,但是在目前的科学发展水平(这种技术不单是软件技术的问题,它还和人思维的生物基础有密切关系)下却还无法实现。需求和能够自动转化为代码的精确的形式化规范之间有一个巨大的鸿沟,目前这项转换工作还只能由人来独立地完成。因此,这种技术在目前来说只能是一个神话。我们在本文中所指的代码自动生成是针对比较局限的领域而言的,即需求已经被正确的理解并由人转化为解决方案领域中的抽象模型。代码自动生成并不是为了替代人去完成系统的软件开发的,它只是一种支援抽象的工具而已。

 

领域特定语言(DSL)

其实,大家在每天的软件开发中都在不经意的使用着这项工具。当我们在使用面向对象语言进行软件开发时,其实我们是在一种抽象的层面上进行工作。有了这层抽象,我们所编写的软件就会更有表现力,更为简洁。比如:当我们写下下面的代码行时:class  Cat  extends  Animal。我们想表达的是Cat is a Animal,面向对象语言为我们提供了强有力的支持。而这个抽象的实现细节则由编译器来完成,我们无需关心。这样我们就能够在一个更高、更直接、更易于理解抽象的层面进行开发和交流,同时也大大降低了出现错误的机会。当我们使用支持泛型或者AOP的语言进行软件开发时,其实我们是在另外一种抽象层面上工作。比如:当我们写下如下代码时:

template

T Add(T, T)

我们想表达的是求两个类型为T的变量之和,而不管T到底是什么具体类型。想想看,如果语言不支持这种表达规范,我们要写多少个雷同的Add方法。有了这种表达规范,我们就可以直接、简洁地表达出我们的意图,而具体的转换工作就有编译器代劳了。还有,如果我们在支持AOP的环境中进行软件开发,那么我们只要使用该环境提供的AOP语言规范定义出我们希望的横切关系(其实就是一种抽象),剩余代码的编写和插入工作就由该环境帮我们自动完成了。虽然编译器或者开发环境在底层生成的实际上也是大量重复的代码,但是这些代码的抽象规范却只有一份,而人们开发、维护、沟通所基于的正是这唯一的一份抽象规范,底层的重复实现细节对开发者来说是不可见的,并且是自动和抽象规范保持一致的。可以说,在开发者的头脑中,是没有重复的。从而有力的支持了“once and only once”和DRY原则。试想,如果语言种没有提供这种描述规范,那么我们要编写多少晦涩、难懂、重复的代码才能描绘我们想要表达的概念。

 

上面提到的抽象是一些比较通用的机制,因此一般都是语言内置支持的。也正是其通用性使其有效性范围受到了限制。一般来说,上面的一些抽象机制是仅仅针对开发者群体而言的,并且使用这些抽象机制进行的表达也是由编译器来自动生成底层执行代码的。但是,还有一种抽象表达更为重要,它的作用是在开发者和客户之间进行沟通、交流。说它重要是因为它和所要开发的系统是否能够真正满足客户需要密切相关。这种抽象表达更贴近具体的问题领域,因此也称为领域相关语言(Domain-Specific Language(DSL))。比如,如果我们开发的是一个金融系统,那么如果我们能够使用一套金融术语及其关系来刻画金融领域中的一些业务逻辑,那么不但表达起来会简洁、直接得多,更重要的是客户也更容易理解,和客户沟通起来也更为容易。再如,如果我们要开发一个科学计算系统,那么如果我们拥有了一套描述科学计算领域的词汇,那么在表达该系统时不但会容易、自然很多,而且也更加高效。有了这套DSL之后,剩下的工作就是要自己实现一个编译/解释器,来把DSL自动生成为目标语言。由于这个DSL一般都局限于某个特定领域,因此其编译/解释器实现起来也不会有多大困难。

 

       敏锐的读者一定会发现,我们在前面列举的支持面向对象(OO)、泛型(GP)或者面向方面(AOP)的语言,其实也是DSL的一种。只不过它们所针对的是更为通用的,和软件要面临的实际问题领域无关的领域。它们的作用是为了提高一些通用问题描述的抽象层次,并且也为构建更贴近问题领域的抽象提供了基础。

 

自上而下 还是 自下而上?

写到这里我突然想起一个非常有趣的问题,那就是大家常常争论的自上而下开发和自下而上开发。一般认为,自上而下的开发方法更具目的性一些,也更为自然一些。其实自上而下的方法是有很大风险的,一是往往很多预先的设想很可能本身就是错的,一是这些预先设想落实到底层时要么无法实现,要么无法很好地适配。其结果就是生成一个具有大量冗余、丑陋粘合层代码的系统。而采用DSL思想的自下而上方法则具有很多你可能没有想到的好处。你可以先实现一些DSL中的单个单词,然后再实现一些更大的单元,并试着把这些元素组合为更大的领域逻辑,按照这种方法实现起来的系统往往更加简洁、清楚、干净,甚至更加易于重用。一般来说,如果你想采用DSL的开发方式,动态语言大有用武之地(Python、Ruby都是不错的选择,在www.martinfowler.com/bliki中,Martin Fowler对动态语言和DSL的关系进行了深入、有趣的描述)。

 

自下而上的做法实际上是在改变、扩充开发语言,使其适合于所面临的问题领域。当你进行软件系统的开发时,你不仅仅只是把你所构思的程序直接映射到实现语言,同时你还不断对语言进行增强,使其更加贴近你所构思的程序,并且表达起来能够更加简单、更加直接。比如:你会想语言中如果有了这个操作符,表达起来就更加清楚、简洁了,那么你就去构建它。这样,语言和程序就会一同演化,直到二者能够形成一种完美的匹配关系。最后,你的程序看起来就会像是用专门为它设计的语言开发的。而当语言和程序能够很好地相互适合时,所编写的代码也就会更清晰、更少、更有效。

 

       值得注意的是,自下而上设计相对于自上而下设计来说,并不意味着用不同的顺序来编写同样的程序。当采用自下而上设计时,常常会得到一个和自上而下设计不同的程序。所得到的不会是一个单一的单片机(monolithic)程序,而是一个具有更多抽象操作符的更“大”的语言和一个用该语言编写的更“小”的程序。此外,这个语言的抽象操作符也很容易在其他的类似的程序中得以重用,所编写程序也更加易读、更加易于理解。

 

       还有一点值得提出,那就是自下而上的开发方法可以尽快地得到来自代码的反馈,可以及时进行重构。我们大家可能都已经知道,设计模式一般是重构的目标,这里我想特别指出的是:DSL往往也是很好的重构目标。

 

抽象、库和DSL

C++之父Bjarne Stroustrup经常强调的“用库来扩充语言,用库来进行思考”( http://www.artima.com/intv/elegance.html有近期对Bjarne Stroustrup的采访,他再次强调了这个问题),其实就是在强调DSL以及自下向上开发的重要性。库就是DSL的一种形式,Bjarne Stroustrup所列举的科学计算库的例子就是科学计算领域的DSL。构建库的过程其实就是在朝着更加贴近问题领域抽象的方向迈进。明白了这一点,我们就不难理解Bjarne Stroustrup一直强调的泛型在构建一个优雅、高效库的方面的重要性了,因为泛型为构建这种抽象提供了一个坚实的基础。

 

       不仅C++如此,其他一些语言(比如:Java)也拥有众多的库。这些库在我们进行软件开发时,为我们提供了强大的支持。不过,这些库往往都只实现了它所针对领域的一些通用基础性的问题。因此,在某些特定问题上,可能无法直接地使用这些库来进行表达。此时,你就应该考虑建立一个特定于自己问题的特定库了。

 

结论

      作为开发者的我们,该如何做呢?正如本文开始所说的,抽象固然很好,但是要找出适合于自己手边问题的抽象是一件很困难的事。它应该是一个不断从代码编写中得到反馈,然后再修正,接着再编写代码的循环反馈的过程,这也是我为何认为自下而上开发更为有效的原因。我们不应该局限于仅仅会使用某一种工具,某一种开发环境,而应该多想想这些工具、开发环境背后蕴涵的思想。我们应该注重于培养自己发掘抽象的能力,这方面能力的培养既需要很好的和客户沟通的能力,同时还需要有坚实、高超的软件能力。

 

此外,近期热的不能再热的技术MDA,其核心思想其实就是DSL,不过我对于其试图使用一种语言来刻画所有领域模型的做法并不看好。与其使用它,倒不如逐步演化出一个特定于自己问题领域的Mini DSL和一个DSL编译/解释器,并基于这个DSL来进行开发,这样或许更为直接一些,更为轻便一些,更为清晰一些、更为有效一些,更加具有针对性一些,也更为经济一些J

 

参考文献

[1]  Eric Steven Raymond, The Art of Unix Programming

[2] Eric Evans, Domain-Driven Design: Tackling Complexity in the Heart of Business Software

[3] Andrew Hunt, David Thomas, The Pragmatic Programmer:  From Journeyman to Master

[4] Grady Booch, Object-Oriented Analysis and Design with Application

 




Archer 射手 立即下载

相关推荐

万能代码生成器

万能代码生成器 , 支持元数据、模板, 可以 自己配置元数据和模板,

一些抽象的代码写法

1

weixin_51437526的博客 640

kings-guard-archer-defense:国王卫队

国王卫队:弓箭手防御 King's Guard: Archer Defense 是一款 HTML5 动作/塔防混合视频游戏。 你可以在玩。 但它可能还没有工作。 语言、框架和库 HTML5/CSS 标记用作游戏实例的外壳。 用于创建客户端游戏代码。 TypeScript 代码被编译为 JavaScript。 使用的游戏框架是 。 Phaser 提供了一个 TypeScript 定义文件。 工具 用于生成精灵表和动画数据。 我打算修补编辑器的代码,以便能够直接导出到 Phaser 理解的纹理图集格式(目前,这种转换是在 AnimationLoader.ts 下完成的)。 这个游戏正在进行中。 短期内不要期望太多。 如果您对更多详细信息感兴趣,请随时。

BladeX——精心设计的微服务架构

BladeX——介绍

weixin_72076848的博客 3万+

计算思维之抽象与自动化——以Kodii编程中的“吃苹果”为例.pdf

计算思维之抽象与自动化——以Kodii编程中的“吃苹果”为例.pdf

C++调用海康相机SDK采集图像(C++\QT Creator\openCV\线程\接口)

C++调用海康相机SDK采集图像(C++\QT Creator\openCV\线程\接口) 之前写了一篇关于C++调用海康相机SDK采集图像的文章,有很多人私下发送消息咨询了一些问题,由于工作繁忙,只答复了一部分问题,今天抽出时间从头梳理了一下大家提出的问题,把我能够回答的问题都解答一次。上一次的程序只是简单的实现了图像的采集,没有使用到线程,今天把程序重新做出调整,把线程和多态加进去。文章最后有项目的下载地址。 我使用的是QT Creator这个IDE,版本信息如下: 我把相机采集的图像转换为openC

大樱桃的博客 1万+

Java抽象类代码示例

在Circle类中,我们定义了一个私有变量radius(半径),定义了俩个构造方法Circle() 、Circle(double radius),其中Circle()无参构造方法用于初始化圆半径,而Circle(double radius)有参构造方法用传入参数初始化半径,且判断传入参数是否合法,如果不合法则抛出一个异常对象(IllegalArgumentException)。(2)注意抽象类可以不定义抽象方法,都是如果一个类中要定义抽象方法,那这个类必须是抽象类。

2301_80284166的博客 936

游戏开发实战:如何用旋转矩阵实现2D角色平滑转向(附Unity代码)

本文深入探讨了在Unity游戏开发中,如何运用旋转矩阵原理实现2D角色的平滑转向。文章从核心理论出发,提供了计算目标旋转、实现平滑插值(Lerp与SmoothDamp)的完整C#代码,并解决了与动画系统、物理引擎协同的常见难题,帮助开发者提升游戏操作手感与视觉流畅度。

weixin_29057237的博客 287

代码抽象

代码抽象应基于以下思路: (1)保留核心逻辑,把与核心逻辑无关的代码抽象出去 (2)保留完整语境(上下文环境) 方法名,参数应能完整体现被抽象代码的含义 (3)代码抽象出来,应方便阅读而不能影响阅读; 这块代码抽象出的joinListStr就比较好,抽取出无关紧要的代码,能够减少核心方法中代码篇幅,便于理解和阅读代码; ...

LMJ2057113352的博客 646

【人工智能】Cursor模型被封?两步教你破解

Cursor模型全线被禁,主流模型如Claude、GPT-4无法访问,仅剩Deepseek等基础模型可用。官方证实限制源于上游API区域政策,提供三种"无效"解决方案引发用户不满。社区发现有效解决方式:需同时开启全局代理和将Cursor网络设置改为HTTP/1.1协议,详细步骤包括修改用户设置和完全重启程序。另有SOCKS5代理配置方案供高级用户选择。技术原理推测HTTP/1.1可绕过区域检测。用户面临继续使用或转投其他工具的选择,社区交流受限但仍有讨论。

奶爸的编程之路,也就一周冷个三天 2199

Spring AI Alibaba实战训练营-14基于A2A协议智能体应用开发指南

本文介绍了基于A2A协议的智能体应用开发流程,主要包括客户端和服务端两个模块的实现。关键技术包括A2A通信协议、Nacos服务发现、Spring AI Alibaba框架和DashScope通义千问API。开发步骤涵盖环境准备(JDK17、Maven、Nacos)、项目创建、依赖配置(重点引入spring-ai-alibaba相关组件)以及Nacos和DashScope的核心配置。整个系统架构采用客户端通过Nacos发现服务端Agent,再调用阿里云AI服务的模式,实现了AI能力的解耦与复用。

program哲学 506

深入分析MapStruct源码:为什么只需写抽象接口就能自动生成代码

在Java开发中,数据对象之间的转换是一个非常常见的需求。手动进行这些转换不仅冗长且容易出错,因此,引入自动化转换工具显得尤为必要。MapStruct 就是这样一个高效、强大的类型转换工具,它通过注解和接口自动生成转换代码。本文将深入探讨MapStruct为什么只需定义一个抽象接口,就能自动生成实现代码的奥秘。MapStruct 是一款Java的代码生成器,旨在通过注解方式自动生成Java Bean之间的转换代码。

heyongjin22的博客 1796

基于BERTopic模型的英文20新闻数据集主题聚类及可视化

BERTopic是基于深度学习的一种主题建模方法。BERT是一种用于NLP的预训练策略,它成功地利用了句子的深层语义信息。

Cachel Wood的博客 1461

java_抽象类

抽象类1,语法定义抽象类前使用abstract关键字修饰,则该类为抽象类2.应用场景(1)在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法。 (2)从多个具有相同特征的类抽象出一个抽象类,以这个抽象类作为子类的模板,从而避免了子类设计的随意性 3.作用 限制规定子类必须实现某些方法,但不关注实现细节 (主要目的:不关注子类的实现。但是要约束子类...

weixin_30314813的博客 161

芒果YOLO11改进44:主干Backbone篇之MobileViT::结合最新 ICLR2022 顶会|轻量通用的MobileViT结构(一)Transformer,轻量级、通用且移动友好的视觉转换

MobileViT::结合最新 ICLR2022 顶会|轻量通用的MobileViT结构(一)Transformer,轻量级、通用且移动友好的视觉转换

包括YOLOv5、YOLOv7、YOLOv8等模型改进 371

18、项目运行与调试全攻略

本文详细介绍了在IntelliJ IDEA中进行项目运行与调试的完整流程,涵盖运行配置的创建与管理、临时配置的使用与保存、运行窗口的控制台操作及多程序并行运行的处理。同时,讲解了如何通过调试器定位和修复语法错误、运行时错误及逻辑错误,并结合ACME项目演示了第三方库Log4J的集成方法和命令行客户端的功能改进。文章还提供了调试流程图,帮助开发者系统掌握IDEA的强大调试功能,提升开发效率与代码质量。

svm4gardener的博客 76

Python的抽象语法树

Python的AST提供了一种强大的机制来分析和修改Python代码。它在自动化代码审查、重构工具和其他需要编程方式处理源代码的场合中非常有用。

weixin_49520696的博客 506

如何用 ABAP 以程序方式把指定表项写入 Transport Request

本文探讨了在SAP系统中运输自定义配置表数据时如何确保主表和相关文本表数据同步运输的问题。文章分析了两种实现方案:一是直接操作CTS表结构(E071和E071K)手动添加运输条目,二是使用SOBJ对象类型自动推导依赖关系。重点阐述了第一种方法的实现细节,包括如何正确拼接表键值到TABKEY字段,并提供了示例代码说明如何将ZXA_HEADER主表和ZXA_HEADERT文本表数据同时加入运输请求。文章特别指出在全球化交付场景中,文本表缺失会导致界面显示异常,强调理解底层运输机制对解决此类问题的重要性。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 221

避免重复造轮子!用C++元编程实现零成本抽象与代码自动生成

掌握高效开发秘诀!利用C++元编程实现编译期计算与代码生成,避免重复造轮子。适用于模板库设计、类型反射等场景,达成零成本抽象与自动化代码生成,提升性能与可维护性,值得收藏。

QuickCode的博客 825

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

【Python程序开发系列】一文带你了解Python抽象语法树(案例分析)

一文带你了解Python抽象语法树(案例分析)

数据杂坛 1639

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

自定义APT终极—>生成有参抽象工程

接着上篇 自定义apt实战之一>抽象工厂 在和Java后台的同事聊天的时候,发现他们经常使用Data-Map来存放类名,然后通过反射来初始化。我在想为什么不用抽象工厂呢?抽象工厂和策略反射相比较: 优点: 抽象工厂无反射,性能相对较高; Data-Map每次增加 一个类,都需要在Data_Map里面进行注册,一不小心还有可能key重复; 缺点: 抽象工厂强依赖,不符合高内聚低耦合的设计思想; 抽象工厂要写很多if-else,不够优雅,每次新增类都要增加if-else; 特别是针对我现在工作内容,各种协议,每

wengliuhu的博客 207

Action模型 -- 增强型UML建模和后台代码的自动生成工具

Action模型主要是融合了三项堪称黑科技的技术:无需考虑并发的并发模型、无需时间输入的时间模型、N元关联也支持Qualifier的关联模型。只要是有增删改查需求的系统都可以应用Action模型,从而使得Action模型具有广阔的应用前景。

Down345的专栏 720

Flutter 三方库 code_builder 的鸿蒙化适配指南 - 实现具备流式语法抽象的代码自动生成引擎、支持端侧元编程与高性能插件开发实战

在进行 Flutter for OpenHarmony 的大规模工程化、自动化测试或复杂插件开发(如 ORM 框架、JSON 序列化器)时,如何通过程序逻辑动态生成稳定、格式规范且符合 Dart 语法的源码文件?手动拼接字符串不仅极易引发语法错误,更是一场维护噩梦。是 Dart 生态中用于“代码生成代码”的权威基础设施,它提供了强大的抽象语法树(AST)构建能力。本文将探讨如何在鸿蒙端利用此神器构建极致、稳健的自动化生产线。采用“声明式 Builder 模式”。

jiang_style的博客 4245
上一篇: 权衡的艺术
下一篇: 软件测试认识中的误区
techcrunch
博客等级 码龄19年 34粉丝 3441原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值