我正在开发一个工具,它将生成一个接口的源代码和几个实现该接口的类.我的输出并不是特别复杂,因此输出符合我们正常的代码格式标准并不难.
但这让我想到:自动生成的代码需要多么可读?什么时候应该花费额外的努力来确保生成的代码很容易被人类阅读和理解?
在我的例子中,我生成的类本质上只是与构建的另一部分相关的一些数据的容器,其中包含获取数据的方法.没有人需要查看类本身的代码,他们只需要调用类提供的各种getter.因此,如果代码"干净",格式良好且易于人类阅读,则可能并不太重要.
但是,如果您生成的代码中包含少量简单逻辑,会发生什么?
我们在自己的设计师中使用DesignSurface和所有优秀的IDesignerHost优点.然后,设计的表格将以我们自己的定制格式保存,并且所有这些都非常有用.我们还希望将表单导出为基于文本的格式(我们已经完成了,因为它并不困难).
但是,我们还希望将该文本导入设计器的文档中,该文档涉及将设计器代码重新放回CodeCompileUnit.不幸的是,Parse方法没有实现(毫无疑问,很好的理由).还有其他选择吗?我们不想使用标准.NET安装中不存在的任何东西(比如用Visual Studio安装的.NET库).
我目前的想法是编译导入的文本然后实例化表单并将其属性和控件复制到设计表面对象,并只捕获新的CodeCompileUnit,但我希望有更好的方法.谢谢.
更新:我可能会对我们的进展感兴趣.到目前为止,还不是那么好.我发现的一个简要概述是Parse方法没有实现,因为它被认为太难了,开源解析器存在,但是它们不完整,因此无法保证在所有情况下都能工作( NRefactory是SharpDevelop项目中的一个,我相信,并且从实例到设计器的控件复制工作尚未完成.我相信这是因为虽然控件被添加到设计器表面包装的表单实例中,但设计者表面并未意识到它们的包含.我们的下一个尝试是模仿剪切/粘贴,看看是否能解决它.显然,这是一个巨大的讨厌的解决方法,但我们需要它工作,所以我们'
是否有支持从注释生成一些标准单元测试的框架?我想到的一个例子是:
@HasPublicDefaultConstructor
public class Foo {
}
Run Code Online (Sandbox Code Playgroud)
这显然会用于自动生成一个单元测试,用于检查Foo是否具有默认构造函数.我是唯一一个想到这样的人吗?虽然我对Java最感兴趣,但其他语言的解决方案肯定也很有趣.
编辑:回应S.Lott的回答,让我澄清一下:
我正在尝试测试该类是否具有默认构造函数.(当然这只是一个例子.)我可以通过编写测试来做到这一点,但我觉得这很乏味.所以我正在寻找一种工具,可以在编译时处理注释(通过APT)并为我生成测试.这样的事情存在吗?如果没有,你认为这是个好主意吗?
我曾经研究过许多利用代码生成的产品.它似乎是实现高度用户可定制性和高执行速度的唯一方法.
缺点是我们要求用户安装编译器(主要在MS Windows上).
这一直是一个令人头痛的问题,因为像MS这样的供应商一直在淘汰编译器,有些用户往往安装了多个编译器.
我们正在考虑使用GNU C,可能还有C++,但即使在那里,也存在持续的版本问题.
我考虑过可能会生成汇编语言,试图摆脱编译器版本的跑步机,但汇编语言都是机器特定的.
理想情况下,可以通过某种方式生成生成的代码,这些代码具有灵活性,运行速度快,并且不会让我们看到第三方提供商的突发奇想.
也许我忽略了一些简单的东西,比如Java.任何想法,将不胜感激.谢谢.
我正在为Haskell中的简单命令式语言编写编译器,输出Java字节码.我已经到了我发出字节码的抽象表示的地步.
在编写用于编译if语句的代码时遇到了一些麻烦.要实现if语句,我需要跳转到标签.因此,我需要为该标签生成一个名称,该名称必须是唯一的.
我的第一个想法是通过一些状态compileStatement,即
compileStatement :: Statement -> UniqueIDState -> [AbstractInstruction]
Run Code Online (Sandbox Code Playgroud)
当然,compilerStatement是递归的,所以使用这种方法需要我从递归调用中将唯一ID生成器的状态传递回upp:
compileStatement :: Statement -> UniqueIDState -> (UniqueIdState, [AbstractInstruction])
Run Code Online (Sandbox Code Playgroud)
这看起来有点笨拙,特别是如果我意识到我需要在将来携带更多状态; 有更优雅的方式吗?
Hibernate默认创建一个globel序列,用于为所有表生成id(在PostgreSQL的情况下),它可以扩展非常糟糕的恕我直言.虽然我可以为每个实体类型指定使用哪个序列,但我不喜欢这样做.我不喜欢明确命名序列和强制使用序列作为生成器策略,因为我希望hibernate为可能根本不支持序列的数据库生成DDL.单个全局序列也使得无法使用32位int作为主键,这意味着我必须将所有int id转换为long类型.
标题基本上都说明了一切.我尝试过谷歌搜索,但返回了大量的误报.我想我只是想知道这两个具体数字背后是否有一定的理由,或者他们是否很容易就有其他许多数字?
编辑:并且,由于数字的来源已被回答,布尔hashCode方法的编写者使用这些数字的任何理由(除了他们是素数)?其他任何一个素数都可以效果吗?
是否可以创建一个扩展方法来返回对象列表中的单个属性或字段?
目前我有很多功能,如下所示.
public static List<int> GetSpeeds(this List<ObjectMotion> motions) {
List<int> speeds = new List<int>();
foreach (ObjectMotion motion in motions) {
speeds.Add(motion.Speed);
}
return speeds;
}
Run Code Online (Sandbox Code Playgroud)
这是"硬编码",仅在单个对象类型中提供单个属性.它很乏味,我确信有一种方法可以使用LINQ/Reflection来创建一个可以通用和可重用方式执行此操作的扩展方法.像这样的东西:
public static List<TProp> GetProperties<T, TProp>(this List<T> objects, Property prop){
List<TProp> props = new List<TProp>();
foreach (ObjectMotion obj in objects) {
props.Add(obj.prop??);
}
return props;
}
Run Code Online (Sandbox Code Playgroud)
除了使用LINQ的最简单的方法,我也在寻找最快的方法.是否可以使用代码生成(和Lambda表达式树)在运行时创建这样的方法?我确信这比使用Reflection更快.
我正在使用.properties文件进行邮件国际化.例如:
HELLO_WORLD = Hello World
HELLO_UNIVERSE = Hello Universe
Run Code Online (Sandbox Code Playgroud)
然后在Java代码中:
String foo = resourceBundle.getString("HELLO_WORLD");
Run Code Online (Sandbox Code Playgroud)
字符串文字是"HELLO_WORLD"有问题的,因为它们容易出错并且无法自动完成.我想从属性文件中的键生成代码,如下所示:
public interface Messages { // Or abstract class with private constructor
public static final String HELLO_WORLD = "HELLO_WORLD";
public static final String HELLO_UNIVERSE = "HELLO_UNIVERSE";
}
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
String foo = resourceBundle.getString(Messages.HELLO_WORLD);
Run Code Online (Sandbox Code Playgroud)
有没有标准的方法来做到这一点?我更喜欢Maven插件,但我可以手动运行的任何独立工具都足以满足我的需求.
Let's consider this trivial code:
#include <atomic>
std::atomic<int> a;
void f(){
for(int k=0;k<100;++k)
a.load(std::memory_order_relaxed);
}
Run Code Online (Sandbox Code Playgroud)
MSVC, Clang and GCC all perform 100 loads of a, while it seems obvious it could have been optimized away. I expected the function f to be a nop (See generated code here)
Actually, I expected this code generation for a volatile atomic:
volatile std::atomic<int> va;
void g(){
for(int k=0;k<100;++k)
va.load(std::memory_order_relaxed);
}
Run Code Online (Sandbox Code Playgroud)
Why do compilers not optimize away unnecessary atomic loads?
code-generation ×10
java ×3
c# ×2
.net ×1
algorithm ×1
annotations ×1
atomic ×1
automation ×1
c++ ×1
ddl ×1
designer ×1
eclipse ×1
equals ×1
haskell ×1
hibernate ×1
oop ×1
orm ×1
readability ×1
reflection ×1
unit-testing ×1
volatile ×1
winforms ×1