前言
这是我《回顾我的开发经历》系列的第二篇,聚焦于我与代码生成器的故事。从最初的简单工具到最终演变成一个功能强大的ORM框架,这段经历不仅让我在技术上得到了极大的提升,也让我深刻理解了重构、设计模式和系统架构的重要性。希望通过这篇文章,能为大家提供一些启发和思考。
初识代码生成器
工作几年后,我第一次接触到了代码生成器。虽然最初的版本非常简单,但这个思路让我眼前一亮。在接下来的十几年里,我不断扩展和完善这个代码生成器,最终实现了通过数据库自动生成具备完整增删改查功能的网站。这段经历让我受益匪浅,我将其中一些关键点总结在这篇博客中:代码生成器的成长历程。
代码生成器与阅读
刚开始编写代码生成器时,我对面向对象开发的理解还很模糊。当时,我正在阅读《C# Primer Plus》,一边学习,一边将书中的知识应用到代码生成器中。有时遇到问题不知道如何解决,有时学到新的知识点,立刻就能在代码生成器中实践。这段经历非常奇妙,我甚至常常在走路时思考书中的内容,以至于多次错过路口。我在《我的读书生涯》中回顾了这段经历。
在这种边学习边实践的过程中,代码生成器逐渐发生了变化:功能不断扩展,代码量减少,但继承关系变得复杂。我甚至为业务对象设计了一个基类,后来发现这是一个误区。尽管如此,代码生成器逐渐演变成了一个框架------一个属于我自己的框架。代码生成器本身的代码量和生成的代码都显著减少,功能却更强大,可维护性也更强。
ORM框架的诞生
有时候,改变源于一句不经意的话。在与同事讨论时,有人提到"不应该将SQL语句放在逻辑代码中"。这句话触动了我,我开始在代码生成器中将SQL语句从代码中移除,这为后来形成ORM框架奠定了基础。
ORM框架的另一个技术来源是C#的开源项目DNN(Dot Net Nuke)。我从中学到了CBO(基于元数据的对象创建与赋值),这成为ORM框架的核心技术之一。例如,将一个DataTable中的Row转换为对象,或将对象转换为DataRow;还有Null类。此外,DNN中的策略模式也为我提供了灵感,使ORM框架能够支持多种数据库。
在2006年到2007年间,我实现了一个类似MyBatis的ORM框架,甚至一度觉得它比MyBatis更好用(惭愧中)。
XML读取与数据库访问
在ORM框架中,我将SQL语句和参数放到XML中,并设计了一个访问框架,实现了缓存和更新功能。为了支持多种数据库,我应用了设计模式,尽管当时对设计模式的理解还不够深入。后来我意识到,设计模式并不是刻意学习的,而是在实践中自然"长"出来的。我多次重构数据库访问程序,最终形成了一个稳定且高效的库。
技术追求的弯路:Attributes
在这段经历中,我也曾走过弯路。例如,我曾过度使用C#的Attributes,甚至将其放到业务对象类中。后来意识到这是错误的,便将其移除。这段经历让我明白,技术工具的使用需要适度,不能为了炫技而牺牲代码的可维护性。
前端控件的发展
在代码生成器的早期,我主要做Web开发,前端使用ASP.NET,后来转向Castle Monorail。为了减少Web页面和后台的代码生成量,我不断扩展Web控件,将能前端处理的功能尽量放到前端,并抽象出通用功能。前端控件的抽象经历了两个阶段:
-
第一阶段 :抽象出包含后台代码的Web控件,例如扩展DataGrid和TextBox控件。
-
第二阶段:使用纯前端控件,进一步提升灵活性和可维护性。
前端自动输入合法性验证框架
除了扩展控件,我还为前端输入合法性验证设计了一个框架。通过JavaScript遍历所有DOM控件,根据扩展属性(如是否为空、最大最小长度、是否整数等)进行合法性验证,并在控件下方弹出提示信息。这一设计大大减少了后端验证的负担。
使用模板技术
最初,代码生成器的所有代码都是通过字符串拼接生成的。随着框架的升级,生成的代码量减少,字符串拼接的工作量也大幅下降。后来,我意识到可以使用模板生成代码,于是设计了一个简单的模板引擎,用"#***#"格式替换变量。再后来,我引入了VTL等模板技术,进一步减少了代码生成器的代码量。
Excel操作
我为框架添加了Excel导入导出功能,根据数据库结构生成Excel文件,并支持数据合法性验证和格式设置。用户可以在Excel中编辑数据后,再导入系统,实现批量添加数据,同时严格遵循主外键关系,避免脏数据。这一功能在后来的视频监控配置中发挥了巨大作用,将原本需要数天的配置工作缩短到十几分钟。
框架与库
经过几年的开发,我发现框架不一定要以单一的形式存在,而是可以拆分为多个独立的库。每个库可以单独使用,组合起来又能形成一个完整的框架。基于这一思路,我将框架拆分为数据访问库、元数据映射库(CBO)、SQL缓存库、前端合法性检查库、前端控件库、Excel导入导出库和通用库等。
代码生成器的扩展
代码生成器最初是一个简单的Form页面,后来逐渐扩展为包含多个Panel的界面,支持数据库表树、代码生成区域、数据库表结构选择以及代码类型选项。生成的代码不仅支持ASP.NET,还支持Java、C++、Castle Monorail的页面代码以及多语言配置。
代码生成器与重构
重构的习惯是在编写代码生成器的过程中逐渐养成的。从最初的混乱代码到一个完整的框架,再到拆分为多个库,重构起到了关键作用。这段经历让我形成了几个重要的认知:
-
重构要小步快跑,步子太大会迷失方向。
-
代码越重构,越敢动它;否则,代码会逐渐僵化。
-
几次小的重构后,需要进行一次相对完整的验证,避免浪费时间。
-
重构的目标可以大一些,但要从小步开始,逐步实现。
-
重构的最终目标是让代码更清晰、更灵活。
后续
这个代码生成器我写了十几年,乐在其中,也学到了很多。我还用Python和Java实现了类似的工具,例如Python版的代码生成器(Mysql_CodeGen)和Java版的框架(HiJDB)。此外,我还开发了一个C#版的DataGridView辅助类(DataGridView辅助类)。
总结
通过编写代码生成器,我的技术能力得到了极大的提升,对重构、面向对象、设计模式、前端技术和后端技术都有了深入的理解。唯一的遗憾是,这段经历主要是单打独斗,如果能与更多人合作,可能会成长得更快,收获更多。在未来的工作中,我希望能再次找到类似的机会。就像我的代码生成器一样,从无到有,从框架到库,不断重构和突破,逐步完善自己。
其实,在开发方面,我也的确又遇到了类似的工作,例如:ACE,例如后来做的智慧校园平台。
就像我的代码生成器,从无框架到有框架到打破框架形成多个库,不破不立,期望在任何好的或坏的情形下,都有重构自己的勇气,正反正的螺旋上升,逐步完善。