
这是一个三部曲系列文章的第三部分,探讨所有初创公司都会面临的从融资路演到可用产品之间的“阻抗失配”问题。
欢迎回来。看来你是认真的。这篇文章正是为像你这样的构建者而写。你从这篇文章的第二部分中实施了哪些内容?
上次,我们讨论了如何将“分而治之”模式应用于看似难以攻克的问题:把它们拆分成大小不一、具备弹性、可复用且自成一体的模块。
今天,我们将讨论另一类情形:由于没有明显的最佳切分点,将任务切分为大小大致相等的同质化块反而更合理。
设计系统中的图标体系
在大多数早期初创公司里,搭建和强化设计系统的工作都会落到我头上。尽管设计系统中的许多工作都符合第二部分讨论过的 CDD(组件驱动开发)范式,但仍有一整类子任务需要执行无法完全自动化的重复性操作。在这种情况下,将任务切分为大小相等或相近的块,并逐块处理整个清单,是合理的做法。
这类子任务中一个显而易见的例子就是图标体系。当设计师需要调整一套“几乎到位”却尚未完美的图标集之间的失配时,他必须把这些图标一个一个地过一遍,调整尺寸、色调、描边宽度、格式等等。这时候找到一份好的歌单来让时间过得更快就显得尤为重要。
将现有基础设施转换为 IaC
我建议你从开始搭建云基础设施的那一刻起,就用代码来描述它。然而,个人经验表明,在大多数情况下,你都是从一套已有的环境开始着手的。
// 导入现有资源并逐步用新资源替换它们。
this.vpc = Vpc.fromLookup(this, 'ExistingVPC', { vpcId: 'legacy-vpc-id' });你可以把需要导入的服务拆分成若干个包,每包 n 个。然后,你就可以逐个啃下它们。这会拖慢你的进度,但要将遗留构件逐步迁移为通过 IaC(基础设施即代码)创建的构件,这是必要的。对于网络配置或 lambda 函数等无状态资源,此类迁移几乎是即时完成的;但对于数据库或用户池等有状态资源,迁移工作量会相当可观。如果你需要一个倾诉和探讨的对象,请随时联系我。
Storybook 文件
既然你的 Storybook 已经搭建完成,每个 Web 组件都会有一个包含 stories 的专用文件。如果你从零开始,请遵循完成的定义(DoD),创建一个至少包含一个基础 story 的文件。如果你接手的是一套已有的代码库,你可以投入时间进行迭代,为现有组件补充这类文件。
一个基础的 Storybook 组件文件
由此生成的交互式 story在推进过程中,我建议将库中所有组件和页面的层级结构组织成一棵与代码文件夹结构相对应的树。你希望组件在树结构中处于必要的高度,但不要更高。使用 Storybook 为组件编写文档,能够提供直观的视觉辅助,帮助你判断是否需要将某个组件下移,还是将其上提到层级更高的位置。
测试文件
既然测试框架已作为配齐必要的、与上下文无关的开发工具的一部分而搭建和配置完成,你现在就可以分批摘取一些唾手可得的成果,每批 x。
本文第一部分提到了冒烟测试和快照测试。
//...
// Smoke test
it('renders without crashing', () => {
const container = document.createElement('div');
const root = createRoot(container);
root.render(<Hint text={'Hint'} />);
});
// Snapshot test
it('renders correctly', () => {
const view = render(<Hint text={'Hint'} />);
expect(view).toMatchSnapshot();
});编写这些测试是重复性的工作,不需要深入思考。你只需为每个组件补充内容即可,无论它是一个包、一个 React 按钮,还是一个 Amazon Web Services(AWS) CDK 构件——按照你的 DoD(完成的定义)文档所述,为其添加一个额外的文件。你有多少个可测试的独立组件,就会有多少个这样的文件。逐个迭代地处理它们,并加上那几行代码即可。
分析事件追踪
Meta 以对你追踪约 50,000 个数据点而闻名。你的初创公司大概不需要追踪那么多,但你确实希望收集那些重要事件的分析数据。你不会希望从第一天起就实现五万个随意的事件。达到这种复杂程度的需求是随着成熟度而来的。
// 典型用户购物车分析。
await analyticsAddToCart({
currency,
items: products.map(({ id }) => id),
webappUserId: user.username,
value: numberOfItems,
})我经常看到的情况是,本应负责实现分析事件追踪的开发者,指望营销人员确切知道他们想要追踪哪些事件。“把你们想要的列个清单给我们,我们来排优先级,”我经常听到这样的话。除非对方是曾经在同类产品上身经百战的资深专家,否则通常并非如此。
然而,如果这样一份清单确实做出来了,你就可以把它拆分成便于管理的若干部分,并在每天或每个冲刺中交付其中一部分。
在为你的代码库覆盖事件追踪时,我建议不要想太多,从粗到细逐步推进。先局限于简单的事件,例如页面浏览量和首屏以下的滚动。然后,加入搜索查询词和会话时长。之后,你可以做得更加细致,收集购物车中的商品,以及这些商品与系统根据用户搜索意图给出的推荐之间的关联。
业务实体建模
希望本文第二部分已经说服你投入精力,通过 UML(统一建模语言)或等价方式为你的业务建模。如果你确实做出了这个明智的选择,那么现在你就需要用公司内部日常使用的业务实体来充实你的模型。有一份常用实体的清单,例如用户、查询、聊天消息等等。但毫无疑问,也会有一些特定于业务的实体。
一个基础的 UML 用例图我的建议是先从绘制 ERD(实体关系图)开始。每一个相关的业务实体都应当连同你希望随其存储的属性一并体现出来。用鸡爪表示法(chicken leg notation)将它们连接起来。
一个产品可以属于零个或多个购物车。一个购物车可以包含零个或多个产品。采用更高层次的概念性视角,而不是像数据库表那样的低层次思维方式。尽管属性被描绘为某个特定实体的一部分,但它们并不一定要在同一个数据存储中实现。这在分布式系统中尤为适用,而现代平台大多属于分布式系统。你也可以使用 RDF 或 OWL 本体约定,但那是另一个话题了。
值得你投入关注和金钱的跨操作系统建模软件并不多。我一向推荐 StarUML,因为在不花大钱的前提下,它是我能找到的最接近顶级分析软件的选择。
结论
这篇文章最初是为了避免我重复自己而写的。
确实,我曾任职过的所有公司无一例外地都在四处分散精力,试图同时构建所有东西,或者把注意力更多地放在次要事项而非核心事项上,牺牲了效率,并以次优的方式烧钱。
我并不是在指责谁。我们都会只见树木不见森林。我自己肯定也犯过这个毛病。诀窍在于足够早地察觉到它,或者把自己置于一种让这种情况发生概率变低的环境中。这正是我们使用框架的原因。它们框定了我们的工作,从而关闭了人为因素。“分而治之”只是其中之一。
如果你读到的这些内容让你觉得只是常识,那是因为它们本就是常识。大多数行之有效的东西往往简单得可笑。我没有发明任何东西。没有人在发明。相反,这是一种久经考验、行之有效的模式,借鉴自其他学科——在那些学科里,它们是完成工作的一等公民。我相信它们对你同样有效。
特别鸣谢
如果没有以下各位无比宝贵的贡献,这一系列文章将无法完成:Lilian T. 、 Farouq Aldori、Teppo Hudsson、Jarek Owczarek、Nickolay Tsybulyanko 以及 Jason Collins。


