方法绑定无效_是无效的方法不好

方法绑定无效

编码最佳实践 (CODING BEST-PRACTICES)

(Meta)

A deep-dive into the nature of void methods and the associated side-effects. Why you should broadly avoid them. And the cases when you shouldn’t.

深入研究空方法的性质及其相关的副作用。 为什么要广泛避免使用它们。 还有您不应该使用的情况。

While I have tried to make plain the subject of this post with the title, in the above paragraph, I have again added a small description of the post. This serves two purposes.

虽然我试图用标题来使帖子的主题简单明了,但在上一段中,我再次添加了对该帖子的简短描述。 这有两个目的。

  1. SEO 😅

    SEO😅
  2. Countless times in the past, I have clicked on a link, read a few paragraphs only to realise that it wasn’t what I was looking for. So being a good samaritan, I wanted to give a fast exit point, in case you came here expecting something else.

    过去无数次,我单击了一个链接,阅读了几段,只是意识到这不是我想要的。 因此,作为一名优秀的撒玛利亚人,我想提供一个快速的出口点,以防万一您来这里还有其他期望。

Tldr; 有时间? 阅读全文。 其他搜索“ Key Takeaway” (Tldr; Have time? Read full post. Else search “Key Takeaway”)

Again going by my own reading patterns, sometimes I want to read and take away something from a post, but don’t have the time, or sometimes, I broadly understand and agree with the subject, and so don’t want to wade through all the text, only to see if there is any new information or point of view that I can glean from it. As a result throughout the post, I have marked: Key Takeaway. I would encourage you to read the whole post, but if you prefer, fire up the trusted Ctrl/Cmd+F. :)

再次按照自己的阅读方式,有时我想阅读和删除帖子中的某些内容,但没有时间,或者有时,我广泛地理解并同意该主题,所以不想浪费时间所有文字,只是看看是否有任何新信息或我可以从中收集的观点。 因此,在整个帖子中,我都标记了: Key Takeaway 我鼓励您阅读全文,但如果愿意,请启动受信任的Ctrl / Cmd + F。 :)

Methods, functions (or whatever you want to call them) that return nothing, i.e. have a return type of void, are a staple of programming. In fact, it is the first return type all Java developers see.

不返回任何内容(即返回类型为void)的方法,函数(或任何您想调用的函数)是编程的主要内容。 实际上,它是所有Java开发人员看到的第一个返回类型

And if you are not a Java developer, then,

如果您不是Java开发人员,那么,

You sir/madam, are a scoundrel without valour, without valour, I say! 😛

先生/女士,我是无勇无惧的流氓,我说! 😛

— John Oliver

—约翰·奥利弗(John Oliver)

But keeping the jests out of service, irrespective of the programming language(s) of your choice, you have doubtless come across the concept of void methods. For in our binary world, void methods are ubiquitous. These methods are so common, and we are so familiar with them that we seldom pause to think, how weird and dare I say, how sinister they are.

但是,不管选择哪种编程语言,都不要开玩笑,毫无疑问,您会遇到void方法的概念。 因为在我们的二进制世界中,空方法是无处不在的。 这些方法是如此普遍,而且我们对它们非常熟悉,以至于我们很少停下来思考,我说的多么奇怪和敢,它们多么险恶

Because think about it, a void method does not provide any output. So why will anyone write a method, and then call it only for nothing to be returned? For Ex,

因为考虑一下,所以void方法不会提供任何输出。 那么,为什么有人会写一个方法,然后只调用它却什么也不返回呢? 对于Ex,

No one in their right mind would create a method like this. We can’t use this method, to build anything of value. We can call this method a million times, with different values but it wouldn’t matter. [ Key Takeaway 1 ]

在他们的右脑中没有人会创造这样的方法。 我们不能使用这种方法来建立任何有价值的东西。 我们可以将此方法称为百万次,使用不同的值,但这无关紧要。 [要点1]

On their own, Void methods are dead code. It’s like a virus. On its own it cannot “live” in the world of programming. And just like a virus requires a host to be truly alive. Void methods, require side-effects[1][2] to actually survive.

Void方法本身就是无效代码。 就像病毒一样。 靠它自己不能“生活”在编程世界中。 就像病毒需要宿主真正存活一样。 无效方法需要副作用[1] [2]才能真正存活。

Let us now modify the above code, to introduce some side-effect.

现在让我们修改上面的代码,以引入一些副作用。

Now let us look at this code. Every time add() is called, then as a side-effect the state of the Adder class is changed, and the instance variable cumulativeValue is incremented by value

现在让我们看一下这段代码。 每次调用add() ,作为副作用,Adder类的状态都会更改,并且实例变量cumulativeValue会按value递增

So now we can use this for some purpose. In this case, I used it to find the sum of all numbers from 0 to 9. Hence to reiterate.

所以现在我们可以将其用于某些目的。 在这种情况下,我用它来查找从0到9的所有数字的总和。因此重申一下。

Void methods are essentially methods that lives on side-effects. If a method gave no output and produced no side-effects, no one would write it, and no one would call it.

无效方法本质上是依赖副作用的方法。 如果一种方法没有输出并且没有产生副作用,则没有人会编写它,也没有人会调用它。

“Hmm”, now may say. “If there are no side effects, void methods don’t make sense. Cool. I’ll just introduce side-effects and use them” — Fair point. There will be nothing in the standard programming languages[3] that will stop you from doing so. The compiler will pass it without question. But your code reviewer should stop you. And if the reviewer is me. Then I Will!

现在可以说“嗯”。 “如果没有副作用,那么无效方法就没有意义。 凉。 我将介绍副作用并加以利用” –公平点。 标准编程语言[3]不会阻止您这样做。 编译器将毫无疑问地传递它。 但是您的代码审阅者应该阻止您。 如果审稿人是我​​。 接着我会!

You see, When you write a void method, you essentially declare to the world that, This method works through side-effects. And, Side-effects in code or Stateful Programming, is a code smell. It makes your code hard to read, and even harder to debug and expand upon.

您会看到,在编写void方法时,实际上是向世界宣告,该方法通过副作用起作用。 而且, 代码或有状态编程中的副作用是代码的味道。 它使您的代码难以阅读,甚至难以调试和扩展。

So by Extension, that begs the question,

因此,通过扩展,这就引出了一个问题,

Are void methods bad and should we never use them?

空方法不好吗,我们不应该使用它们吗?

Well, Yes and No. Generally yes. If you can write a method, that can work without side-effects, then you should definitely, do so. And in most standard programming you will be able to avoid voids entirely (see what i did there, eh.. eh.. no-one? alright). But, and this is important, some things are by their nature stateful, and when that is the case, not only will I deem void methods acceptable but also will recommend them.

是的是和否。通常是。 如果您可以编写一种无副作用的方法,那么您绝对应该这样做。 并且在大多数标准编程中,您将能够完全避免空隙 (请参阅我在那做的事情,嗯……没有一个人吗?)。 但是,这很重要,有些事情从本质上讲是有状态的,在这种情况下,我不仅会认为无效方法是可以接受的,而且会推荐它们。

Now, I understand, the above answer seems a little confusing and to some extent self-contradictory. So, let us observe some void methods in action, and understand what makes good or bad.

现在,我知道,以上答案似乎有点令人困惑,并且在某种程度上是自相矛盾的。 因此,让我们观察一些无效的方法,并了解什么是好是坏。

无效的无效方法 (Bad Void Methods)

In general, a bad void is one where the underlying operation need not be state-full, or introduce side-effects. Why? To understand that, let us expand our Adder class a bit.

通常,不良无效是指基础操作不需要处于全状态或产生副作用的情况。 为什么? 为了理解这一点,让我们稍微扩展一下Adder类。

Now we have added a simple and logical extension to our Adder class. reset(). This method essentially resets cumulativeValue to 0, so that we can use Adder again.

现在,我们在Adder类中添加了一个简单且逻辑上的扩展。 reset() 。 此方法本质上会将cumulativeValue值重置为0,以便我们可以再次使用加法器。

逻辑未封装 (Logic is not encapsulated)

Yet, even in this simple example, we start to see the problem. Failing to call the reset() before a subsequent add() means a wrong addition.

但是,即使在这个简单的示例中,我们也开始看到问题所在。 未能在随后的add()之前调用reset() add()意味着add()错误。

Now in this example, the mistake is simple to avoid. But that is because here we have a significant advantage. We have full knowledge of the inner workings of code, and we are the sole author. How often do we have this advantage in real life? Hardly ever. Just think back,

现在在此示例中,很容易避免该错误。 但这是因为我们在这里拥有显着的优势。 我们对代码的内部运作有充分的了解,并且是唯一的作者。 我们在现实生活中多久拥有一次这种优势? 几乎没有。 回想一下,

Have you closed every resource you have ever opened? More importantly, did you always know whether the resource needed to be closed?

您是否关闭了曾经打开过的所有资源? 更重要的是,您是否始终知道是否需要关闭资源?

The point I am trying to make is, introducing state, often leads to a situation where the client must use your code responsibly, else it can lead to issues. And while I am all for trusting your fellow developer, I myself subscribe to the philosophy that, [ Key Takeaway 2],

我试图提出的观点是,引入状态,通常会导致客户必须负责任地使用您的代码,否则可能会导致问题。 尽管我全都信任您的开发人员,但我本人也秉承[Key Takeaway 2]的理念,

The lesser someone needs to know and understand my code, in order to use it as intended, the better. You have deadlines approaching, you made an otherwise reasonable assumption that just didn’t happen to pan out in this case. We are all Human, mistakes happen. The lesser chance I give you to make that mistake when interacting with my code, the better it is for the product, the customer, and the codebase.

有人需要了解和理解我的代码的次数越少,以便按预期使用它就越好。 您的截止日期临近,您做出了其他合理的假设,即在这种情况下并没有成功。 我们都是人类,会发生错误。 与代码交互时,我给您犯该错误的机会越少,对产品,客户和代码库的影响就越大。

即使代码错误也没有封装。 (Even Code Bugs are not encapsulated.)

In this particular example, say a bug was introduced, and now our reset method looks like this.

在这个特定示例中,假设引入了一个错误,现在我们的重置方法如下所示。

Now, none of the add() methods will work as expected. You see the problem? [ Key Takeaway 3]

现在,所有add()方法都无法按预期工作。 你看到问题了吗? [要点3]

A slight misuse of void methods, and introduction of a small amount of state-fullness, means that, even code bugs become non-encapsulated. Bugs in one method, can affect the functioning of another. More than anything else, this is scary.

略微使用void方法,以及引入少量状态填充,这意味着甚至代码错误也变得未被封装。 一种方法中的错误会影响另一种方法的功能。 最重要的是,这很可怕。

In our 30 lines of code, this otherwise external dependency is easy to find. But, what if this line was tucked away somewhere deep in the codebase? Furthermore, what if this bug is live in public? And while you are fumbling around from one spaghetti thread to another trying to find and fix this, your customers are seeing wrong price info on all their orders.

在我们的30行代码中,很容易找到这种外部依赖。 但是, 如果将此行隐藏在代码库的某个深处怎么办? 此外, 如果此错误在公共场所发布怎么办? 当您从一个意大利面条线程到另一个试图寻找并解决此问题的线程时,您的客户在所有订单上都看到了错误的价格信息。

I wouldn’t blame the author or the reviewer for missing this bug really. The code might have been legitimate for the feature that was added, but it caused an unintended consequence in some other part of the code, which was not even part of the commit.

我不会责怪作者或审稿人确实错过了此错误。 该代码对于所添加的功能可能是合法的,但在代码的其他部分(甚至不是提交的一部分)中导致了意外的结果。

Hence, [ Key Takeaway 4]

因此, [重点总结4]

A method’s influence should be kept as local as possible. A good way to do this is to not change the state of the class/global variables or that of the parameters passed. Doing this means, that unless you then return an output, your code is meaningless, and hence, avoid Void.

方法的影响应尽可能保持局部。 这样做的一个好方法是不更改类/全局变量的状态或传递的参数的状态。 这样做意味着,除非您随后返回输出,否则您的代码是没有意义的,因此请避免使用Void。

好的空洞方法 (Good Void Methods)

Let’s evaluate a few scenarios.

让我们评估一些方案。

  • Writing data for persistent storage in a file / database etc.

    将数据持久存储在文件/数据库等中
  • Rendering UI, using otherwise clean design patterns and frameworks such as MVVM, React-Redux etc.

    使用其他干净的设计模式和框架(例如MVVM,React-Redux等)渲染UI。
  • Invoking other methods with side-effects. ( You shouldn’t, but its not practical to put a blanket ban on this)

    调用具有副作用的其他方法。 (您不应该这样做,但全面禁止这样做是不现实的)
  • etc.

    等等

All of these scenarios have one thing in common, the underlying operation or intent of the method is to commit a stateful behaviour. Here we absolutely must change state. It still carries risk. An external change, such as a corruption to the database will lead to our operations failing. And we should put in reasonable validations, idempotency checks and all the works to mitigate that risk, but we cannot eliminate statefulness, and still build our product.

所有这些场景都有一个共同点, 该方法的基本操作或意图是提交有状态行为。 在这里,我们绝对必须改变状态。 它仍然带有风险。 外部更改(例如数据库损坏)将导致我们的操作失败。 而且,我们应该进行合理的验证,幂等性检查以及所有可减轻这种风险的方法,但是我们不能消除有状态性,而仍然要构建我们的产品。

And in this scenario, when you must have side-effects, not only can you use void. You should use void. For then it highlights the fact the the method in question has side-effects, and it was designed to have side-effects. This does two things,

在这种情况下,当您必须具有副作用时, 不仅可以使用void。 您应该使用void。 然后,它突出了一个事实,即所讨论的方法具有副作用,并且它被设计为具有副作用。 这有两件事,

  • First, it tells the reader that all non-void methods don’t change state, so one can be sure that calling this method wont have any un-intended side-effects. This is a great ability to have, as it essentially lowers the amount of knowledge I need to have to use, expand and debug the code.

    首先,它告诉读者所有非void方法都不会改变状态,因此可以确保调用此方法不会有任何意想不到的副作用。 这是一种很好的能力,因为它实质上减少了我需要使用,扩展和调试代码的知识量。

  • Second, it me exactly which methods will change state. If I want to use that method, I’ll be careful. This is important. If we don’t follow this, and all methods can potentially have unintended side-effects, then I will need to be careful when using any method. And the way the human mind works, If we always need to be careful, we will never be careful. By reducing the pool of side-effects, we can effectively communicate to the reader, client and reviewer, where caution is due and attention is warranted. It is like putting in Key Takeaway markers in an article :)

    其次,它准确地确定了哪些方法将改变状态。 如果要使用该方法,请务必小心。 这个很重要。 如果我们不这样做,那么所有方法都可能会产生意想不到的副作用,那么在使用任何方法时都需要小心。 以及人类思维的运作方式,如果我们始终需要谨慎,我们将永远不会谨慎。 通过减少副作用的产生,我们可以有效地与读者,客户和审阅者进行沟通,在这种情况下应谨慎行事,并应引起注意。 就像在文章中加入Key Takeaway标记一样:)

Hence, [ Key Takeaway 5]

因此, [要点5]

If the underlying intent of the method is to commit a stateful behaviour, like writing to a DB, you should use Void methods. It segregates the pure functional methods from those with side-effects, telling us where we need to pay attention and exercise caution, and where we can assume that no intended side-effects will occur on invocation.

如果该方法的基本意图是提交有状态行为(如写入数据库),则应使用Void方法。 它将纯函数方法与具有副作用的方法分开,告诉我们需要注意和谨慎的地方,以及可以假定调用时不会发生预期副作用的地方。

I am leaving out a few points, the most important of which is the performance implications of writing non-stateful methods. In many cases, stateful methods are more performant. Case in point Collections.sort()[4]. By sorting the list in-situ, it doubtless saves memory, and possibly takes lesser time to do so.

我没有提到几点,其中最重要的是编写无状态方法对性能的影响。 在许多情况下,有状态方法的性能更高。 以Collections.sort() [4]为例。 通过对列表进行原位排序,无疑可以节省内存,并且可能会花费更少的时间。

Here I will argue that in most situations I’ll not think twice in taking that performance hit. I have gone into it in much detail in a post, I wrote a while back. So check that out, or if you prefer to discuss directly on this or any other thing, then just drop me a note! :)

在这里,我将争辩说,在大多数情况下,我不会三思而后行 。 我在一篇文章中对此进行了详细的介绍,我写了一段时间。 因此,请检查一下,或者如果您希望直接讨论此问题或其他任何事情,请给我留言! :)

资料来源,脚注和更多阅读链接 (Sources, Footnotes & Further Reading Links)

翻译自: https://towardsdatascience.com/are-void-methods-bad-6d67dedc6600

方法绑定无效

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值