太过关注底层
症状包括经常重写一些常见的代码,很多开发人员都有这种症状。
下次面对特定问题时,首先进行快速搜索,确定解决该问题的库是否已被集成到 Spring 中;
现在,你可能找到一个合适的现成解决方案。
Lombok 被用作样板代码生成器,希望懒惰的开发人员在熟悉这个库时不会遇到问题。
举个例子,看看使用 Lombok 的 “标准 Java Bean” 是什么样子的:
内部结构 “泄露”
“泄露” 的内部机制表现为使数据库结构可以从某些 API 端点访问。
例如,下面的 POJO(“Plain Old Java Object”)类表示数据库中的一个表:
返回 TopTalentEntity 实例可能很诱人,但更灵活的解决方案是创建一个新的类来表示 API 端点上的 TopTalentEntity 数据。
缺乏关注点分离
讽刺的是,大多数好的软件工程原则开始在规模上崩溃 —— 特别是在没有太多考虑程序体系结构设计的情况下。
开发人员最常犯的一个错误就是混淆代码关注点,这很容易做到!
当然,这是一个很好的短期解决方案(对于初学者来说,它需要更少的输入),但它也不可避免地会在将来成为一个问题,无论是在测试期间、维护期间还是介于两者之间。
考虑下下面的控制器,它将从数据库返回 TopTalentData。
它提供了一个从 TopTalentEntity 实例检索出来的TopTalentData 的 List。
也就是说,它将请求映射到特定端点,从数据库检索数据,并将从 TopTalentRepository 接收的实体转换为另一种格式。
一个“更干净” 的解决方案是将这些关注点分离到他们自己的类中。
看起来可能是这个样子的:
缺乏异常处理或处理不当
虽然编码风格可能存在争议(通常团队或整个公司内部已达成一致),但拥有一个共同的标准最终会极大地提高生产力。
对多人团队尤为如此;
一致性允许交流发生,而不需要花费很多资源在手把手交接上,也不需要就不同类的职责提供冗长的解释。
在命名时保持语义上的一致性,可以创建一个易于搜索的结构,任何新的开发人员都可以按照自己的方式管理代码;
例如,将 Config 后缀添加到配置类,服务层以 Service 结尾,以及控制器用 Controller 结尾。
如果你曾经不得不处理编写很差的 API 的异常响应,那你可能知道原因 —— 正确解析异常会是一件痛苦的事情,而确定这些异常最初发生的原因则更为痛苦。
这通常意味着有一个通用的错误代码和描述,而不是逃避解决问题:
a) 返回一个 “500 Internal Server Error”信息。
b) 直接返回异常的堆栈信息给用户。
(实际上,这些都应该不惜一切代价地去避免,因为除了客户端难以处理以外,它还暴露了你的内部信息)。
将异常转换为这种格式可以通过向方法提供 @ExceptionHandler 注解来完成(注解案例可见于第六章)。
多线程处理不当
由并行执行程序所引起的问题是令人毛骨悚然且难以捉摸的,而且常常难以调试 —— 实际上,由于问题的本质,一旦你意识到你正在处理一个并行执行问题,你可能就不得不完全放弃调试器了,并 “手动” 检查代码,直到找到根本上的错误原因。
根据具体场景来评估情况,然后从你认为最好的角度来解决问题。
同样,不存在那种一刀切的方法,但这有一些调试和防止多线程错误的实际考虑因素:
如果你正创建一个多线程应用,那么应该密切关注任何可能全局修改的内容,如果可能的话,将他们全部删掉。
如果某个全局变量有必须保持可修改的原因,请仔细使用 synchronization,并对程序性能进行跟踪,以确定没有因为新引入的等待时间而导致系统性能降低。
简而言之,这意味着放弃 setter 方法,并在所有模型类上拥有私有的 final 字段。
它们的值唯一发生变化的时间是在构造期间。
这样,你可以确定不会出现争用问题,且访问对象属性将始终提供正确的值。
如果发生错误,你将很高兴可以得到信息说明收到了哪些请求,并可更好地了解你的应用程序为什么会出现错误。
需要再次注意的是,日志记录引入了额外的文件 I/O,可能会严重影响应用的性能,因此请不要滥用日志。
向不同的服务发出异步请求),复用现有的安全实现来代替创建自己的解决方案。
这在很大程度上意味着要使用 ExecutorServices 和 Java 8 简洁的函数式 CompletableFutures 来创建线程。
Spring 还允许通过 DeferredResult 类来进行异步请求处理。
不使用基于注解的验证
此外,假设基于某些原因,每个新名词都需要为 10 个字符长度。
执行此操作的一种方法可能如下:
让我们首先重构 addTopTalent 方法来支持验证:
虽然你通常只在需要超出 Hibernate的内置约束集 时才使用自定义注解,本例中,我们假设 @Length 不存在。
你可以创建两个额外的类来验证字符串长度,一个用于验证,一个用于对属性进行注解:
(依旧)使用基于xml的配置
XML 配置只是作为附加的不必要的样板代码。
在我们的案例中,这意味着这个顶级包 (co.kukurin)将用于检索:
忽略 profile
在每次从测试切换到部署应用程序时,不要手动替换各种配置项,更有效的方法是使用 profile。
推荐阅读:
Spring Boot Profile不同环境配置。
关注Java技术栈微信公众号,在后台回复关键字:
boot,可以获取一份栈长整理的 Spring Boot 最新技术干货。
你正在使用内存数据库进行本地开发,而在生产环境中使用 MySQL 数据库。
本质上,这意味着你需要使用不同的 URL 和 (希望如此) 不同的凭证来访问这两者。
让我们看看可以如何做到这两个不同的配置文件:
另外,还可将操作系统的环境变量设置为所需的默认 profile。
无法接受依赖项注入
这对于解耦关系非常有用,也使测试变得更为容易,而不是通过类之间的紧耦合来做这样的事情:
在关注点分离(常见错误 #3)一节中,我们创建了一个服务和控制器类。
我们可以通过提供一个单独的配置类来插入一个模拟对象来代替实际的服务实现:
缺乏测试,或测试不当
这显然是不可取的,因为测试不仅应该验证代码的正确性,还应该作为程序在不同场景下应如何表现的文档。
考虑以下带有依赖项注入的代码片段:
RestAssuredMockMvc 只是用来设置一个轻量级环境,并向 /toptal/get 端点发送一个 GET请求。
喜欢就点个"在看"呗^_^
本文分享自微信公众号 - 江南一点雨(a_javaboy)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
相关文章
暂无评论...