<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>且听书吟</title>
        <link>https://yufan.me</link>
        <description>诗与梦想的远方</description>
        <lastBuildDate>Mon, 04 May 2026 08:23:18 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>WordPress 3.2.1</generator>
        <language>zh-CN</language>
        <image>
            <title>且听书吟</title>
            <url>https://yufan.me/logo.svg</url>
            <link>https://yufan.me</link>
        </image>
        <copyright>All rights reserved 2011, 雨帆</copyright>
        <category>文章</category>
        <category>杂谈</category>
        <category>杂思</category>
        <category>编程</category>
        <category>笔记</category>
        <category>小说</category>
        <atom:link href="https://yufan.me/tags/encoding/feed" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[編碼三境界]]></title>
            <link>https://yufan.me/posts/three-stage-of-programming</link>
            <guid isPermaLink="false">https://yufan.me/posts/three-stage-of-programming</guid>
            <pubDate>Fri, 19 Jan 2018 01:20:12 GMT</pubDate>
            <description><![CDATA[很多人停留在第一階段，也就是能寫出來，能用。但是代碼邏輯不精簡，質量一般，同時雜亂無章。典型的特點是寫之前毫無想法，隨想隨寫。]]></description>
            <content:encoded><![CDATA[<link rel="preload" as="image" href="https://cat.yufan.me/images/2019/05/2019051818123745.jpg"><img src="https://cat.yufan.me/images/2019/05/2019051818123745.jpg?v=1777738726110" alt="Working Girl" width="1013" height="670" data-thumbhash="JBgODYJfWFmrZ3iGh3iHhoOPCXen">
<h1 id="编码的三重境界">编码的三重境界<a href="#编码的三重境界"><span class="icon icon-link"></span></a></h1>
<p>在程序员的成长过程中，写代码的能力通常会经历三个阶段：</p>
<h3 id="1-由少写多--开始懂得写代码">1. 由少写多 —— 开始懂得写代码<a href="#1-由少写多--开始懂得写代码"><span class="icon icon-link"></span></a></h3>
<p>这个阶段的特点是“能写出来，能用”。很多人停留在这里，写的代码逻辑不够精简，质量一般，而且往往杂乱无章。典型表现是：写之前毫无规划，想到什么就写什么。虽然功能能实现，但可读性和可维护性都很差。</p>
<h3 id="2-由多写少--学会优化逻辑">2. 由多写少 —— 学会优化逻辑<a href="#2-由多写少--学会优化逻辑"><span class="icon icon-link"></span></a></h3>
<p>进入第二阶段，你会开始有意识地精简代码逻辑、优化思路。代码看起来更简洁，重复和冗余减少了。但是，这种刻意追求简洁的做法，容易带来新的问题：</p>
<ul>
<li>异常情况考虑不周全</li>
<li>可维护性下降</li>
<li>代码虽然短，但阅读困难，逻辑复杂
很多程序员在这个阶段陷入“面条代码”的陷阱：为了追求短小精悍，反而让代码变得难以理解。</li>
</ul>
<h3 id="3-由少写多--掌握抽象与设计">3. 由少写多 —— 掌握抽象与设计<a href="#3-由少写多--掌握抽象与设计"><span class="icon icon-link"></span></a></h3>
<p>第三阶段的程序员，写代码前就有清晰的需求和思路。</p>
<ul>
<li>适度抽象，考虑未来扩展</li>
<li>逻辑条理清晰，易于维护</li>
<li>不一定是最简洁的代码，但一定是最优质的代码
好的代码，重在可读性、可维护性和扩展性，而不是极致的简洁。</li>
</ul>
<hr>
<h3 id="总结">总结<a href="#总结"><span class="icon icon-link"></span></a></h3>
<p>我发现一个有趣的现象：优秀的代码，其编程风格往往相似。写代码的关键，不在于技巧，而在于思路——你知道自己想要什么，知道要解决什么问题。</p>
<p>没有思路写出来的代码，即便再好看，也无济于事。</p>]]></content:encoded>
            <author>syhily@gmail.com (雨帆)</author>
            <category domain="https://yufan.me/tags/thinking">思考</category>
            <category domain="https://yufan.me/tags/encoding">编码</category>
            <category domain="https://yufan.me/tags/programming">编程</category>
            <category domain="https://yufan.me/cats/coding">编程</category>
            <enclosure url="https://yufan.me/images/og/three-stage-of-programming.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[在编程中思考，简化你的判断逻辑]]></title>
            <link>https://yufan.me/posts/rewrite-your-logic</link>
            <guid isPermaLink="false">https://yufan.me/posts/rewrite-your-logic</guid>
            <pubDate>Mon, 06 Mar 2017 04:31:33 GMT</pubDate>
            <description><![CDATA[之前看 Linus Toward 在去年的某次采访中说到的好代码坏代码，当中提到了逻辑的精简，能用更通用的逻辑减少 if else 的判断在某种程度上可以使你的代码变得更好。]]></description>
            <content:encoded><![CDATA[<link rel="preload" as="image" href="https://cat.yufan.me/images/2019/05/2019051818210131.jpg"><img src="https://cat.yufan.me/images/2019/05/2019051818210131.jpg?v=1777738726110" alt="在编程中思考，简化你的判断逻辑" width="1363" height="881" data-thumbhash="q+cJDIJ6iIl/dnd4iJeJj4v3iQ==">
<p>之前看 Linus Toward 在去年的<a href="https://www.youtube.com/watch?v=o8NPllzkFhE&amp;feature=youtu.be&amp;t=890" rel="nofollow" target="_blank">某次采访</a>中说到的好代码坏代码，当中提到了逻辑的精简，能用更通用的逻辑减少 if else 的判断在某种程度上可以使你的代码变得更好。最近一段时间重构了部分老代码，也 Review 了不少代码，对此观点深有感触。</p>
<p>很多时候，程序员接到的需求，产品巴不得你立刻就能搞定，有时候会给非常紧迫的时间点。这种情况下会带来的最直接问题，就是<a href="http://www.ituring.com.cn/article/263057" rel="nofollow" target="_blank">“设计坏味”</a>。有整体的架构设计的不合理，也有代码逻辑的问题。尤其是对于边界条件的处理，因为需求的急，很多时候大家就会按照业务语言去写。</p>
<p>比如，下面这个例子：</p>
<p>某一报警系统产生了报警邮件，现在需要按照类型显示不同的内容。</p>
<table><thead><tr><th>类型</th><th>报警选择对象</th><th>邮件中展示内容</th></tr></thead><tbody><tr><td>Web事务</td><td>单条Web事务</td><td>Tier，Web事务，节点</td></tr><tr><td>Web事务</td><td>Tier</td><td>Tier，节点</td></tr><tr><td>节点</td><td>某一个节点</td><td>节点</td></tr><tr><td>节点</td><td>Tier</td><td>Tier，节点</td></tr></tbody></table>
<p>如果按照业务的语言，我们可能写出如下的伪代码：</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-java"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Web事务</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 单条Web事务) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Tier,Web事务,节点;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Web事务</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Tier) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Tier,节点;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (节点</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 某一个节点) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 节点;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (节点</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Tier) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Tier,节点;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>可能你看到这里会立刻笑出来，哪有只写 <code>if</code> 不写 <code>else</code> 的。那好，也许你会写出这样的代码。</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-java"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Web事务) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (单条Web事务) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Tier,Web事务,节点;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Tier) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Tier,节点;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">} </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (节点) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (某一个节点) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 节点;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">else</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Tier) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> Tier,节点;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>我相信，大部分人都能将判断逻辑写到这一层，但是，这就完了么？也许你会说完了，逻辑也正确，看起来也很清晰。然而，这远远不够。</p>
<p>其实我们可以发现，在每种情况下，都会返回 <code>节点</code> 信息。只返回节点信息的只有一种情况，其他的情况下，基本都返回 <code>Tier</code> 信息。只有 <code>Web事务 &amp;&amp; 单条Web事务</code> 的情况需要返回 <code>Web事务</code> 信息。所以，最后我们可以精简为两个判断。</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-java"><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> &quot;节点&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Web事务</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> 单条Web事务) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> &quot;Web事务&quot;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (Web事务 </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">||</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">某一个节点) {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    result </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF"> &quot;Tier&quot;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> +</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> result;</span></span></code></pre>
<p>回到最初的命题，为何不要用业务的语言来编写判断逻辑呢？因为业务语言是给用户和产品看的，他们在描述上本身就不够精简。其次，业务的描述，很多时候，是定义边界，说明问题，而不是告诉你判断逻辑。</p>
<p>所以，在写代码的时候，更多的时候要细化逻辑。这样，在维护修改时，才更为方便。下面我举另一个更具体的例子。</p>
<p>这是我 Review Scala 代码的时候遇到的一个问题，首先我先用业务语言描述一下需求。需要判断某个规则的开闭状态，在一天的几点到几点间启用，且还可以额外设置是周一到周日的哪几天启用。</p>
<p>于是我看到当时的同事，写一个方法 <code>isSuppressTime</code> ，会给两个参数，第一个参数为一个时间戳 <code>timestamp</code> ，第二个参数为一个 <code>List[Map[String, String]]</code> 。</p>
<p><code>Map[String, String]</code> 里面有4个值，分别是：</p>
<ol>
<li>startTime，从零点到某个具体开始时间的秒数，0~86399。</li>
<li>endTime，从零点到某个具体结束时间的秒数，0~86399。</li>
<li>isDaily，当时间戳在 startTime endTime 之间时，如果此项为 true，则返回 true。</li>
<li>weekdays，周一到周日，1~7，以<code>,</code>间隔组成的字符串，如<code>1,4,5</code>。表示周一、周四、周五且时间戳在 startTime endTime 之间时返回 true</li>
</ol>
<p>最后他写出了如下的代码（Scala）：</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-scala"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isSuppressTime</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Long</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.currentTimeMillis(),</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                   suppressTimes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> rule.getSuppressTime)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Boolean</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(suppressTimes </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  import</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> scala</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">collection</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">JavaConversions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">_</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  suppressTimes.foreach(params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> &amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.size </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&gt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> startTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;startTime&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> endTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;endTime&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> isDaily</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;isDaily&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> weekdays</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;weekday&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;,&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).toList</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> zero</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zeroTimestamp()</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      //今天零点零分零秒的毫秒数</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> start</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zero </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> startTime.toLong </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> end</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zero </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> endTime.toLong </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (start </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> now</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> end </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&gt;=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> now) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (isDaily.toBoolean)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">          return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> cal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.getInstance()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        cal.setTimeInMillis(now)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        var</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> day</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cal.get(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DAY_OF_WEEK</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 7</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        else</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> weekday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> day.toString</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (weekdays.contains(weekday))</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">          return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  })</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> zeroTimestamp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Long</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> cal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.getInstance()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  cal.set(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">HOUR_OF_DAY</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  cal.set(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">SECOND</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  cal.set(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MINUTE</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  cal.set(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">MILLISECOND</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  cal.getTimeInMillis()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>这个代码看着很长，判断很多，而且还用了超级多陈旧的 API，使得它的性能也不好。而且这是一段 Scala 的代码，却用了较多的 <code>return</code> 和 <code>var</code> ，这两个都是 Scala 不提倡的。最关键的，明明是函数式的代码，他却写出了过程式的感觉。给后面的维护人员（我）带来了不少困扰。</p>
<p>下面，我们来一点点优化这段代码（需要一点点 Java 功底），首先对于方法 <code>zeroTimestamp()</code> ，我第一眼看到的时候，是惊讶的，原作者用了一个比较旧的 <code>Calendar</code> 。对它最深刻的印象就是当年写 <code>SimpleDataFormat</code> 的时候，因为 <code>Calendar</code> 这货导致线程不安全。而每次创建 <code>SimpleDataFormat</code> 的开销比较大，最后不得不写了个 <code>ThreadLocal&lt;simpledataformat&gt;</code> 。</p>
<p>而Java8以后，我们可以直接用 <code>java.time</code> 下面的类来改写 <code>zeroTimestamp()</code> ，这里只需要一行代码，如下：</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-scala"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> zeroTimestamp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">()</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Long</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  Timestamp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.valueOf(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">LocalDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.now().atStartOfDay()).getTime</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>回到 <code>isSuppressTime</code> 方法上来，我姑且不说他的设计多么麻烦，因为这是一个已经被广泛使用的方法，我能做到的就是在不改变签名的情况写来优化实现。</p>
<p>首先，开头我们就看到</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-scala"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(suppressTimes </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> false</span></span></code></pre>
<p>这个空的判断和强制 <code>return</code> ，在 Java 里面， <code>null</code> 是一个很痛苦的事情，Scala 因为基于 JVM 也不例外，但是 Scala 和 Java 8 都分别有一个 <code>Option</code> 类（Java8是 <code>Optional</code> ），来做空值处理。</p>
<p>所以，我们这里第一时间可以干掉这个判断，写成如下方式</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-scala"><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]]](suppressTimes).map(times </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  // ba la ba la</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}).getOrElse(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">false</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span></code></pre>
<p>代码里面的 <code>times</code> 为方法中非空的 <code>suppressTimes</code> ，注释部分为核心的处理逻辑，这样我们避免了一个 <code>if</code> 判断，减少了一个 <code>return</code> 。</p>
<p>而其实， <code>Option([A]).map([B] =&gt; Boolean).getOrElse(false)</code> 等价于 <code>Option</code> 的 <code>exists</code> 方法，最后完整的代码应该如下：</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-scala"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isSuppressTime</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Long</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.currentTimeMillis(),</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">        suppressTimes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]])</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Boolean</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]]](suppressTimes).exists(times </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    times.foreach(params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.size </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&gt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 0</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> startTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;startTime&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> endTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;endTime&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> isDaily</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;isDaily&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> weekdays</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;weekday&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;,&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).toList</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> zero</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zeroTimestamp()</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">        //今天零点零分零秒的毫秒数</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> start</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zero </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> startTime.toLong </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> end</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zero </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> endTime.toLong </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (start </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> now</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> end </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&gt;=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> now) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">          if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (isDaily.toBoolean)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">          val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> cal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.getInstance()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          cal.setTimeInMillis(now)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">          var</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> day</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cal.get(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DAY_OF_WEEK</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">          if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 7</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">          else</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">            day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">          val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> weekday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> day.toString</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">          if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (weekdays.contains(weekday))</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">            return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      }</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    })</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">    false</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  })</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>在上面的例子里面，我们已经干掉了两个 <code>return</code> 和一个 <code>if</code> ，让它有一点 Functional 的感觉了。</p>
<p>上面重构后代码中， <code>times</code> 的类型是 <code>util.List[util.Map[String, String]]</code> 。 <code>times.foreach(params =&gt; {})</code> 里的 <code>params</code> 对应的是 <code>util.Map[String, String]</code> 类型。所以，我们看到判断 <code>if (params != null &amp;&amp; params.size &gt; 0)</code> 时应该会发现，这就是一个list filter的过程嘛。 <code>.filter()</code> 之后不就是一个 <code>.map()</code> ，于是我们可以这么改：</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-scala"><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]]](suppressTimes).exists(times </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  times.filter(params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">params.isEmpty).map(params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">    // ba la ba la</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }).contains(</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">})</span></span></code></pre>
<p>当然 <code>.map(xxx =&gt; Boolean).contains(true)</code> 等价于 <code>.exists()</code> ，于是我们重构的方法如下：</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-scala"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isSuppressTime</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Long</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.currentTimeMillis(),</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">        suppressTimes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]])</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Boolean</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]]](suppressTimes).exists(times </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    times.filter(params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">params.isEmpty).exists(params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> startTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;startTime&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> endTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;endTime&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> isDaily</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;isDaily&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> weekdays</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;weekday&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;,&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).toList</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> zero</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zeroTimestamp()</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">      //今天零点零分零秒的毫秒数</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> start</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zero </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> startTime.toLong </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> end</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zero </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> endTime.toLong </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (start </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> now</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> end </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&gt;=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> now) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (isDaily.toBoolean)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">          return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> cal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.getInstance()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">        cal.setTimeInMillis(now)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        var</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> day</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cal.get(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DAY_OF_WEEK</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 7</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        else</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">          day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> weekday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> day.toString</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">        if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (weekdays.contains(weekday))</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">          return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      }</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">      false</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    })</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  })</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>这次重构，我们又去掉了一层 if 判断，改为 filter 实现，减少了一次返回。到了这一步，我们会发现，下面需要实现的就是一个方法，对 <code>util.Map[String, String]</code> 去做处理，返回一个布尔值，于是我们精简方法的实现代码为两部分：</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-scala"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isSuppressTime</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Long</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.currentTimeMillis(),</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                   suppressTimes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> rule.getSuppressTime)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Boolean</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]]](suppressTimes)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .exists(times </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> times.filter(params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">params.isEmpty).exists(isValidateTimes(_, now)))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>这个为边界过滤的方法。</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-scala"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isValidateTimes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Long</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Boolean</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> startTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;startTime&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> endTime</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;endTime&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> isDaily</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;isDaily&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> weekdays</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;weekday&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;,&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).toList</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> zero</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zeroTimestamp()</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D">  //今天零点零分零秒的毫秒数</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> start</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zero </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> startTime.toLong </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> end</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zero </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> endTime.toLong </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (start </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> now</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> end </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&gt;=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> now) {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (isDaily.toBoolean)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> cal</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.getInstance()</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    cal.setTimeInMillis(now)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    var</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> day</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> cal.get(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Calendar</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">DAY_OF_WEEK</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">==</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 7</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    else</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">      day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> day </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">-</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> weekday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> day.toString</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">    if</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (weekdays.contains(weekday))</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">      return</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> true</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  }</span></span>
<span class="line"><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF">  false</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>这个为我们要重构的核心处理逻辑。我们优化整理它的判断条件，最后可以实现如下的完整代码：</p>
<pre class="shiki shiki-themes github-light github-dark" style="--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e" tabindex="0" icon="&lt;svg viewBox=&quot;0 0 24 24&quot;&gt;&lt;path d=&quot;M 6,1 C 4.354992,1 3,2.354992 3,4 v 16 c 0,1.645008 1.354992,3 3,3 h 12 c 1.645008,0 3,-1.354992 3,-3 V 8 7 A 1.0001,1.0001 0 0 0 20.707031,6.2929687 l -5,-5 A 1.0001,1.0001 0 0 0 15,1 h -1 z m 0,2 h 7 v 3 c 0,1.645008 1.354992,3 3,3 h 3 v 11 c 0,0.564129 -0.435871,1 -1,1 H 6 C 5.4358712,21 5,20.564129 5,20 V 4 C 5,3.4358712 5.4358712,3 6,3 Z M 15,3.4140625 18.585937,7 H 16 C 15.435871,7 15,6.5641288 15,6 Z&quot; fill=&quot;currentColor&quot; /&gt;&lt;/svg&gt;"><code class="language-scala"><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isSuppressTime</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Long</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> System</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.currentTimeMillis(),</span></span>
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">                   suppressTimes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> rule.getSuppressTime)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Boolean</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">  Option</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">List</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">]]](suppressTimes)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .exists(times </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> times.filter(params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">!=</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> null</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> !</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">params.isEmpty)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">    .exists(isValidateTimes(_, now)))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">private</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> def</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> isValidateTimes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">params</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: java.util.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">[</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">String</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">], </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70">now</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">: </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0">Long</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> Boolean</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> zero</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zeroTimestamp()</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> start</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zero </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;startTime&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).toLong </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> end</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> zero </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">+</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;endTime&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).toLong </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">*</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF"> 1000</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> isDaily</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;isDaily&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).toBoolean</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> weekdays</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> params.get(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;weekday&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).split(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF">&quot;,&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">).toList</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">  val</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70"> weekday</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0"> LocalDate</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">.now().getDayOfWeek.getValue.toString</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">  (start </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&lt;</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> now</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> end </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&gt;=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> now)</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> (isDaily </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583">||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8"> weekdays.contains(weekday))</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8">}</span></span></code></pre>
<p>这样，我们就实现了一个 <code>if</code> 都没有，一个 <code>return</code> 都没有的纯函数式写法。</p>
<p>总的来说，代码谁都能写出来，但是把需求从文字或者是流程描述换成编码实现时就有了对程序员抽象逻辑能力的需求。如何组织抽象，就像是如何写作文，或者是 Kata（空手道里面的招数、套路），不要按照业务描述写 if else，而要尽可能简化找到一致性的简单逻辑描述。</p>
<p>如果能将所有的特殊情况变为通用情况，简化逻辑判断，那么代码在后面的迭代中也会比较易于维护。</p>]]></content:encoded>
            <author>syhily@gmail.com (雨帆)</author>
            <category domain="https://yufan.me/tags/thinking">思考</category>
            <category domain="https://yufan.me/tags/encoding">编码</category>
            <category domain="https://yufan.me/tags/programming">编程</category>
            <category domain="https://yufan.me/cats/coding">编程</category>
            <enclosure url="https://yufan.me/images/og/rewrite-your-logic.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>