在生产力工具大类里,Project Management & Issue Tracking Tool(国内一般统称项管工具)可以说是其中历史最悠久也是最拥挤的品类。一方面项管工具是任何一家信息化管理的公司里最基本,最核心的工具,承担着安排计划,管理进度,追踪问题,串联其它各平台的任务。另一方面项管工具表面上的门槛比较低,Todo list其实也称得上是一个轻量化的项管工具。这两个因素叠加在一起,自然有人前仆后继地涌进这条赛道,而这其中的绝大多数产品也还是难以摆脱Jira+Trello的影子,形成低水平的重复。Linear(https://linear.app)是最近出现的又一款项管工具,倒是有些与众不同。
创始团队
Linear的创始团队背景确实很合适打造项管工具,设计师+全栈+工程管理+成功创业背景,又都是顶配。
Karri Saarinen - 之前担任Airbnb的首席设计师,Coinbase的第一位设计师以及之后的设计团队负责人。之前也在YC的其它公司创过业。
Tuomas Artman - 研发背景,主要经验在iOS移动端,早先创业的公司被Groupon收购,之后担任过Groupon和Uber的研发以及管理职位。在Uber帮助把移动工程团队从15人扩张到400人。
Jori Lallo - Coinbase早期的工程师,负责API和前端框架。
数据模型
数据建模很大程度上决定了产品的形态,体现了设计者的取舍,所以大量的篇幅会分析Linear的建模。
顶层模型 - Workspace
半顶层模型 - Account
Workspace的子模型 - Team, Project
Team的子模型 - Issue, Workflow, Label, Template, Cycle
顶层模型之Workspace
Workspace有两个重要属性,一个是URL name,一个是Workspace name,前者类似于邮箱的名字,全局唯一,作为Workspace在linear的地址,格式是linear.app/<<url name>>。后者类似于nickname,可以任意起名。后文cookie的截图中可以看到,Workspace对标的是Organization概念。
半顶层模型之Account
Account代表一个用户。说它是半顶层模型,因为它的两面性。
作为Workspace子模型的一面
- 管理Account设置的URL是linear.app/<<workspace url name>>/settings/account/profile。
- 在某一个Workspace下访问这个account所有issue的URL是linear.app/<<workspace url name>>/profiles/<<username>。
- 上一点URL里的<<username>>还有头像这些可以被更改,但是修改的作用范围仅限于这个Workspace。
作为顶层模型的一面
- 看上去和Workspace是多对多的关联关系,一个Workspace可以关联多个Account,一个Account也可以关联多个Workspace。
- 管理Account设置的URL,如前所述虽然是按照Workspace限定的,但其中的一些设置,比如界面Theme是否采用Light还是Dark mode又是跨Workspace的全局设置。
虽然无法看到Linear具体的DB Schema,但是从cookie上还是可以看出不少端倪。如截图,其实之前说的Theme设置是作为cookie存的,为了确认Theme只是存于本地cookie而没有存于服务端,我还专门在隐身(incognito)窗口用同一个用户再次登陆一下,确实发现Theme的值没有同步过来。截图上还可以看到有3个user,它们都有相同的邮箱地址,各自属于不同的Workspace(cookie里是organization字段表示)。
这样看来,本质上Account还是一个Workspace的子模型,只是在设计上通过障眼法使得用上去感觉像个顶层模型。那为什么Linear不直接把Account设计为一个顶层模型呢,毕竟这样的做法是一个更符合直觉的设计。我的猜测是考虑到隔离性,按照Linear目前的设计,只有Workspace一个顶层模型,那么数据层可以按照Workspace进行切片,每一个Workspace其实都是独立的沙箱。这个对于运维,部署,数据迁移等都有巨大的好处。举个例子,不少企业通常考虑到数据隐私安全的原因,都会要求工具进行私有云部署,虽然Linear目前还仅提供SaaS公有云服务,但是将来要把它上面的某一个Workspace迁移到私有云就比较容易,因为一个Workspace就是一个沙箱,整体迁移很容易,不会牵扯到数据的裁剪或添加。当然Account隶属于Workspace,也会带来一定的开销,一个实体用户在每一个Workspace都会有一份用户数据,这个就产生了冗余,冗余会导致不一致,也会造成操作的繁琐,比如将来如果要给用户添加MFA,SSO等功能就需要每个Workspace都配置一遍。
Workspace的子模型
为了阐述方便,先放一张叫space2的Workspace截图
Team
从之前Cookie截图中能看到,Workspace对标的是Organization组织概念,Team作为Workspace的一个子模型也就比较自然,一个Workspace可以包含多个Team,而一个Team只能属于一个Workspace。从Team设置的链接也能确认这点linear.app/<<workspace url name>>/settings/teams/<<team key>>,这里的team key类似于Jira里的project key,作为Team下Issue的前缀,如上图中展示的TEAM1。
Project
从视图上看,Project是挂在Team下面的,看上去是Team的子模型。事实上Project和Team一样是Workspace的子模型。和Team是多对多的关系。对应的URL是linear.app/<<workspace url name>>/project/<<project id>>。
截图上可以看到project22关联了2个Team,这个对应到实际场景也很合理,许多项目(Project)是由多个团队(Team)参与的。
Team的子模型
Issue
在所有的项管工具里, Issue或者有些系统里也叫Task都是最核心的模型,作为工作项的载体。在Linear里, Issue是属于Team的,并且只能属于一个Team。对应的URL是linear.app/<<workspace url name>>/issue/<<team key>> + <<issue sequential id>>/<<issue title>>。team key指定了team,issue sequential id是一个从1开始的自增序列。从链接可读性上考虑,url里也包括了issue title,但是issue的定位并不依赖这个信息。虽然URL整体是放在Workspace下面,但是因为用了team key的前缀,所以还是属于Team的。另外Issue中也可以关联子Issue。
Workflow
Workflow以当前形态看更确切的叫法应该是Workflow state/status,因为只定义了State,没有定义Transition。对应的是Issue上的Status字段。Linear在这里限定了5大类状态Backlog, Unstarted, Started, Completed, Canceled,暂时还不允许新增。而在每一个大类状态里,用户则可以自定义小类状态,有一点特殊的是Started类下,进度环会根据状态的数量自动均分。
Label
Label就是打在Issue上的标签,对应的URL是linear.app/<<workspace url name>>/team/<<team key>>/label/<<label name>>。URL下展示的是这个Team下打了这个label name的所有Issue。
Template
Template用于新建Issue时的预填模版。对应的URL是linear.app/<<workspace url name>>/team/<<team key>>/templates/<<template id>>。