前言
之前在社群媒體,看到有人分享 Windsurf 可以替代 Cursor,甚至做的更好。身為愛給自己找麻煩的工程師,當然不會錯過這個新玩具。
如果僅僅是簡單的讓 Windsurf 修改既有的程式,似乎無法體現它的與眾不同。所以我給自己一個挑戰: 透過 Windsurf 協助,製作克隆 Twitter。
Windsurf 是什麼
Windsurf 是由 Codeium 公司推出的一款新型集成開發環境(IDE),旨在提升開發者的編程效率。這款編輯器基於 Visual Studio Code,並整合了人工智能技術,特別適合需要高效處理複雜專案的開發者。
主要特點:
- AI 驅動:Windsurf 利用 AI 技術提供智能代碼補全、代碼生成和即時聊天功能,幫助開發者更快地編寫高質量的代碼。
- 多語言支持:它支持超過 70 種編程語言,並與多種 IDE 兼容,如 VSCode、JetBrains 和 Eclipse。
- 用戶友好:Windsurf 的界面設計直觀,適合各種技術水平的用戶,甚至非編程人員也能輕鬆上手。
- 免費使用:目前,Windsurf 的所有功能均可免費使用,未來可能會推出部分高級功能的付費選項。
Cascade 是 Windsurf 的核心組件,這是一個創新的聊天系統,結合了深度代碼理解和即時開發者行為感知。它的主要功能包括:
- 上下文感知:Cascade 能夠理解整個代碼庫的上下文,提供更準確的代碼建議和生成。
- 命令建議:系統能夠根據開發者的操作提供即時的命令建議,簡化編碼過程。
- 協作助手:Cascade 支持開發者與 AI 的實時協作,提升工作效率。
- 問題檢測與除錯:它還具備問題檢測和除錯功能,幫助開發者快速定位和解決代碼中的問題。
總的來說,Windsurf 和其核心組件 Cascade 代表了開發工具的一次重大進步,通過 AI 的輔助,開發者能夠在編碼過程中保持更高的流動性和效率。
挑戰目標
我的目的是想要體驗, Windsurf 如何幫助我的上手新事物和除錯,所以選擇了我沒那麼熟悉的語言和框架來施作:
- 後端:Golang
- 前端:Svelte, Tailwind CSS
- goal:製作 twitter (x)
準備好一個空的專案,開始向 Windsurf 發問吧。
第一問
我想要創建以 golang 為後端,Svelte/Tailwind CSS 為前端的 saas。 我想要做出我自己的 x (twitter) 頁面,請指導我
回答如下:
從回答來看,Cascade 會去試著檢查,專案是否有執行指令的條件。如果沒有,Cascade 會繼續問怎麼建立環境。
不過 Cascade 似乎沒注意到,當前的目錄已經是 similar-x
了。但是沒關係,只是小問題。
使用指令建立目錄:
值得注意的是,這裡給的終端指令,需要手動複製貼上。 雖然回應中的 Code Block 有 Insert 按鈕,但它的作用跟 Cursor 裡的一樣,只有開啟 Editor 才能插入內容。
第二問
先從後端開始吧 引導我建立後端的部分
結果如下:
看起來非常的合理
仔細看就會發現,Cascade 還是認為我目前身處在外面一層的資料夾。似乎沒有記下來,在上一次操作中,我已經移動到其他目錄下了。
執行指令,建立目錄和依賴包:
幾乎不用修改就能使用,挺準的。
不過 Cascade 似乎也不記得,同一個回應操作中,他已經帶領我建立 cmd/api
和 internal/model
目錄。猜測 Cascade 在遇到 Error 的時候,實際上會自動發起其他 Prompt 延續回答,用這種方式來做整合也挺不錯。至於記憶的問題,希望未來可以修正吧。
執行完命令後,結果如下:
第三問
我完成了,請繼續
結果如下:
這裡我注意到,Code Block 出現了新的形式:
- 點擊
Path
:在 Editor 開啟檔案。 - 點擊
Preview
:查看修改前後差異,唯讀模式。 - 點擊
Apply
:跟 Cursor 差不多。
這一次沒有太大問題,點擊 Apply
後繼續下一問。
第四問
實現數據庫連接
結果如下:
有意思的是,這次在我送出訊息後,Cascade 將之前 Apply 的檔案一起提交出去。不過它僅僅提供了 2 個檔案,它漏掉了 .env
。
另外 Cascade 又做出了冗餘的步驟。這是模型記憶的問題,我們不管它。
我注意到,上下兩個 Code Block,雖然都標註 bash 語言,但上面提供了 Insert In Terminal
,下面僅僅提供 Insert
。經過實測,上面可以直接連動到終端,下面則顯示 No active editor
。
我大膽猜測,Cascade 目前的判斷邏輯,會把多行指令的 Code Block 直接當作文件修改。我覺得多行 Insert In Terminal
會很方便,希望未來可以修正添加這個特性。
第五問
完成了,請繼續
結果如下:
這次的操作有兩個問題:
- Cascade 認為我正在修改
db.go
文件 (實際上沒有): Cascade 沒有幫我直接實現這部分程式碼。不過有提供手動複製貼上的內容。 - 確保已經安裝並運行 PostgreSQL: 目前我確實沒有運行 PostgreSQL。
既然沒有安裝,何不問問 Cascade 呢?
第六問
我的電腦還沒安裝並運行 PostgreSQL 數據庫,指導我進行這一步,並且完善數據庫設定,最好使用 docker-compose 加 .env 的方式安裝運行
結果如下:
這次有兩個問題:
-
Cascade 在第二步,並沒有如之前般,讓我
touch
檔案後,後續透過 Apply 整合插入內容。我認為這是模型的誤判,Cascade 可能以為我根目錄已經有.env
檔案,實際上並沒有。 -
使用 docker compose ,他給予的指令是舊版的
docker-compose
,然而我使用的是新版本的docker compose
。Cascade 沒有幫我檢查docker compose
指令是否存在。
看起來 Cascade 觸發檢查的機制可以在加強,檢查的判斷標準目前還看不出來。
將所有執行完,使用 DB Client 測試連線:
由於這一次,我請 Cascade 指導我安裝執行 ,跟第五問
比起來,Cascade 這次提供了運行後端應用程序來測試數據庫連接
的建議。理所當然我們來測試後端與 DB 的連線。
第七問
運行後端應用程序來測試數據庫連接
結果如下:
依照回答進行操作,依然有問題:
- 第四步,Cascade 直接複製根目錄的
.env
到 backend 目錄,這種做法很不嚴謹:在第三問的回應中,我們已經建立過 backend 目錄裡的.env
檔。
所以我們需要比較兩者的差異:
看起來格式大同小異,除了值的內容有變,僅僅是 UPLOAD_DIR
這個 key 被移除掉,但現在我們用不到,那就放心大膽的覆蓋過去。
- 第五步,執行後發生錯誤:
1~/similar-x/backend/cmd/api$ go run main.go2../../../../go/pkg/mod/github.com/jackc/puddle/v2@v2.2.1/pool.go:142:30: undefined: atomic.Int643note: module requires Go 1.194---5$ go version6go version go1.18.1 linux/amd64
原來是我的 go 版本太舊了,Cascade 依然沒有幫忙檢查,可惜了。
這次不提問,使用以下指令更新:
1# 使用 snap 安裝新版 golang2sudo snap install go --classic3# 移除 apt 安裝的舊版 golang4sudo apt remove golang-go
再執行一次 api/main.go
:
1$ go run main.go22024/11/22 01:47:44 Warning: .env file not found3
42024/11/22 01:47:44 /home/vinny987/similar-x/backend/internal/database/db.go:165[error] failed to initialize database, got error failed to connect to `host=localhost user=postgres database=`: failed SASL auth (FATAL: password authentication failed for user "postgres" (SQLSTATE 28P01))62024/11/22 01:47:44 Failed to connect to database:failed to connect to `host=localhost user=postgres database=`: failed SASL auth (FATAL: password authentication failed for user "postgres" (SQLSTATE 28P01))7exit status 1
.env
找不到,其實只要到 go 根目錄執行檔案就解決了。不過就利用這個機會,來考驗 Cascade 的除錯能力。
第八問
執行 go run main.go 看起來 .env file not found ,為什麼
結果如下:
本次開始,出現明顯的問題:
- 第一步,點擊
Preview
或Apply
按鈕會出現無反應或內容錯誤,錯誤提示:
照著 Reddit 的網友分享的解法,開啟右下角的 Write
功能後,依然不可用:
看來這應該是 Windsurf 的 Bug 了,希望作者們早日修復吧。
只好用最笨的方法 - 手動比較
:
回答內容,Cascade 使用了遞迴來讀取 .env
檔案,老實說蠻蠢的。
使用另一個方法: 回到 backend
根目錄執行 cmd/api/main.go
:
1~/similar-x/backend$ go run cmd/api/main.go22024/11/22 02:23:05 Database connected successfully3
42024/11/22 02:23:05 /home/vinny987/similar-x/backend/cmd/api/main.go:275[13.305ms] [rows:1] SELECT count(*) FROM information_schema.tables WHERE table_schema = CURRENT_SCHEMA() AND table_name = 'users' AND table_type = 'BASE TABLE'6
72024/11/22 02:23:05 /home/vinny987/similar-x/backend/cmd/api/main.go:278[11.058ms] [rows:0] CREATE TABLE "users" ("id" bigserial,"created_at" timestamptz,"updated_at" timestamptz,"deleted_at" timestamptz,"username" varchar(50),"email" varchar(100),"password" varchar(100),"display_name" varchar(100),"bio" varchar(500),"profile_image" varchar(255),PRIMARY KEY ("id"))9
10[...]11
12[GIN-debug] GET /health --> main.main.func1 (3 handlers)13[GIN-debug] POST /api/v1/users/register --> (3 handlers)14[GIN-debug] POST /api/v1/users/login --> (3 handlers)15[GIN-debug] POST /api/v1/tweets --> (3 handlers)10 collapsed lines
16[GIN-debug] GET /api/v1/tweets --> (3 handlers)17[GIN-debug] GET /api/v1/tweets/:id --> (3 handlers)18[GIN-debug] DELETE /api/v1/tweets/:id --> (3 handlers)19[GIN-debug] GET /api/v1/users/:id --> (3 handlers)20[GIN-debug] PUT /api/v1/users/:id --> (3 handlers)21[GIN-debug] POST /api/v1/users/:id/follow --> (3 handlers)22[GIN-debug] DELETE /api/v1/users/:id/follow --> (3 handlers)23[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.24Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.25[GIN-debug] Listening and serving HTTP on :8080
執行成功了。看 log 的資料,看起來它自動幫我們建立了一些 table 的結構。
稍微看了程式碼,原來是 gorm migration 的功能。
gorm - migration 的文件是這樣說的:
NOTE: AutoMigrate will create tables, missing foreign keys, constraints, columns and indexes. It will change existing column’s type if its size, precision changed, or if it’s changing from non-nullable to nullable. It WON’T delete unused columns to protect your data.
雖然很方便,但它是無法支持複雜的場景、沒有版本控制,且可能帶來資料丟失的風險。在正式環境或大型項目,應該避免使用這種特性。
結論
透過 Windsurf 的幫助,目前我完成了目錄建立、DB 安裝運行和後端與 DB 的連動。剩下的內容,在下一篇繼續跟大家分享。
另外,從我操作的過程中可以看出,Windsurf 的確在 Cursor 的基礎上,添加的全新的特性,讓這個程式助手變得更好用,但它依然還是保有 GenAI 常見的缺陷,以及不少的 Bug。如果這個 IDE 可以保持穩定更新,並且修復上述提到的問題,我會很願意跳槽到 Windsurf。