Shutting Down Fornjot

Shutting Down Fornjot

终止 Fornjot 项目

Fornjot is ending; unfinished, incomplete. This is not what I wanted, not why I started this project. But it is the decision I have made. For a while now, Fornjot’s development has been happening on the side, next to other work that filled most of my day. This became unsustainable, and I addressed that by serializing my efforts: focus on one project at a time until I reach a good point to pause, then switch to the next one. Ironically, these improved conditions led to my decision to quit. Once it was Fornjot’s turn, I made better progress than I could before. As a result, for the first time in a while, I was able to get my head above water and take in the bigger picture, understand where things were going. That’s when I realized I had to quit.

Fornjot 即将终结;它尚未完成,也不够完整。这不是我想要的,也不是我启动这个项目的初衷。但我还是做出了这个决定。一段时间以来,Fornjot 的开发一直是在业余时间进行的,与我日常大部分工作并行。这变得难以为继,于是我通过“串行化”工作来解决:一次只专注于一个项目,直到达到一个合适的暂停点,然后再切换到下一个。讽刺的是,正是这些改善后的条件促使我决定放弃。当轮到 Fornjot 时,我取得了比以往更好的进展。结果,我终于在很长一段时间里第一次能够喘口气,审视全局,看清事态的发展方向。就在那时,我意识到我必须放弃。

My work was supported by sponsors. I couldn’t justify taking their money, if I didn’t believe that I was on a path to create something meaningfully different (and thus in some ways better) than what’s already available. It became clear to me that under current conditions, it would have easily taken another 2-3 years to put the foundation in place to even start delivering such value. After already being at it for almost 6 years, I realized that I couldn’t commit to that. It’s too much. I no longer have it in me. (Before writing this, I sent a private announcement to my sponsors, in which I stated that I had been working on Fornjot for about 5 years, not 6. Which is what I believed at the time, but I just checked, and it turns out the first commit to the Fornjot repository happened on July 30, 2020.)

我的工作得到了赞助商的支持。如果我不相信自己正走在创造出某种有意义的差异化(从而在某些方面优于现有产品)的道路上,我就无法心安理得地接受他们的资金。我清楚地意识到,在当前条件下,至少还需要 2 到 3 年的时间才能打好基础,从而开始提供这种价值。在已经投入了近 6 年之后,我意识到我无法再做出这样的承诺。这负担太重了,我已力不从心。(在写这篇文章之前,我向赞助商发送了一份私人公告,称我从事 Fornjot 工作大约 5 年,而不是 6 年。当时我是这么认为的,但我刚刚核实了一下,结果发现 Fornjot 仓库的第一次提交发生在 2020 年 7 月 30 日。)

Mistakes I Made

我犯下的错误

Six years without even delivering something useful; it’s not a good look. CAD kernels are notoriously difficult, but that’s only a partial excuse. I made many mistakes along the way. In this section, I want to reflect on those mistakes. Maybe we can learn from them.

六年时间却没能交付任何有用的东西,这看起来确实不太好。CAD 内核以难度极高著称,但这只是部分借口。我在过程中犯了很多错误。在这一节中,我想反思这些错误。也许我们可以从中吸取教训。

Extrapolating from Early Success When I started working on Fornjot, it was a departure from my earlier experiments with CAD, which had been based on signed distance fields. When I switched to boundary representation, that showed promise, and I expected linear progress from there. That linear progress never materialized. Instead, I ran into a cliff. Discovering in so many different ways why CAD kernels, specifically b-rep kernels, are considered hard.

从早期成功中过度推断 当我开始开发 Fornjot 时,它与我早期基于符号距离场(signed distance fields)的 CAD 实验有所不同。当我转向边界表示法(boundary representation)时,它展现出了前景,我期望从此能取得线性的进展。但这种线性进展从未实现。相反,我撞上了一堵墙,以各种不同的方式发现了为什么 CAD 内核(特别是 b-rep 内核)被认为如此困难。

Seeking Sponsorship Too Early Starting in 2022, I became more serious about Fornjot. Opening issues and pull requests to make progress easier to follow, instead of pushing to main directly. Creating a website, publishing regular releases, writing release announcements. And seeking sponsorship. It worked. The growth in sponsorship enabled everything that followed. If the project ever had a chance to succeed, it was because of that. And yet, I wouldn’t do it again; not like this. I was still on my way towards creating something useful. Instead of selling a product, I had sold a dream. That wasn’t my intention. I had been expecting linear progress towards a useful tool, but then never got there. And it gnawed on me for all these years. I mean, I managed. But still, I didn’t like it. I don’t intend to ever sell a dream again, at least not without an actual product to deliver alongside.

过早寻求赞助 从 2022 年开始,我开始认真对待 Fornjot。我开始通过开启 issue 和 pull request 来让进展更易于追踪,而不是直接推送到主分支。我创建了网站,发布定期版本,撰写发布公告,并寻求赞助。这奏效了。赞助的增长促成了后来的一切。如果这个项目曾经有过成功的机会,那也是因为这一点。然而,我不会再这样做;至少不会以这种方式。我当时还在通往创造有用工具的路上。我卖掉的不是产品,而是一个梦想。这并非我的本意。我一直期待着向一个有用的工具取得线性进展,但最终没能实现。这些年来,这一直折磨着我。我的意思是,我确实应付过来了,但我仍然不喜欢这样。我打算以后再也不卖梦想了,至少在没有实际产品可以交付的情况下不会再这样做。

Sticking to Incremental Improvements As I tried to scale that cliff I had run into, I limited myself to incremental improvements. Those had always served me well, while big rewrites had only ever been a distraction. Born from my yearning to replace a messy situation with a clean slate, without ever solving the underlying problems. But both attitudes are extremes. There’s fertile ground in between. Instead of convincing myself that a new idea was promising, then spending a long time implementing it in small steps, I should have been prototyping. All the time. Only then integrating, incrementally or not, what proved valuable.

坚持增量改进 当我试图攀登那座我撞上的悬崖时,我将自己局限于增量改进。这些方法过去一直对我很有帮助,而大规模重写往往只会分散注意力。这种重写源于我渴望用一张白纸取代混乱局面的愿望,却从未解决根本问题。但这两种态度都是极端的。在两者之间存在着肥沃的土壤。我不应该说服自己某个新想法很有前景,然后花很长时间分小步去实现它,而应该一直进行原型设计。始终如此。只有在确定有价值之后,再将其整合进来,无论是否采用增量方式。

Responding to Crisis with Half-Measures My sponsorship income had reached a sustainable level for the first time some months into 2022, due to a single, very generous sponsor. When they didn’t renew in 2023, that left a large gap. A similar thing happened in 2024. Both times I thought that sponsorship income was unlikely to recover, yet both times existing sponsors stepped up to close the gap. But there were delays between drop and recovery, which gave room for mistakes. The first time, it broke the spell. Dissolved that image in my head, of Fornjot as the only thing I needed to do. The second time, I decided I needed to double down on diversifying and reduced Fornjot to a side project. A side project I absolutely wanted to still finish. But my life’s work became something else. And that was my biggest mistake. Each time, I had exactly two reasonable options: continue with full commitment or quit right then and there. I did neither. And if I had to trace back the project’s failure to a single cause, that would be it.

以半吊子措施应对危机 2022 年年中,由于一位非常慷慨的赞助商,我的赞助收入首次达到了可持续的水平。当他们在 2023 年没有续约时,留下了一个巨大的缺口。2024 年也发生了类似的情况。两次我都认为赞助收入不太可能恢复,但两次都有现有的赞助商挺身而出填补了缺口。但在收入下降和恢复之间存在延迟,这给了犯错的空间。第一次,它打破了魔咒,消除了我脑海中“Fornjot 是我唯一需要做的事情”的幻象。第二次,我决定必须加倍努力实现多元化,并将 Fornjot 降级为一个副业项目。这是一个我绝对想完成的副业,但我的毕生事业变成了别的东西。这就是我最大的错误。每次,我都有两个合理的选择:全力以赴继续,或者当场放弃。我两者都没做。如果我必须将项目的失败归结为一个原因,那就是这个。

Allowing My Vision to Become Muddled The initial goal of Fornjot was to build a code-first CAD application, which included a custom CAD kernel. Reacting to that first drop in income, I decided to cut the application and focus on the kernel only. In a way, this was good. It removed many moving parts, which simplified the project significantly. But overall, I still think it was a mistake. An application can be focused. A CAD kernel is a generic piece of infrastructure, with many use cases to consider. At least that’s how I felt about it at the time. And this muddled my vision (though it recovered somewhat, as time went on). I should have thought more outside of the box, should have ditched those categories. Something can be a kernel, a library, but still focus on specific use cases. Be a tool instead of a building block. (And building an application on top of an existing kernel was an option that never appealed to me.)

让愿景变得模糊 Fornjot 的最初目标是构建一个代码优先的 CAD 应用程序,其中包括一个自定义的 CAD 内核。为了应对第一次收入下降,我决定砍掉应用程序,只专注于内核。从某种程度上说,这是好的。它移除了许多变动的部分,极大地简化了项目。但总的来说,我仍然认为这是一个错误。应用程序可以有明确的重点,而 CAD 内核是一个通用的基础设施,需要考虑许多用例。至少当时我是这么觉得的。这模糊了我的愿景(尽管随着时间的推移,它有所恢复)。我本应该跳出思维定式,抛弃那些分类。一个东西既可以是内核,也可以是库,但仍然可以专注于特定的用例。成为一个工具,而不是一个积木。(而且在现有内核之上构建应用程序,这个选项从未吸引过我。)

Prototyping Came Too Late I eventually realized that exclusively sticking to incremental improvements was a mistake. I had maneuvered the codebase into a transitionary state, halfway between an old approach…

原型设计来得太晚 我最终意识到,仅仅坚持增量改进是一个错误。我已将代码库推向了一种过渡状态,处于旧方法和新方法之间……