代码污染_小事情会污染您的代码

代码污染

使用“仅测试”方法或访问修饰符污染代码 (Polluting code with 'test-only' methods or access modifiers)

First of all, if you give access to something that shouldn't be used in production code, it gets used sooner or later. Just because it exist. The argument that it's an internal stuff doesn't work as it absolutely shouldn't be matter, writing you a library or isolated project! Treat people who will add anything to your internal codebase the same way as if they use your existing code as a different library.

首先,如果您可以访问生产代码中不应该使用的内容,则迟早会使用它。 仅仅因为它存在。 认为它是内部内容的说法是行不通的,因为绝对不应该这样,为您编写库或隔离的项目! 对待将要向您的内部代码库添加任何内容的人员,就像他们将现有代码用作其他库一样。

Thus, if for some reason in test, you need to call something that should not be called on prod — use reflection or whatever else

因此,如果出于某种原因在测试中,您需要调用某些不应在产品上调用的内容,请使用反射或其他方法

但不要在生产代码中公开 (but do not expose it in production code)

! And there's no reason to afraid of reflection for test proposes, at the end, you using Mockito, shouldn't it be bad in that case as well?

! 而且没有理由担心测试建议会被反思,最后,您使用Mockito,在这种情况下也应该不错吗?

避免使用JavaDoc (Avoiding of JavaDoc)

I've heard quite a lot, a weird strange argument that «JavaDoc means that code is not self-documented». I wouldn't talk about that self-documented code in reality is myth — it's an absolutely separate topic. JavaDoc is about providing a contract with your code. And again, it doesn't matter, writing you a library or isolated project! Only on private methods, I can agree, that JavaDoc can be skipped. Who is writing one service in your project shouldn't go and read all implementations of other services or DAOs or whatever that he's using. He should be able to open an interface and read JavaDoc and that is it!

我听到了很多,一个奇怪的奇怪论点,即“ JavaDoc意味着代码不是自记录的”。 我不会谈论现实中的自我记录代码是神话-这是一个绝对独立的主题。 JavaDoc将与您的代码签订合同。 再说一次,没关系,写一个库或孤立的项目! 我可以同意,只有在私有方法上,才可以跳过JavaDoc。 谁在您的项目中编写一项服务,不应去阅读其他服务或DAO或他正在使用的任何内容的所有实现。 他应该能够打开一个界面并阅读JavaDoc,就是这样!

For example, if you're writing something that returning Map, and using LinkedHashMap to provide some specific order — you have to mention that in JavaDoc! Otherwise, who is using that service can't rely on the order as it wasn't part of the contract, and nothing will prevent you to silently change that behaviour later.

例如,如果您正在编写返回Map的内容,并使用LinkedHashMap提供一些特定的顺序-您必须在JavaDoc中提及! 否则,使用该服务的人将不能依赖订单,因为它不是合同的一部分,并且没有任何阻止您以后更改该行为的方法。

The other popular argument: «Tests are better description». Of course, BDD is a useful thing and it's a pretty nice way to check your code behaviour, but someone who will write one service in your codebase should investigate all tests of services (neither their implementation) that he will need to use before doing that! You have to provide a contract!

另一个流行的论点是:“测试是更好的描述”。 当然,BDD是有用的,它是检查代码行为的一种很好的方法,但是要在代码库中编写一个服务的人应该调查在使用该服务之前需要使用的所有服务测试(无论是其实现)。 ! 您必须提供合同!

没有接口用于服务的单一实现 (No interface for single implementation of a service)

The same reason as in a previous paragraph. To write new service we want just open interface and read about a contract of services that we'll use. We are not interesting in the implementation!

与上一段相同的原因。 要编写新服务,我们只需要开放接口并阅读我们将使用的服务合同。 我们对实现并不感兴趣!

单元测试中的过度测试 (Overtesting in unit-tests)

Test only things that you

仅测试您所要做的事情

(really)

should! There's absolutely no sense to make a unit test for controller that doing nothing more than simply delegate everything to a service.

应该! 对控制器进行单元测试绝对没有任何意义,只不过是简单地将所有内容委派给服务。

There's no sense to test your domain layer. I saw some examples when people test sterilisation of a POJO by Jackson, explaining that as they're testing that annotations is putted correctly… Come on! Tests are description of how your code logic should work and Jackson annotations is also description! Your just cannot test that, as if you write one description wrong, why you decided that by adding another one you will avoid mistake and not just copy it? Furthermore, for any change in your model, now you will have to change same description in two different places!

测试您的域层毫无意义。 当人们测试杰克逊对POJO的灭菌处理时,我看到了一些示例,它们解释说,当他们测试批注是否正确放置时,……加油! 测试是对代码逻辑应该如何工作的描述,而Jackson注释也是描述! 您只是无法测试,就像您写错了一个描述一样,为什么您决定通过添加另一个描述来避免错误,而不仅仅是复制呢? 此外,对于模型的任何更改,现在您都必须在两个不同的地方更改相同的描述!

This particular example was even more ridiculous as ObjectMapper was created in each test, so, has nothing with the real one in a Spring context. Thus, because of different configurations it may serialise differently in prod at the end…

由于在每个测试中都创建了ObjectMapper,所以这个特定示例更加荒谬,因此,在Spring上下文中,与真实示例无关。 因此,由于配置不同,最后它的序列化可能会有所不同……

If your description is correct, you can check

如果您的描述正确,则可以检查

只要 (only)

by integration tests. Unit tests for serialisation/deserialisation checking nothing other than serialisation/deserialisation works. And if it is a part of some framework and not part of your code — do not test it!

通过集成测试。 进行序列化/反序列化的单元测试仅检查序列化/反序列化的工作。 如果它是某些框架的一部分,而不是您的代码的一部分,请不要进行测试!

害怕框架的“魔力” (Afraid of framework's 'magic')

For example, Spring core brings lifecycle of beans to you and instruments to work with it and all services should be beans inside the context. If you want, for example, to do something with a DB before any of beans start using it, use ContextStartedEvent or BPP for for your DB connector bean but do not create separate object for the DB connector! Otherwise you will create second configuration that have to be maintained exactly the same way as the first one and this is the field for potential bugs. Don't reinvent the wheel if you already have a proper instrument!

例如,Spring核心为您带来了bean的生命周期以及可以使用它的工具,并且所有服务都应该是上下文中的bean。 例如,如果您想在任何bean开始使用它之前对DB做某事,请为您的DB连接器bean使用ContextStartedEvent或BPP,但不要为DB连接器创建单独的对象! 否则,您将创建必须与第一个配置完全相同的维护第二个配置,这是潜在错误的领域。 如果您已经拥有合适的乐器,请不要重新发明轮子!

丢弃原始异常 (Throw away original exceptions)

If you catch an exception, always log it or throw forward (but don't do both). If you want to use another exception, wrap the original one in it! Even in situations when exception happened due to invalid user input. For example, you catch some ParseException and want to throw IllegalArgumentException that will be handled later and the 400 code will be sent. Wrap ParseException and log everything in your handler before sending the response! When something goes wrong (for instance, there's a bug and expected input gets 400) you will be extremely glad to see full stacktrace in you logs and not just IllegalArgumentException that can't tell exactly which part of the request failed.

如果捕获到异常,请始终记录该异常或将其抛出(但不要同时执行)。 如果要使用其他异常,请在其中包装原始异常! 即使在由于无效用户输入而发生异常的情况下。 例如,您捕获了一些ParseException并想抛出IllegalArgumentException,稍后将对其进行处理并发送400个代码。 在发送响应之前,包装ParseException并将所有内容记录在处理程序中! 当出现问题时(例如,存在一个错误,预期输入为400),您将非常高兴地看到日志中有完整的堆栈跟踪信息,而不仅仅是IllegalArgumentException,它无法确切说明请求的哪部分失败。

业务逻辑基于异常 (Businesses logic is built on exceptions)

Exception — for something that goes

例外—发生的事情

与预期不同 (not as was expected)

! Something happened — you throw, but if you want to do some additional operations (like call to some services or DB) to figure out the state — it should not be exception any more: create a proper class that you will call Report or whatever and return it to the user, but do not provide information by throwing exception to the top in that case!

! 发生了一些事情(您抛出了,但是如果您想执行一些其他操作(例如,对某些服务或数据库的调用)以弄清状态),那就不再是例外:创建一个适当的类,您将调用Report或任何其他方式,将其返回给用户,但在这种情况下不要通过抛出异常来提供信息!

在各处使用流 (Using streams everywhere)

Functional approach is not a silver bullet. Sometimes it just making code more complicated and less readable. If you want just to convert List to Set, without any additional operation in between, there's absolutely no reason to do it through .collect(toSet()). When you have List with some items that should be converted to Map<K, List>, or something even more tricky, that require some merge — just do it through .forEach, it'll be much nicer than toMap with two mappers and merge function.

功能方法不是万灵丹。 有时,这只会使代码更复杂且可读性更差。 如果您只想将List转换为Set,而无需在其间进行任何其他操作,则完全没有理由通过.collect(toSet())进行操作。 当您拥有包含某些项目的List时,应该将其转换为Map <K,List>或更棘手的事情,需要进行一些合并-只需通过.forEach进行操作,它将比使用两个映射器进行合并的toMap好得多功能。

I thought that for most of developers that things are obvious. Unfortunately, I've found out that it isn't a case… Hope that this small article will push to rethink approach…

我认为对于大多数开发人员来说,事情是显而易见的。 不幸的是,我发现情况并非如此……希望这篇小文章能推动人们重新思考方法……

翻译自: https://habr.com/en/post/512108/

代码污染

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值