作者归档:白宦成

关于白宦成

独立开发者, 自由职业者, 写作者

找到对的问题

找到对的问题

最近在读《如何成为顶级记者》,总体来说,不同的记者有不同的切入视角,但如果要找一个能够综述所有人的关键点就是 —— 「离事情发生的地点足够近」。无论是通过自己的数据分析找到真正的事情发生点,还是和当事人建立更加友好、更加深入的联系,都是为了达成「离事情发生的地点足够近」这个诉求。

而当我总结到这里时,我突然在思考一个问题:我的问题真的是如何成为一个顶级记者么?

显然不是,我必然是会在编程和工程师的路上越走越远的,我的目的其实是:「如何录制好一档访谈类型的播客」,而这个问题如果细化的话,其实真正的问题应该是「如何提出一个正确的问题」

当我明确了正确的问题之后,那就知道正确的 Action 应该是什么 —— 「学习提出正确的问题」

回到这个事情本身,我其实在初期也进行了思考:从做一个好的访谈播客出发,推导出我需要具备优秀的访谈能力,而优秀的访谈能力往往出现在优秀的主持人和优秀的记者身上,因此我推导出了需要去学习顶级记者的思路。但是,问题的思考还不够深入,如果进一步推导和抽象,才能得到正确的答案 — 「提出一个正确的问题」。

Laravel 9 单元测试报错 An email must have a “From” or a “Sender” header

Laravel 9 单元测试报错 An email must have a “From” or a “Sender” header

在 Laravel 9 当中,引入了新的 Mailer 组件,随之而来的是一些过去没有的 Bug。

如果你在开发过程中出现了 An email must have a "From" or a "Sender" header 的报错,需要在 PHPUnit 当中配置 MAIL_FROM_ADDRESS 属性,用于通过测试。

<env name="MAIL_FROM_ADDRESS" value="from@example.com" />

来源:https://laracasts.com/discuss/channels/laravel/for-reference-an-email-must-have-a-from-or-a-sender-header

Gutenberg 编辑器带来的模式变更

Gutenberg 编辑器带来的模式变更

自 WordPress 5.0 开始, Gutenberg 编辑器(后文称为古腾堡编辑器)开始存在于 WordPress 当中,为普通用户所用。而得益于古腾堡编辑器带来的卓越的使用体验(用户不需要再记录晦涩难懂的短代码、无须忍受 TinyMCE 的界面),用户使用 WordPress 的方式也开始变得多种多样。

如果你还没有用过古腾堡编辑器,那你可以访问 WordPress 官方提供的在线预览工具来试用:https://wordpress.org/gutenberg/

体验的变革

古腾堡的出现,让作者可以更加接近于我一直描述的 WordPress 所能够提供的最大的价值 —— 让写作变得更加简单,易实现。不仅如此,古腾堡带来的新的编辑体验,让除了工程师、Geek 以外的人也可以很轻松的实现一个更好看、更易读、更加丰富的界面。

而从 WordPress 开发团队的态度来看,也是更加推荐作者们更多的使用古腾堡编辑器:从Twenty Nineteen 开始,古腾堡的支持就成为了默认,并不断的通过官方主题的用法,让作者们看到 WordPress 原来还可以是这样。今年的 Twenty Twenty Two 更是从写作者变为了艺术家 —— 你可以十分简单的建造一个线上的画廊。

开发模式的变更

过去,WordPress 开发整体来说,可以分为两条线:一条是主题开发,你需要与 PHP、HTML、CSS、Javascript 共同战斗;另一条线则是插件开发,你需要与PHP 为伍。

搞插件开发的,你对于前端开发不甚了解也无所谓。WordPress 提供了大量的 helper function 。比如,我在「开发一个短代码插件」中,不使用一行前端代码就实现了 TinyMCE 的功能新增。

而在新的古腾堡编辑器生态下,开发者如果希望对于古腾堡进行拓展,一方面依然可以使用之前的方式,接入各种短代码来实现各种不同的用户体验,另一方面,则可以借助与前端技术栈来实现一个更加丰富的用户体验。

你可以使用 JQuery 和 WordPress 为你绑定的全局对象来修改古腾堡编辑器实现你的目标,更是可以借助前端的开发体系,诸如 Webpack、React 来开发一个强交互,体验佳的用户体验。

WordPress 的开发不再是 PHP 工程师自己的事情,它将更多的人卷入 WordPress 的开发过程中。而对于 WordPress 开发工程师来说,则有了更高的要求,来完成插件的开发、主题的开发。

总结

自古腾堡的推出,这样的趋势就开始渐显。但直到我真正开始开发一款古腾堡插件,我才真正意识到 —— WordPress 在内容创作领域的价值,无可替代。纵然他有众多的历史包袱,但对于每一个创作者来说,他都是最好的选择。

WordPress 如何获得最顶级的自定义分类

WordPress 如何获得最顶级的自定义分类

WordPress 支持设定多级分类,如果你需要在页面中展示最顶级的分类,则需要获取到最顶级的分类,具体实现的方式如下:

1. 获取当前文件类型的自定义分类

使用如下代码获取到自定义分类

$tax = wp_get_post_terms($post->ID,array('part'))

获得的结果如下

Array
(
    [0] => WP_Term Object
        (
            [term_id] => 7
            [name] => 目录1
            [slug] => category1
            [term_group] => 0
            [term_taxonomy_id] => 7
            [taxonomy] => part
            [description] => 
            [parent] => 6
            [count] => 2
            [filter] => raw
        )

)

这里的 term_id 则代表你设定的自定义分类的 ID

2.获取分类树

因为分类是多级的,我们需要找到祖先节点,因此需要用到函数 get_ancestors ,执行如下代码

$tree = get_ancestors($tax[0]->term_id)

会获得如下结果

Array
(
    [0] => 6
    [1] => 8
)

这个返回结果则是从你当前分类向上查找,查找到最顶级的分类的结果。需要注意的是,这个数组的最后一个元素才是你最终最顶级的分类。

3. 提取最后一个元素的 ID

当你知道了最后一个才是最顶级的分类,只需要使用 end() 函数来获取最后一个。

end($tree)

这样,就能拿到最终目录的 ID,接下来要做的就是在你的界面上展示这些数据。

为 WordPress 加入 Server Timing 判断不同行为性能差异

为 WordPress 加入 Server Timing 判断不同行为性能差异

自打上次为我的博客加入了 Redis 缓存后,博客站点访问速度明显变快,几乎可以达到秒开的效果。剩下的需要在网络层面进行进一步的优化。

不过,我还在思考如何才能更好的优化我的 WordPress 性能。很显然,我需要一个指标来帮助我做决策。这让我想到了一个东西 —— HTTP 标准中的 Server-Timing Header。

Server-Timing 标头传达在一个给定请求-响应周期中的一个或多个参数和描述。它用于在用户浏览器的开发工具或 PerformanceServerTiming (en-US) 接口中显示任何后端服务器定时参数(例如,数据库读/写、CPU 时间、文件系统访问等)。

来自 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Server-Timing

Server Timing 可以帮助我们记录服务端到底在哪些步骤中消耗了哪些时间,可以方便我进行性能的查询。

使用 WP Server Timing 添加 Server-Timing 头

我在 WordPress 的 Plugin Directory 目录进行了搜索,并没有找到支持这个功能的插件,不过我在 Github 上找到了这个插件 —— https://github.com/ocReaper/wp-server-timing

有了这个插件,我就可以无需自己手动添加相应的能力。

使用插件也非常简单,在页面上下载压缩包,并在 WordPress 后台安装并启用这个插件。

安装后的效果

安装完成后,你接下来要做的就是重新在浏览器中打开你的网站,并按下 F12 打开开发者工具,选择文档 Tab(英文是 Document),刷新当前页面,就可以看到列表中出现了一个你博客地址对应的文档,点击文档,并在弹出的窗口中切换到「时间」Tab,就可以在下方看到服务器计时了。

示意图

按照上图的结果,可以看到,我的 WordPress 耗时最长的是 Template Processing ,我需要针对这个属性进行定向优化。

辅助理解资料

以下是 WordPress 的加载顺序图,你可以对比着参考

WordPres 的加载顺序图,来源:https://www.rarst.net/wordpress/wordpress-core-load/

Jest 如何将复杂的判断条件中的具体问题暴露出来?

Jest 如何将复杂的判断条件中的具体问题暴露出来?

在写测试的时候,如果你需要对大量的数据进行 compare 处理的时候,你大概率不会把所有需要对比的对象都列出来,而是选择直接循环处理。

在测试中如果有循环处理的时候,很有可能会出现的一个问题是你可能无法在测试无法通过时快速定位道具体是循环中的哪一个元素出现的问题。这个时候的定位就会比较麻烦。

一个比较好的办法是,可以在 Jest 中加入 try/catch 中来处理错误,这样可以在出现错误的时候,打印一些辅助信息来快速定位,比如

it('test-error-catch-example',() => {

   let needTestData = [1,2,3,4]

   needTestData.foreach( item => {
       let result = doSomething(item)
       // 这里开始是新增的
       try{
          expect(result).toBe(true)
       }catch(e){
          console.log("error key",item)
          throw e;
       }
       // 新增的错误处理结束
   })

})

通过添加一个自定义的 try catch ,可以在出现问题的时候,一方面将 Error 按照常规的方式抛出,等待 Jest 处理,另一方面,可以在 catch 时输出自定义的信息,方便我们进行排查和修复。

为什么不买 NFT?

为什么不买 NFT?

从去年开始,我就开始定投 Crypto 领域的主流货币,比如 BTC、ETH 等,每月少量入金,用一笔不会影响我正常生活的钱来完成 Crypto 领域的投入。

而最近大火的 NFT,我除了参与一些 NFT 的开发意外,并没有参与市场化的交易。

对我来说,原因其实非常简单:

  1. 我认可数字藏品有价值,但数字藏品很多时候是在赌喜好,相比于主流币的价值增长(随着共识和稀缺提升),数字藏品往往会出现非常典型的「接盘」的情况出现。如果你看好的藏品没有人喜欢,则很难产生流通。这一点 NFT 有典型的弱点。
  2. 基于结论 1 ,就会推导出结论 2 :一个流通比较困难的产品,就需要你更加在乎时机,你只有在卖出的时机卖出,才能获得收益。这会要求你「盯盘」,时刻关注交易信息,及时将你自己的藏品卖出去。

虽然 NFT 确实可以一夜暴富( 0.1 Eth 入,5 个 Eth 出)也是很正常的,但对于身在其中的玩家来说,消耗的精力也是 BTC、ETH 等主流币的定投者无法比拟的。

至少,买 BTC 和 ETH 我可以每天安稳的睡觉,不用担心需要实时盯盘,在一个好的时候卖出。

独立开发者可用的支付方式

独立开发者可用的支付方式

我会关注一些个人可用的收款方式,核心支付要解决的问题是在开发产品过程中,必须要用到的各项基本技能。如果支付流程无法打通,独立开发者的商业模式就会遭到最直接的打击:你如何赚到钱?

可能你会想,我难道不能使用广告的方式来赚钱么?

当然可以,但与直接向最终用户收款的方式相比,显然,广告赚到的钱不过是蝇头小利。

此外,我也说过,广告赚钱是非常少量的,因为你拿到的本身就是平台收益中的一小部分。此外,广告还有一个问题是与流量相关的,你必须不停的想办法获取流量,并将流量转化,这对于独立开发者而言,并不友好。因此,我并不看好以广告为基础的独立开发产品模式。

故而,我十分在乎收款流程的通畅。

其实想想也能明白,你会发现国内独立开发者大多出现在 iOS、Android 等移动应用开发平台上,这里很难说没有平台提供的收款渠道带来的价值。

所以从这个角度而言,我也建议大家可以适当关注一些收款渠道,以便你自己后续使用。

为什么不注册公司,自己接入渠道?

当提起这些第三方渠道的时候,大家经常会说,诶呀,你这个收款平台的费率好高啊,你看看支付宝官方,只有XXX。

我觉得,这个事情如果只对比收款费率的话,过于单纯。

实际上,支付宝官方、微信支付官方往往需要企业资质才能开通。而你开通这些账号所支付的成本,远超你当下的收入。

你用你前期的收入,养活了代注册公司、代记账公司。早期其实完全没有必要,你大可以用这些平台完成前期的冷启动,启动完成,有了长期收入,你的收益足以支撑你继续后续的工作,再替换不迟。

我关注到的收款平台

面包多 Pay

https://mbd.pub/

PayJS

https://payjs.cn/

XorPay

https://xorpay.com/

读罗翔《刑法学讲义》感悟 & 批注

读罗翔《刑法学讲义》感悟 & 批注

感悟

我想读这本书,自然是对风靡 B 站的罗翔老师所好奇,在微信读书上打开了这本书,读了起来。

从个人的阅读体验上来看,比较推荐拿来做日常的读物,如果你希望更了解刑法,这本书不适合,这本书是罗翔老师视频的文字版。

值得表扬的点

这本书我认为最有价值的便是「写在最后」章节中的三不和三要。特地再摘出来,以提醒自己和读到这篇文章的你。

三件不要做的事

1. 控制内心的张三,人心隐藏着整个世界的败坏,你无法避免心动,但千万不要行动。

2. 不要有知识的优越感,追逐知识只是让我们承认自己的无知。

3. 学习法律不是钻法律的漏洞,而是真正认定法治的信念。

罗翔《刑法学讲义》

三件坚持做的事

1. 坚持阅读经典,与人类伟大的灵魂对话,走出我们固有的平庸与傲慢。

2.思想与行动并存,我思并不代表我在,我动方能印证我存,在每个个案中坚守法治的精神。

3. 从爱抽象的理念转向对具体的人的爱,我们无法做伟大的人,但我们可以心怀伟大的爱,做细微的事情。

罗翔《刑法学讲义》

还不够好的点

这本书的整体行文上是先探讨了法律的基础,再针对刑法进行定向的研究。在内容上,往往是法条的基本解释 + 案例 + 思考题。

个人觉得,因为并没有直接提及完整的法条,这样的书对于读者而言,帮助有限,大概率是看完乐呵乐呵得了,这一点我认为之前购买的民法典的实用版会更好。

批注

前言 每一次学习都是为了追求智慧

永远不要在自己看重的立场上附着不加边际的价值,要接受对立观点的合理性。

作为学者,我们时常生活在一种幻象之中,认为真正的知识一定是高雅的,大众传播都是下里巴人,娱乐至死。但这是一种傲慢与偏见,甚至是另一种形式的不学无术。真正的知识一定要走出书斋,要影响每一个愿意思考的心灵。

每一个人都拥有学习的能力与权利,每一种学习从根本上都是对普遍真理的回应。

刑法:犯罪人的大宪章

001 刑罚的起源

任何一部法要被称为刑法,一定有两个部分:一个是犯罪论,一个是刑罚论。

为什么刑事立法应当遵循民主程序,以及刑罚有追求正义的内在要求。

我国法律体系由7大法律部门构成:宪法、民商法、行政法、经济法、社会法、刑法,以及程序法。

002 刑法是道德伦理的最低要求

决定是否发动刑罚权的时候,既要考虑结果正义,又要考虑行为正义。犯罪侵犯了法益,在结果上不正当。同时,犯罪行为也违反了伦理规范,在行为上也不正当。

003 不受约束的刑罚权,比犯罪更可怕

刑法既要实现惩罚犯罪的保护机能,也要恪守保障罪犯人权的保障机能

刑法的基本原则

004 罪刑法定原则:对权力的严格约束

法无明文规定不为罪,法无明文规定不处罚,这是法治国家最重要的刑法原则

国家的立法权、司法权和行政权这三种权力应当分立以制衡。

罪刑法定反对罪刑擅断,使公民免受任意刑杀的恐惧,它必须体现限制国家权力,保障公民自由的基本精神。

一个是“刻薄少恩”推行专制的法家,一个是保障自由限制权力法治,两者虽一字之差,但却谬之千里。

005 空白罪状怎么填

只有明确的法律才能保障公民的合理预期,而这是自由的关键,

009 刑法解释的范围与实质

解释是司法活动,而非立法行为。因此,形式解释论是首要的,它划定了刑罚权的范围。如果突破刑法条文形式上的限制,仅从社会生活需要对刑法进行实质解释,就会破坏刑法的稳定性和明确性,侵害公民的合理预期。但是,在形式解释的基础上,需要考虑实质解释论的要求,否则法律就会太过僵化。

010 举轻以明重,举重以明轻

罪时举轻以明重,当轻的行为构成犯罪,那重的行为更应是犯罪;出罪时举重以明轻,当重的行为不构成犯罪,那轻的行为就自然不是犯罪。

011 刑法解释,朝着良善进行

人类所有的知识都来源于对权威的相信,我们相信存在正义,而正义一定是客观存在的。看见的不用相信,看不见的才用去相信。

刑法的效力

012 刑法的空间效力

主权是国家的最高统治权,主权国家之间是平等

刑法的空间效力主要有四个原则:属地管辖、属人管辖、保护管辖和普遍管辖。

013 刑法的时间效力

对未来的合理预期,是所有生物存活的基本条件。作为万物之灵的人类更是需要合理预期,法律必须保障人们的这种需要,让人免于恐惧。因此,禁止溯及既往是对权力的基本约束。

015 危害行为的作为与不作为

任何犯罪都必须要有行为,如果没有行为就不是犯罪。一个人的思想再邪恶但只要没有表现出行为,就不应该进行惩罚。

权利跟义务是对等的。如果警察在休假期间也有制止义务的话,那就意味着警察身着便装也有权搜查民众。从这个意义而言,在休假期间的警察没有制止犯罪的义务。法律不能够对人做过高的道德要求,刑法只是对人最低的道德要求。

018 不知者无罪

近代以来,人类最悲惨的命运就是用抽象人的概念取代了具体人,人被抽象化的必然后果就是人的价值被贬损。当人被抽象化,他也就不可避免地根据种族、性别、国别、阶层、贫富等各种抽象概念进行归类。

犯罪排除事由

021 正当防卫

霍姆斯大法官说:法律的生命是经验而不是逻辑。法律人要有逻辑推导能力,但更重要的是要有常识。法律人要学会谦卑地听取民众的朴素的声音。

司法要倾听民众朴素的声音,刑事责任的一个重要本质是在道义上值得谴责。因此,犯罪与否不是一个单纯的专业问题,普罗大众都有发声的权利,司法永远不能超越社会良知的约束。法律不是冰冷的条文,它必须兼顾天理人情,不断地在各种利益中寻找一个最佳的平衡点。

023 责任排除事由

判断一个人负不负刑事责任,应该根据行为时有无责任能力,而不是看结果时。

024 刑事责任年龄需要下调吗

大陆法系倾向于乐观主义,代表国家是德国和意大利,这些国家的刑法都和我国一样,认为不满14周岁没有刑事责任能力,对任何犯罪都不负刑事责任

025 法律认识错误

在法律体系中,刑法是一种最后的补充法,认识到行为不符合刑法规定,必然也知其不符合民法、行政法等部门法,但反之未必

未完成的犯罪

026 犯罪预备

根据犯罪的实现程度,可分为完成形态与未完成形态,前者完全实现了法条规定的构成要件,是既遂;后者没有完全实现构成要件,包括犯罪预备、犯罪未遂和犯罪中止。

犯意表示是一种思想流露,还没有表现为行为,不属于刑法打击范围。犯意表示一般是以口头、书面或者其他方法,将真实犯罪意图表现于外部的行为。

032 中立的帮助行为

人们习惯于在自己看重的事情上附上不着边际的价值,司法机关往往过分看重打击犯罪的价值,而忽视了其他职业的稳定性。

034 主刑

刑罚可以分为主刑和附加刑,主刑是只能独立适用的主要刑罚方法,它不能附加适用,对一种罪行一次只能适用一个主刑。主刑包括管制、拘役、有期徒刑、无期徒刑、死刑。

035 死刑的存与废

死刑也体现了对犯罪人的尊重。犯罪人出于自由意志,选择犯罪,自然也就预见了行为的后果,对他的惩罚是对他理性选择的尊重。黑格尔把这叫做“自为的正义”,由于犯罪是犯罪人选择的结果,因而刑法也可以合乎逻辑地从犯罪人的行为中引申出来,获得合理性。

刑罚的裁量与消灭

038 量刑

法律一经制定,就已经滞后,它不可能与时俱进地涵盖社会生活的方方面面,机械地、教条地适用法律,或者导致法律过于宽松,或者过于严苛。法官是人,而不是“机器人”,他必须运用正义之心,主动弥补法律的漏洞,以满足公众对于正义的期待。

039 自首

但是如此恶劣的罪行,难道因为是自首就可以从宽处罚吗?法律对于自首,规定的是可减主义,而非必减主义。对于自首的犯罪分子,可以从轻或减轻处罚,犯罪情节较轻的,可以免除处罚。既然法律的表述是“可以”,那么对于上述示威型自首也就可以不从宽处理。

040 累犯和缓刑

有三类人员只要符合条件,就应当适用缓刑,不满18周岁的人、怀孕的妇女和已满75周岁的老人。

053 洗钱罪

洗钱罪,是指明知是毒品、黑社会性质的组织、恐怖活动、走私、贪污贿赂、破坏金融管理秩序、金融诈骗犯罪的违法所得及其产生的收益,掩饰、隐瞒其来源和性质的行为。通俗来讲就是把黑钱变成白钱。

性自由权

065 强奸罪

总之,交往中最重要的就是尊重,在法律上,没有半推半就这个概念,要么是同意,要么是拒绝。女性语言上的拒绝应当获得法律的尊重。如果一个男性出于花花公子式的哲学,认为女生说不就是半推半就,这是他的评价误认,必须要为错误的价值观付出代价。

083 索赔是正当权利

这种见解忽视了起码的法治观。法治的基本原理告诉我们:对公权力而言,凡是没有允许的,都是不可为的;对私权力而言,凡是没有禁止的,都是可以做的。

私人权利不是法律所赋予的,只要法律没有禁止,就是民众的权利之所在。相反,公共权力才是法律所赋予的,只要法律没有授权,公共权力就不能轻举妄动。

妨害司法罪及卖淫罪

093 律师伪证罪

一个国家是否有真正的自由,试金石之一是它对那些为有罪之人、为世人不耻之徒辩护的人的态度

写在最后

三件不要做的事。1.控制自己内心的张三,人心隐藏着整个世界的败坏,你无法避免心动,但千万不要行动。2.不要有知识的优越感,追逐知识只是让我们承认自己的无知。3.学习法律不是钻法律的漏洞,而是真正认定法治的信念。

三件坚持做的事。1.坚持阅读经典,与人类伟大的灵魂对话,走出我们固有的平庸与傲慢。2.思想与行动并存,我思并不代表我在,我动方能印证我存,在每个个案中坚守法治的精神。3.从爱抽象的理念转向对具体的人的爱,我们无法做伟大的人,但我们可以心怀伟大的爱,做细微的事情。

拥抱不确定性

拥抱不确定性

最近又进行了一次播客录音。刚好又收到了协作者的邀请,在听两个月前自己的录音。

莫名的感觉到,我可能在成长了。

两个月前的我,对于录音过程中的节奏要求非常高,如果我发现情况不对,就一定要强行扭转回去。但这并没有意义,反而会让大家觉得很生硬。

如今的我,可以坦然的面对节奏的消失,坦然面对冷场的局面。

大概是我正视了,录播的压力就是可以很小,就算我的顺序有问题,只要大方向不出错,那就不会在后续成片造成太大的影响。后续逐步调整即可。