Java高级特性:循序渐进地培养面向对象的思维方式

困惑于两个问题:一是怎样培养面向对象设计的思维能力?二是怎样进行架构设计 , 有无方法?
因为我做了那么多年项目 , 却很少看到有漂亮的面向对象思维写出来的代码 , 觉得有必要提醒下年轻从业者 。 如今总结一下自己的经历 , 希望对刚刚入行的朋友有所启发吧 。
我的基本观念是 , 面向对象的思维方式是可以循序渐进地培养出来的 。 通俗地讲 , 就是不断地编码实践 , 量变会引起质变 。
1 开发人员的思考动力不足
记得参加工作后做的第一个项目是某电信局的运营支撑系统开发 , 采用的开发框架是Struts1+EJB+Hibernate的组合 , WebLogic8作应用服务器 。
弹指间 , 十年时光飞逝 , 慢慢适应了中年大叔的生活 。
有趣的是 , 经典的组合搭配至今没有过时(千万不要那么快过时啊 , 靠它混饭吃啊) , 特别是在企业应用中 , 例如大家常说SSH组合:Struts/SpringMVC + Spring/EJB + Hibernate/Mybatis/JPA等 。
开源框架的出现 , 使得只要在其基础上进行二次开发就可以大大降低开发工作量 。 只要高级工程师搭建好了项目的开发工程 , 初级开发人员就可以依照模版代码 , 依葫芦画瓢 , 流水线作业进行业务功能开发 。
从项目组整体的生产效率角度看 , 这确实是很大的进步 。 各个成员不同分工 , 各自做好自己的一部分工作即可 , 也符合现代企业管理的理念 。 但从个体的角度看 , 也客观造成了一些弊端 , 对初级开发人员 , 他就是流水线长的一个螺丝工 , 没有机会去思考如何进行面向对象的设计 。
这里我以一个常用的用户登录模块举例 , 系统采用经典的三层架构进行分层 , 类图如下:
Java高级特性:循序渐进地培养面向对象的思维方式文章插图
【Java高级特性:循序渐进地培养面向对象的思维方式】简单解释下业务场景:
1) 用户用浏览器访问系统登录页面 , 输入用户名与密码 , 提交表单 。
2) 系统对用户的用户名和密码进行验证 , 并对用户的访问进行日志记录以便以后作审计 。 其中数据库中存储的用户密码信息是加密后的字符串 。
作为一个初级开发人员 , 开发业务功能常常只需要复制粘贴图中的6个类即可 。 有时甚至连PasswordEncoder类都省去 。 还有些项目组有开发自己的代码生成工具 , 甚至连复制粘贴工作都省去 , 只需要对工具生成的代码作少量修改即完成了开发 。
回到类图 , 这里的LoginService和UserDao接口是否有必要定义?复制粘贴以及代码生成工具使得工作量成本很低 , 初级开发人员就没有动力去思考这个问题的 , 依葫芦画瓢完成功能 , 打完收工即可 。
我个人的观念是有没有必要取决于具体的项目需求与人员分工 。
1) 如果该业务模块由1个开发人员完成 , 系统不需要支持多数据库 , 也就是UserDao没有多个实现类的需求 , 则UserDao接口可以移除掉 。 同时如果系统只有通过数据库查询认证的可能 , LoginService也没有多个实现类的需求 , 则也可以移除掉 。
2) 如果项目组中该模块每一层都由不同的人员分工合作 , 则由于层次间依赖的需要 , 引入接口使得上一层可以更早地开始开发 , 也使得上一层的单元测试变得简单 。 在这种情况下 , LoginService和UserDao接口有存在的合理性 。
3) 在项目中 , 某些模块因为业务需要Service层和Dao层必须要有多种实现类 。 从代码风格一致性角度考虑 , 存在一个类对应一个接口的情况也是可以容忍的 。 这样是为了维护代码的可读性 , 也客观上预留了系统的可扩展性 。
一般来说 , LoginService和UserDao接口存在有其合理性 。
这些开发框架对通用功能进行了大量的封装 , 其本身源码中包含了大量OOD的思想 。 提供给开发人员进行二次开发时 , 单表单的增删改查由于业务需求简单 , 就体现不出OOD的价值了 。 这在一定程度上 , 使得开发人员去思考OOD的动力不足 。
比如MVC架构中对于控制器与视图的分离 , 业务模型类与Servlet API的转换这些恰恰是复杂的需要OOD抽象能力的 , 框架已经给你实现了 。 框架做的多一点 , 所以开发人员就轻松一点 。 再比如Spring中对于Java bean的创建与管理 , 依赖关系的注入 , 基于拦截器和动态代理机制来实现的声明式事物以及日志处理 , 还有与其它框架的集成支持等复杂点 , 它都给你实现了 。 还有Hibernate中实体对象与关系型数据库中表的对应转换 , 对API调用翻译转换成SQL语句 , 对多种数据库语法的支持 , 查询结果的缓存等 , 也是复杂点 。