2025年12月14日 星期日

Github-Copilot-7-分析整個專案架構

Github-Copilot-7-分析整個專案架構

身為程式設計師,理所當然的會經常收到新的專案需求,從無到有的進行一個新系統的開發工作,這是相當有趣且充滿挑戰的工作,然而,更多時候,程式設計師並不是從無到有的開始一個新系統的開發工作,而是接手一個已經存在的系統,這個系統可能已經歷經多年開發與維護,程式碼量龐大且複雜,對於新進的程式設計師來說,要快速理解整個系統的架構與運作方式,是一項艱鉅的任務。

面對收到一個指示,需要要來維護現有的系統,然而,你當初卻沒有參與過這個專案,並且收到需要在這個專案系統中,需要進行問題除錯或者要加入一個新的需求或功能,也有可能只收到這個系統的專案原始碼,並且沒有任何說明文件或者可供參考的資料。

面對這樣的情況,應該絕大多數的人,都會無從下手,對於資深人員有可能憑藉著他之前累積的經驗與知識,給他足夠的時間,也許有機會慢慢地探索與理解,分解出這個系統的架構,找出如何解決現在提報的錯誤或者把新的需求新增進去。可以,絕大多數時候,並不是每個程式設計師都這麼的厲害,面對著這樣的情況,如何能夠讓一般人員甚至新手小白,也能夠快速理解整個系統的架構與運作方式,這是相當重要的課題。

若現有系統地原有開發或者維護人員還在組織內,當檢視程式碼的時候,可以直接詢問這些原有的開發或者維護人員,這樣的方式雖然直接且有效率,但是,若這些原有的開發或者維護人員已經離職或者轉調他單位,這時候就只能靠自己檢視程式碼來理解整個系統的架構與運作方式。

在這裡,同樣的使用我這一年所開發的一個專案,如下面節圖,先不說明這是一個甚麼專案,看看能否透過 Github Copilot 的協助,來快速理解這個專案的架構與運作方式。

以 Github Copilot 分析專案架構

  • 首先開啟這個專案,切換到 [Github Copilot 聊天] 視窗內
  • 在該視窗左上方點選 [建立新執行緒] 按鈕
  • 在下面聊天面板中,輸入這個 Prompt 指令,並且按下 Enter 鍵
#solution 我是一個尚未接觸過這個系統開發的人員,需要進行來維護與找出一個錯誤問題,並且進行修正,首先,我需要了解這是一個甚麼系統,請分析出這個方案內的所有專案,說明這個系統是甚麼,提供了甚麼功能。

請使用最簡潔、清爽的方式呈現需要內容,讓人可以用快、容易閱讀為主

在這裡使用 #solution 標籤,讓 Github Copilot 知道這是一個針對整個方案的需求,緊接其後,輸入這次的需求的提示文字內容,在這裡,稍後因為要將結果貼到這個部落格文章上,因此,希望以簡潔的方式產出內容,了解這樣的操作效果;若為正常操作過程,可以要求 AI 產生出更詳細的說明與分析內容。

另外,在 [Github Copilot 聊天] 視窗內,可以看到這裡使用兩個參考來源,一個是 [使用中文件],另外一個是 [#solution],這表示這次的需求是參考這兩個來源來進行分析與說明。所以,在這裡將會從這個 [ProjectAssistant.Web] 啟動專案內,找到並且開啟 [Program.cs] 檔案。

也可以使用 #project 標籤,來針對某一個專案進行分析與說明,這樣的方式,可以讓程式設計師更聚焦在某一個專案內,來了解該專案的內容與功能。

底下將會是完整的畫面截圖

檢視 Copilot 生成結果

從 [Github Copilot 聊天] 視窗內,參考下圖,可以看到這次的 Prompt 送達到 AI 之後,實際上有去參考這個方案的其他檔案內容,另外,在這個方案內,其實並沒有人關於 Readme 的文件,來說明這個方案是做甚麼用的,因此,這次的測試結果若符合預期,這就表示 [Github Copilot 聊天] 功能,真的有去閱讀與分析這個方案內的內容,並且產生出相當不錯的說明內容。

底下為 [Github Copilot 聊天] 產生內容

從這個內容敘述,AI 能夠相當清楚地說明這個系統的名稱是甚麼,並且說明這個系統的主要功能,另外,也能夠說明這個方案內的各個專案的用途與功能,對於一個新進的程式設計師來說,這樣的資訊已經足夠讓他快速理解整個系統的架構與運作方式,接下來,就可以針對這些專案內的類別與程式碼,進行更深入的了解與分析。

因此,就算是一個資淺或者小白,也可以透過這樣的方式,了解到這個系統的架構與運作方式,進而能夠有效率地進行維護與開發工作,這對於提升團隊的生產力與協作效率,有著相當大的幫助。


這個系統大概是什麼?

系統名稱(從 Repo):MeetingMinutes / ProjectAssistant
型態

  • 後端:ASP.NET Core + EF Core + SQLite
  • 前端:Blazor Server(ProjectAssistant.Web
  • 另有一個 React 專案資料夾 Src-React(看起來是另外一套或舊版前端)
  • 使用 Ant Design Blazor 來做 UI 元件
  • 支援 JWT + Cookie 雙模式認證
  • 內建 Swagger / OpenAPI 供 REST API 測試與整合
  • 使用 FFmpeg + 語音轉文字服務(SpeechToText)處理錄音檔

核心領域(從專案與類別命名推論):

  • 專案管理(ProjectMyTaskGanttChartRepository
  • 會議管理與會議紀錄(MeetingMeetingRepositoryRecordedMediaFileRepository
  • 錄音 / 媒體檔管理 + 語音轉文字(RecordedMediaFileSpeechToTextService
  • 使用者與角色權限管理(MyUserRoleViewBuildPermissionJsonHelper 等)

可以先把它想成:

一個「專案 + 會議 + 任務」管理系統,
支援錄音上傳,伺服器用 FFmpeg 轉檔,再透過 Speech-to-Text 服務把錄音轉成文字,
前端是 Blazor Server,部分功能另有 React 前端。

AI 產出的 實際分析結果

先用「整體 → 各專案 → 主要功能」的方式,幫你快速建立腦中地圖。


一、這個系統大概是什麼?

系統名稱(從 Repo):MeetingMinutes / ProjectAssistant
型態

  • 後端:ASP.NET Core + EF Core + SQLite
  • 前端:Blazor Server(ProjectAssistant.Web
  • 另有一個 React 專案資料夾 Src-React(看起來是另外一套或舊版前端)
  • 使用 Ant Design Blazor 來做 UI 元件
  • 支援 JWT + Cookie 雙模式認證
  • 內建 Swagger / OpenAPI 供 REST API 測試與整合
  • 使用 FFmpeg + 語音轉文字服務(SpeechToText)處理錄音檔

核心領域(從專案與類別命名推論):

  • 專案管理(ProjectMyTaskGanttChartRepository
  • 會議管理與會議紀錄(MeetingMeetingRepositoryRecordedMediaFileRepository
  • 錄音 / 媒體檔管理 + 語音轉文字(RecordedMediaFileSpeechToTextService
  • 使用者與角色權限管理(MyUserRoleViewBuildPermissionJsonHelper 等)

可以先把它想成:

一個「專案 + 會議 + 任務」管理系統,
支援錄音上傳,伺服器用 FFmpeg 轉檔,再透過 Speech-to-Text 服務把錄音轉成文字,
前端是 Blazor Server,部分功能另有 React 前端。


二、方案內主要專案結構(從命名與引用推論)

1. ProjectAssistant.Web(Blazor 前端 + Web API Host)

用途:整個系統的 Web 入口 + Blazor UI + REST API Host

關鍵點(從 Program.cs 與 App.razor):

  • 啟用 Blazor Server:
    • builder.Services.AddRazorComponents().AddInteractiveServerComponents();
    • App.razor 使用 <Routes @rendermode="InteractiveServer" />
  • UI:
    • 使用 Ant Design Blazor(builder.Services.AddAntDesign();
  • 認證與安全:
    • Cookie + JWT 雙模式認證(AddAuthentication().AddCookie().AddJwtBearer(...)
    • 從 SystemSettings.JwtTokens 讀取 Issuer / Audience / SigningKey
  • 資料庫:
    • AddDbContext<BackendDBContext>(options => options.UseSqlite(SQLiteDefaultConnection))
  • Swagger / OpenAPI:
    • AddOpenApi()AddSwaggerGen(...)app.UseSwagger(); app.UseSwaggerUI();
  • CORS:
    • AllowReactApp,允許任意 Origin/Header/Method(為 React 前端使用)
  • 上傳與大檔處理:
    • Kestrel MaxRequestBodySize 設為 4GB
    • FormOptions.MultipartBodyLengthLimit 也設為 4GB
  • 系統服務註冊(部分):
    • SystemSettingsConfigurationServiceDataFolderHelper
    • SpeechToTextServiceFFmpegDownloaderConverAudioHelper
    • BuildPermissionJsonHelper
    • ViewModel / Repository / Service 都在這裡註冊 DI
  • 啟動流程:
    • 初始化資料資料夾(DataFolderHelper.Initialize(); CheckAndCreateDataFolders();
    • 準備 FFmpeg & 語音服務(speechToTextService.InitializeAsync()
    • 自動執行 EF Core Migration(dbContext.Database.Migrate();

→ 你在維護錯誤時,Program.cs 是整個管線與服務注入的總入口


2. ProjectAssistant.Business(商業邏輯層)

用途:封裝商業邏輯與 Repository。

已看到的類別:

  • MeetingRepository
    • 會議 CRUD + 分頁查詢 + 關鍵字搜尋 + 依欄位排序
  • GanttChartRepository
    • 與專案甘特圖相關的資料存取
  • ProjectRepository
    • 專案的 CRUD / 查詢
  • PromptSetRepositoryChatHistoryRepository
    • 可能與 AI 提示 / 對話紀錄有關
  • MyTaskRepository
    • 任務相關 CRUD
  • RecordedMediaFileRepository
    • 錄音 / 媒體檔相關 CRUD
  • RoleViewRepositoryMyUserRepository
    • 使用者與角色、權限相關
  • 服務類別:
    • SpeechToTextService
      • 包裝語音轉文字流程,啟動時會 InitializeAsync();多半會呼叫外部 STT 服務(或本地 AI 模型)
    • SystemSettingsConfigurationService
      • 管理 SystemSettings 的設定
    • BuildPermissionJsonHelper
      • 構建權限 JSON 給前端/系統使用
    • FFmpegDownloaderConverAudioHelper
      • 負責下載 / 檢查 FFmpeg、媒體檔轉檔(例如把錄音轉成 STT 可接受格式)

→ 所有比較「系統行為 / 功能規則」類的問題,多半在這個專案找。


3. ProjectAssistant.EntityModel(資料庫實體與 DbContext)

用途:

  • EF Core DbContextBackendDBContext
  • 所有資料表實體,例如:
    • Project
    • Meeting
    • MyTask
    • RecordedMediaFile
    • MyUser 等
  • Migrations 目錄(例:20251028080937_Init.cs
    • 定義資料表欄位、關聯

→ 如果錯誤訊息與資料欄位、外鍵、Migration 有關,來這個專案查實體與 Migration。


4. ProjectAssistant.DataModel(Adapter / 設定模型)

用途:

  • Adapter Models(把 Entity 轉成前端使用的模型)
    • ProjectAdapterModel
    • MeetingAdapterModel
    • RecordedMediaFileAdapterModel
  • 設定類別(強型別設定)
    • SystemSettings(在 Program.cs 中透過 builder.Configuration.GetSection(nameof(SystemSettings)) 載入)
      • 裡面包含 JWT 設定、連線字串、可能還有語音服務、檔案路徑等

→ 系統設定(appsettings.json → SystemSettings)以及 API 回傳模型的中介結構,多在這裡。


5. ProjectAssistant.Dto(API 用 DTO)

用途:

  • 傳輸物件(Request / Response)
    • 例如 MyUserDtoProjectCreateUpdateDtoMeetingSearchRequestDto 等
  • ApiResult<T> 這類通用傳回格式
    • Program.cs 內 JWT 失敗時有建立 ApiResult<object> 回傳

→ Controller / API 看到的輸入輸出類型,多數在這裡。


6. ProjectAssistant.Share(共用工具 / Enum)

用途:

  • 共用 Enum / 常數 / Helper
    • 例:ProjectAssistant.Share.Enums 在 MeetingRepository 有被使用
    • MagicObjectHelper(定義 Cookie / JWT Scheme 名稱等)

→ 多個專案共用的東西,優先來這裡找。


7. Src-React(React 前端)

路徑:Src-React\src\components\...

  • 有 ProjectDashboardMeetingMinutes 等元件
  • 透過 CORS Policy AllowReactApp 與後端溝通
  • 看起來是:
    • 舊版 Web 前端、或
    • 另一個給特定使用者使用的前端

→ 目前你主要維護的是 Blazor ProjectAssistant.Web;若錯誤來自 React 畫面,才需要進到這個資料夾。


三、這個系統提供的主要功能(彙整)

從類別與 Repository 名稱,整理出大致功能清單:

  1. 專案管理

    • 建立 / 修改 / 刪除專案 (ProjectRepositoryProjectViewModelProjectController)
    • 顯示專案清單、總覽(React 的 ProjectDashboard + Blazor 專案頁面)
    • 與任務、會議、甘特圖關聯
  2. 任務(MyTask)與甘特圖管理

    • 任務 CRUD
    • 以甘特圖方式呈現專案排程(GanttChartRepository
  3. 會議與會議紀錄

    • 會議 CRUD(MeetingRepository
    • 搜尋 / 分頁 / 依建立時間、更新時間排序
    • 每個會議底下可有錄音 / 媒體檔(RecordedMediaFileRepository
  4. 錄音檔 / 媒體管理與語音轉文字

    • 大檔上傳(4GB 上限)
    • 伺服器用 FFmpeg 轉檔(FFmpegDownloaderConverAudioHelper
    • 呼叫 SpeechToTextService 把錄音轉為文字
    • 可能把轉換後的文字關聯到對應會議,作為會議紀錄或摘要
  5. 使用者與權限管理

    • 使用者資料(MyUserMyUserRepositoryMyUserServiceMyUserDto
    • 角色 / 視圖權限(RoleViewRepositoryRoleViewServiceBuildPermissionJsonHelper
    • 使用 JWT + Cookie 實作登入 / API 授權
  6. API 與外部整合

    • REST API + Swagger(AddControllersAddSwaggerGenapp.UseSwaggerUI()
    • JSON Enum 輸出為字串、處理循環參考
    • CORS 允許 React 前端存取

四、如果你要開始找「錯誤」建議的閱讀順序

  1. 先開 Docs 資料夾下的需求 / User Story(如果你有權限讀)

    • 例如 ProjectPlanUserStory.md(目前工具讀不到,但在檔案系統下應該存在),了解功能定位與名詞定義。
  2. 再看前端路由 / 頁面

    • Blazor:ProjectAssistant.Web\ComponentsViewModels
    • React(如果錯誤來自 React):Src-React\src\components\...
  3. 對應的 Web API

    • ProjectAssistant.Web\Controllers\XXXController.cs
  4. 到底層 Repository / Service

    • ProjectAssistant.Business\Repositories\...
    • ProjectAssistant.Business\Services\...
  5. 若是資料庫異常

    • ProjectAssistant.EntityModel 的實體與 Migrations

如果你接下來能提供「具體錯誤訊息 / 畫面路徑 / API URL」,我可以幫你一步一步沿著上述結構精準定位到可能出錯的類別與程式碼位置,並一起修正。 



Github Copilot 6 : 為程式碼自動加入註解

Github Copilot 6 : 為程式碼自動加入註解

適度的在程式碼中加入適當的註解,將會有助於日後專案維護的效率,雖然,有很多人不贊同在程式碼中加入過多的註解,不過,有些時候,適當的加入程式碼註解,將會有助於整體專案的理解。

這是一個 AI 影響性中心的臨床試驗平台的專案,需要將癌症治療與AI輔助分析進行整合,並且要收集不同週期的各種治療、抽血、問卷的數據,最重要的是,這些都是關於醫療方面的項目,對於像是我們這樣的程式設計人員,這些名稱其實對於我們並沒有受過這樣的專業訓練,因此,程式碼中充斥著這些醫學名詞,特別是在 Data Model 的定義上,首先,面對到的是如何取個適當的屬性名稱,最重要的是日後看到這個名稱,能夠與畫面上的欄位結合起來,畢竟,我這裡設計的畫面語系是中文文字。

例如底下這個類別 [臨床資料手術Node] 是一個要記錄臨床手術相關內容的類別,各個欄位的名稱來自於醫師提供的,並且要對應到畫面上

public class 臨床資料手術Node
{
    public VisitCodeModel VisitCode { get; set; }=new();
    public string SubjectNo { get; set; }
    public DateTime 手術日期 { get; set; }
    public string 術式 { get; set; }
    public string OPOutcome { get; set; }
    public string Ascites { get; set; }
    public string Uterus { get; set; }
    public string UterusSite { get; set; }
    public string UterusTumorNumber { get; set; }
    public string UterusTumorSize { get; set; }
    public string Cervix { get; set; }
    public string CervixSite { get; set; }
    public string CervixTumorNumber { get; set; }
    public string Endometrium { get; set; }
    public string Myometrium { get; set; }
    public string CulDeSac { get; set; }
    public string OvarianSurfaceRuptureOrNotRightOvary { get; set; }
    public string OvarianSurfaceRuptureOrNotLeftOvary { get; set; }
    public string LeftAdnexa { get; set; }
    public string LeftAdnexaTumorNumber { get; set; }
    public string LeftAdnexaTumorSize { get; set; }
    public string RightAdnexa { get; set; }
    public string RightAdnexaTumorNumber { get; set; }
    public string RightAdnexaTumorSize { get; set; }
    public string PelvicPeritonealCavity { get; set; }
    public string PelvicPeritonealCavityTumorSize { get; set; }
    public string ExtrapelvicPeritonealCavity { get; set; }
    public string ExtrapelvicPeritonealCavityOtherFinding { get; set; }
    public string OtherOrganInvolvementGrossLooking { get; set; }
    public string Optimal { get; set; }
    public string ResidualTumor { get; set; }

}

另外,若這個類別將會用於 Web API 上的使用,並且這些資訊要能夠讓使用 Swagger 的前端人員,知道這些欄位的意義與用法,此時,也需要適當的加入 xml 註解,如此,這些資訊可以在 Swagger 上呈現出來,因此,如何快速、有效與方便的建立起這些註解資訊,並且不會造成負擔,就是這篇文章想要表達的。

為 臨床資料手術Node 加入註解

在以往想要為一個類別內的不同屬性加入這些 XML 註解,這是一個相當具大與浪費時間的工作,也考驗著程式設計人員的耐心,很多人因為習慣或者偷懶,不會想要去做這些的工作,可是,一旦這些註解存在之後,除了可以在 Swagger 中讓前端人員快速理解傳遞參數的欄位意義,並且對於在日常維護工作上,也會有相當的益處,例如,當看到一段程式碼,如下圖

當看到這個欄位 [MenstrualStatus] 究竟是甚麼意思,這個欄位的型別為字串,當要看到該欄位值的時候,其為 0 或者 1 ,這又分別代表甚麼意思呢?

此時,若該資料模型欄位有使用 xml 註解,僅需要將游標移動到該欄位上,VS 2026 就會彈跳出一個小視窗,說明這是一個關於紀錄月經狀態,其數值將會有兩種狀態,分別是 0:停經 1:未停經;看到這些訊息是不是瞬間對於這段程式碼的內容更加清晰了呢?

  • 現在,打開 [臨床資料手術Node.cs] 這個檔案,這個檔案定義了 [臨床資料手術Node] 資料模型的類別,內容在上面已經有顯示出來。
  • 切換到 [Github Copilot 聊天] 視窗內
  • 在該視窗左上方點選 [建立新執行緒] 按鈕
  • 在下面聊天面板中,輸入這個 Prompt 指令,並且按下 Enter 鍵
加入xml註解
  • 雖然這個 Prompt 內容簡單又清爽,但是對於這個情境卻絲毫不會有任何影響
  • 等待 Github Copilot 完成生成之後,將會看到底下截圖 
  • 點選 [臨床資料手術Node.cs] 生成結果右上方的套用按鈕
  • 直接將生成結過套用到原始 [臨床資料手術Node.cs] 檔案中
  • 這是尚未套用前的畫面 
  • [臨床資料手術Node.cs] 視窗內,按下多次 [Tab] 按鍵,完成套用程序
  • 這是套用之後的畫面 
  • 可以看到,原本沒有任何註解的程式碼,已經被自動加入了完整的 xml 註解

 




Github Copilot 5 : 程式碼自動完成輔助

 

Github Copilot 5 : 程式碼自動完成輔助

在這一篇文章,將會來分享我在使用 Github Copilot 的自動程式碼輔助生成的經驗。這是一個關於醫院的運動員儀表板的專案開發,在這個專案中,我會示範如何利用 Github Copilot 來協助完成一些程式碼的撰寫工作,並且展示這些功能如何提升開發效率。

該系統將會透過 Excel 檔案來提供身體組成與其他相關數據,其中有些數據則需要從不同的 Sheet 內的不同 cell 來進行計算而得到,其公式如下圖所示:

這些數據將會透過 Blazor 頁面來進行顯示,並且這類型的專案通常需要撰寫大量的程式碼來處理資料的讀取、計算以及顯示等工作,一旦在程式碼中的公式撰寫錯誤,或者指定錯誤 cell 來源,將會造成整體呈現的數據失真。

另外,一旦需要進行功能的擴充,或者是修改計算公式時,也需要花費大量的時間來進行程式碼的調整與測試。

這個專案採用了 MVP 的方式來進行開發,所以,能夠快速與準確的撰寫程式碼是非常重要的任務。

透過 Github Copilot 的協助,我能夠更快速地完成這些任務,並且減少了手動撰寫程式碼的時間。

以下是我在這個專案中使用 Github Copilot 的一些範例:

對於讀取 Excel 檔案內容的部分,這裡採用的是 Syncfusion.XlsIO 套件來進行 Excel 檔案的讀取工作,以下是我使用 Copilot 來協助完成讀取 Excel 檔案的程式碼:

IWorksheet worksheetCT身體組成 = workbook
            .Worksheets[MagicObjectHelper.CT身體組成原始擋20241212WorkSheetName];

根據螢幕截圖,對於 健康肌肉比 的計算公式,為 S13/(I13+N13+S13)

首先,將這段註解寫到程式碼中

// 健康肌肉比 的計算公式,為 S13/(I13+N13+S13)

接著,使用 Copilot 來協助完成程式碼的撰寫

在該註解寫完之後,按下 Enter 按鍵,Copilot 會自動建議以下的程式碼:

var MuscleQuality肌肉品質 = healthManagementModel.BodyMuscleQuality肌肉品質Model;

接著,再度按下 Enter ,Copilot 會自動建議以下的程式碼:

double S13 = worksheetCT身體組成.Range["S13"].Value.ToDouble();

在這裡將會讀取 Sheet 名稱為 MagicObjectHelper.CT身體組成原始擋20241212WorkSheetName ,其中第 S13 cell 的值,並且轉換成 double 型別。接著儲存到 S13 變數內

接著,再度按下 Enter ,Copilot 會自動建議以下的程式碼:

double I13 = worksheetCT身體組成.Range["I13"].Value.ToDouble();

接著,再度按下 Enter ,Copilot 會自動建議以下的程式碼:

double N13 = worksheetCT身體組成.Range["N13"].Value.ToDouble();

現在將會是重點,此時,再度按下 Enter ,Copilot 會自動建議如圖程式碼:

!

從這裡可看到所建議的程式碼雖然已經產生,但是,還是會有些錯誤,不過,關於公式的部分是正確的,接著,只需要將程式碼稍作修改即可,最終的程式碼如下所示:

var 健康肌肉比 = (S13 / (I13 + N13 + S13)).ToString("F2");

在這裡簡短的操作示範中看到,因為最初有加入計算公式的註解,讓 Copilot 能夠更精準的理解我要完成的任務,並且提供相對應的程式碼建議,雖然最後還是需要進行一些修改,但是,大幅減少了撰寫程式碼的時間。

當然,日後若公式有所變更,這裡也僅需要修改註解中的公式,然後再公式的程式碼進行刪除,接著,在按下 Enter 鍵,Copilot 就會再次根據新的註解內容來提供新的程式碼建議,這樣的方式能夠大幅提升程式碼撰寫的效率,並且減少錯誤發生的機率。