java - 怎么样才能写出比较理想的业务代码

 素人1963_497 发布于 2022-11-07 05:11

平时写一些代码的时候不像写一些框架涉及到具体的业务比较少,或者也不能说比较少,只是涉及到的业务感比较轻,现在一般的公司的代码都是具有很强的业务感觉。
而且一般写这些的时候还用框架,比如说比较流行的SSI或者是SSH。然后分模块开发。
当我们用这些框架开发的时候往往是一个Service提供接口给本模块或者其它模块使用。这个时候一个Service往往会包含很多各式各样的接口。这个时候往往会发生以下问题:

  • 一个Service往往是对其它Service的接口的一个组装,这里就会出现很强的过程似代码的感觉
  • 当我们用Spring来注入的时候,往往一个Service的方法里面都出出现1到2个一样的参数,当我们想把它提到类变量的时候,发现已经被框架限制了
  • 因为Service是对外提供方法服务的,所以处理异常就会放在Service,这个时候没有接口都需要附带2个信息:

    • 接口是否成功,如果失败了,那么失败的信息是什么
    • 接口提供的信息,查询接口返回一个实体

    这样子可能会出现以下几个问题:

    • 有些信息在其它模块中,是由很底层的服务提供的。这个时候这个信息需要一层一层往上 传。这就会导致这一层一层的Service在调用底下一层的时候,需要判断对底下一层的调用是否有错误信息,如果有错误信息就中断主流程,并且把错误信息继续往上传。很多true/false的判断会在一个Service方法中出现很多次。
    • 因为是分模块的,所以我们的假设是对其它模块一无所知。所以这个时候Log的记录就会变得很蛋疼。当我调用其它接口是返回给我的是false。这个信息对我很重要,所以我需要打INFO日志记录下这个信息。但是往往很凑巧的是,这哥信息在被调用方也打了一遍,这就会出现一个工程里面出现很多相同的Log。
  • 一些service中往往涉及的方法很多,基本上是一个Service往往有很多职责。

写了很长一段时间业务代码以后。给我的感觉是,程序员并不是在写代码,而是在搞业务,基本上不会涉及到抽象或者抽象成分很小很小。
怎么才能写出比较理想的业务代码,还是业务代码只能这么过程式的去写?

3 个回答
  • 文中你说的两个问题应该是c++才容易遇到的,java一般不用状态码,而是使用异常

    2022-11-12 01:38 回答
  • 首先任何功能的执行,说到底还是一个过程,先做什么再做什么,第一步第二步,这是肯定的,理清这个过程是实现的第一步。然后,面向对象的设计要求我们把过程中的每一步委托给合适的类来做,读文件让谁来做,排序让谁来做,解析xml让谁来做。这样职责委派的结果,就是程序内出现了模块分层,被依赖得多的模块,通常被视为底层。

    当对象在模块之间进行传递时,是否每个模块都要判断其合法性?commons-lang的StringUtils是个例子,它用来处理字符串,而它的所有方法都能很好的处理null参数值,所以它发出了一个很明确的信号:不要在调用我的方法前检查参数是否为null,只管传给我好了!至于你自己写的方法,对参数有什么要求,最好在文档里说明,这样调用者也省心。

    日志记录,每个模块都是在自己的角度上去理解要不要记,所以如果你觉得某个地方重复了的话,通过调整配置屏蔽掉多余的就好。

    2022-11-12 01:38 回答
  • 我没有什么Java经验,看到标签里有PHP,来按照PHP的路子回答一下,可能Java有自己的风格,但我觉得本质应该通的
    我觉得理想的业务代码的判断依据应该是清晰易懂、易维护,不会因为环境的变更需求的叠加而迅速坏死,这和过程式还是OO,抽象还是不抽象并没有直接关系


    那么什么是最容易维护的代码呢?

    我认为是英文。就是需求文档本身,假设需求文档本身就能跑起来,那可维护性一定是最高的

    那需求文档和我们日常写的代码之间的区别在哪里呢?我认为主要的却别就是我们的代码除了需求(业务)以外,还描述了实现方式,除了what to do,还有how to do

    好比需求文档可能是这样的

    在表单中输入名字、价格和描述,点击提交按钮生产一个产品,名字不能为空,价格是小数,描述可以为空

    代码可能是这样的

    conn = sql_connect('xxx.xxx.xxx.xxx');
    inputButton.on('click', ->
      assert name is nonempty string, price is float, price > 0, ....
      conn.query('INSERT INTO product VALUES (.....)');
    )
    

    看,需求在代码里被实现淹没了,我们按钮是点击的,数据库是sql的,表结构是sql语句里写死的……只有当那么多前提条件恰好工作,这段代码才能正确地反映需求

    那么我觉得理想的代码应该就是需求文档的英文版,可能恰好符合某种语法规范,但里面绝对没有任何实现的细节。

    比如

    form = new Form();
    form
      .addField 'name', Form.String, [Assertion.NONEMPTY]
      .addField 'price', Form.Float, [Assertion.POSITIVE]
      .addField 'desc', Form.String, [Assertion.maxLength(65535)]
      .onSubmit ->
        Product.createProduct(form)
    

    然后我可能会以这样的业务代码为目标开始设计整体结构,Form类和Assertion类合作提供表单构建、验证能力,Product里封装关于存储的细节等等。

    哦,这个思路有个很帅气的名字叫DSL,在任何高级语言的基础上,通过合适的设计其实设计这样的DSL都不难,可能最初的代码量工作量会稍大,但稍后你会发现,只要产品需求文档还是人话,你要做的事情就是简单的翻译。加业务就只会改业务代码,环境变化或者性能优化或者新的DSL语法就只会改实现代码。这件事看上去很像是抽象,但和软工传统的抽象有所区别:抽象的目的是复用代码,而分离DSL的目的是分离业务和实现,前者可能希望代码少一点,认为代码复用就能提高可维护性,后者则不在乎代码量,认为业务和实现分离才能提高可维护性(虽然这种分离基本上意味着实现的部分可以复用)

    这个回答的思路源于我以前的这篇文章 http://press.mcfog.wang/2013/06/dsl-style-javascript/
    对应的问题是大表单的JS逻辑代码混乱,可以参考一下

    写完一看发现似乎和PHP也没啥关系,其实我就是不懂Java SSH的service那一套,可能没啥针对性

    2022-11-12 01:38 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有