• 关于 URL 规范 at 2019年01月11日

    首先我更支持平级非嵌套的资源表示方式,即 /animals/:id ,如果要限定 zoo 下的 animals 可以用 /animals?zoo_id=1 。但在有一个唯一标识符 (ID) 的情况下就没必要嵌套了。用户访问他看不到的资源应该通过其他方式来限制。

    其次建议 LZ 多了解下 RESTful API 的定义。不是 Rails 的那套 DSL 定义出来路由的才叫 RESTful 。嵌套资源也不是所谓的标准风格。理论上只要用统一的 URL 表示资源就可以算是 RESTful 的,就算你用的是 /animals?id=1 。它是一种架构风格但不是规范。而资源有个统一的 URL 的好处是它的常规操作只用修改 method 而不是 URL + method 。并且这种统一风格可以让大多数资源受益。

    最后说一句,如何设计好的 API 跟内部怎么实现是两码事。

  • 这样递减的 sql 怎么写 at 2019年01月05日

    @wootaw 是的,如果按照 LZ 的计算过程描述,其实是有不少中间数据的,比较过程化,这并声明式的 SQL 适合表达的领域。而且如果不考虑存储因素的话化,这个需求本质上就是一个链表计算。因此把计算过程和存储分开思考,解决方案的适用性会广很多。

  • 这样递减的 sql 怎么写 at 2019年01月04日

    @wootaw 别闹 😄

  • 这样递减的 sql 怎么写 at 2019年01月02日

    翻完评论才看明白什么意思。我觉得这个计算逻辑不适合用 SQL 做,因为它的关注点并非在集合,而在集合中的每条元素。用两个链表做计算(递归比较头节点)反而更容易,计算结果再保存进数据库就行。

    如果有非常特殊的原因一定要在 SQL 里实现,可以看一下 lateral join 和 with recursive 。

  • 一招秒杀 N+1 agg 问题 at 2018年11月02日

    PG 文档上都有,见 4.2.7 Aggregate Expression

  • {}do ... end 的区别只在于跟前面的方法结合的优先级,简单来说 {} 会 “紧贴” 它前面的方法,而 do ... end 更加宽松。

    我看楼主之前有过几个帖子讨论语言的设计优劣问题。但说实话纠结这些并没有太多意义,更多是结合个人偏好的主观问题。倒不如多了解下各种语法的客观差异,避免踩坑,然后总结出一套符合自己偏好的编程方式和风格干活。

  • SQL Style Guide at 2018年09月10日

    确实 query plan 不同,感觉 CTE 更严格的按照每一步去划分优化的边界,而子查询作为一个整体查询有时候会优化得更多一点。所以我一般是测试时写 CTE 然后转到代码里再换成子查询。这样也更容易转换成 app 层的代码。因为 Elixir 的 Ecto 可以写出非常复杂的分析型查询,但目前还不支持 CTE 。

    Emacs 有个插件能帮你对齐,也是你说的 river 风格。不过 Emacs 的对齐功能基本都有点自恋 + 死不认错,人工调整后编辑器也会不停的帮你 “纠正” 过来。想调整规则得去研究类似 AST 的数据结构,所以我直接放弃了……

  • SQL Style Guide at 2018年09月09日

    缩进方式很有意思。这个例子还是很考究的,比如 JOIN 其实是属于 FROM clause 的部分,算是 FROM 下一层的表达式,因此缩进在 FROM 的更右边,ON 下面换行的 AND 同理。

    这种方式我尝试过一段时间(可能不是严格照着这个 styleguide 来的)。最大的感受是必须有编辑器提供自动格式化才好用,几乎没办法靠人工维护。尤其是写超过 20 行的话自己都不知道缩进对不对,每多加一行都可能导致之前写的部分重新缩进。

    PostgreSQL 文档里有些 SQL 例子是按这种方式缩进的,但也有混用的。比如 window function 的一个例子,内层按分界缩进外层就顶头了:

    SELECT depname, empno, salary, enroll_date
    FROM
      (SELECT depname, empno, salary, enroll_date,
              rank() OVER (PARTITION BY depname ORDER BY salary DESC, empno) AS pos
         FROM empsalary
      ) AS ss
    WHERE pos < 3;
    
  • Why Sometimes I Write WET Code at 2018年09月08日

    DRY 的代码特点是 “改了一个地方,所有相关的地方都被影响” 。有时候这是好事,另一些时候则是坏事。我觉得用 reason to change 来衡量代码是否需要可重用是个可行的做法。如果两段代码实现相同,但是为了不同的业务目的,那就让它重复。

    另外也赞同接口设计比实现更重要。接口定义得良好,实现烂一点影响范围也有限,并且容易重构过来。个人感觉过度重视局部代码的精巧结构,以 DRY 为主要的衡量指标,甚至以实现来反过来影响接口设计是很多新手常犯的错误。

  • @chenge ROM 里借鉴了 Changeset 的概念 :https://api.rom-rb.org/rom/ROM/Changeset.html

    Rails 的 ActiveRecord 作为一个超级 model ,在框架层面集成好用的功能于一身。这点跟 Ecto 在设计理念上有根本差异,脱离这点谈 Changeset 不大现实。毕竟 Changeset 的所有功能在 AR 里都有,只是如何组织,以及好不好用的问题。无端添加一个概念反而容易让人迷惑 -- 我该用那种方式修改数据?这点在 Ecto 里并不存在,因为 Changeset 是唯一修改 “模型” 数据的方式。

    Changeset 另一个好处是容易脱离数据模型再开一层抽象,比如做外部数据的校验。这方面其实 Ruby 也早就探索过,不过是叫做 Form Object 。虽然 ActiveModel 不太给力,但 Ruby 社区的轮子也不少,不喜欢 AR 的可以去用 dry-rb ,有相对完善的校验和类型系统,足够你干很多事情。

    名词是新名词,但内部概念还真不是新概念。