你是否有過思考過,在某個時刻我們將永遠無法看到原版的電影或讀原版的書籍 - 只有根據我們的偏好和個性重新編寫或重拍過的版本,以最大化參與度?如果少數嚴謹的愛好者尋找原版作品(假設它真的存在),他們必定會覺得乏味:節奏錯誤、角色淺薄,以及性愛或動作場面太多或太少,不符合他們的口味。
軟體高度針對個人數據和工作流程(理想情況下是實時的)怎麼樣?與上游看起來毫無關聯的應用程式。根據過往使用者經驗和回饋塑造的應用程式。增強重要場景的應用程式,拋棄其他部分。跨越平台和供應商邊界的應用程式。回報是即時的:更好的性能、生產力和隱私;更少的認知負荷來切換工具。
應用程式適應人,而不是相反。
這不是個新想法.
去年我在《個人知識圖形》書中看到《數據中心宣言》。其前提很明確:專注於整合來自不同來源的数据;將應用程序視為可互換的數據層面視圖;賦予用戶從他們自己的標準附加組件中組合個人化應用程序的能力。幾句引言:
…個人數據—郵件、聯繫人、日曆事件、文件、筆記,以及更多—不再分佈在封閉的應用程式中,而是以圖結構互連。
所需要的,是靈活、以個人為中心的互操作(協同)方式,同時允許自由(自主)選擇和組合管理個人數據的應用程式和服務。
應用程式被允許存取資料,執行它們的魔法,並將它們的處理結果回傳到資料層.
作者提供了一個具體的例子:我不需要選擇單一電子郵件客戶端,我可以從收件箱、草稿視窗和垃圾郵件過濾器組合我喜愛的電子郵件客戶端嗎?
我們現在所擁有的,反而是在數十年間建立了以應用程式為中心的軟體:不相容的標準、封閉式數據收納以及供應商之間的碎片化。任何其他的聲音聽起來都像是一個不可能實現的夢,不是嗎?另一方面,這個想法非常迷人,並且深深觸動人心。它可能會帶來深遠的影響,在多個領域產生巨大的影響,包括生產力和隱私方面。
供應與需求
用戶可以擴展和自定義現有功能,以適應他們實際的工作流程,而不是每次都搜尋如何在特定工具中完成某事。混合搭配不同供應商的功能。跨平台和儲存邊界處理相同數據。
要實現它需要什麼?
首先,針對用戶需求量身定做的軟體聽起來很像是核心的開源軟體自由。不幸的是,開源軟體從未完全實現其潛力——結果顯示,源代碼的開放並非實踐中充分或不必要的條件。更重要的是從一開始就為有意義的可擴展性設計而努力,維護良好的文件(開發者很少主動寫),並保持穩定的API——雖然一些封閉源產品在此方面公認做得更好。
擁有來源是好事,可以製作修補程式——但還缺少些什麼。
其次,已經有很多現有的解決方案:COM/ActiveX組件,WordPress或Firefox的基於插件的架構,瀏覽器中使用類似Greasemonkey的擴充功能進行DOM存取,以運行用戶腳本並動態修改網頁,Slack整合,腳本以及Microsoft Office宏。然而,我們還沒到那裡。
大家都知道障礙點:供應商鎖定、不相容且衝突的數據格式和 API、文件參考不佳以及缺乏對維護和確保終用戶應用程式混搭品質的擁有權。隨意擴展這個清單。一件事很突出:這些例子都要求謹慎的前置規劃和設計。
這裡讓人想到供應與需求的宣告式模式。考慮一個主應用程式和一組執行實際重點工作的附加程式。為每個附加程式宣告一個規範。描述附加程式提供什麼(供應),然後定義限制、相依性和可能的組態(需求)。引入一個獨立的工廠式中間件層,負責協調供應與需求,並產生一個精確的組態計劃,使組裝能夠協同工作。基本上,這就是大多數發行版中套裝管理的工作方式。結果,這種模式對於通用軟體並不具備良好的擴展性。
我過去曾參與過一個項目,該項目圍繞著帶有規格說明的模塊,以及一個約束解決器將它們組裝成一個捆綁。最終該項目被放棄了。它需要精確的規格說明,所有細節都必須明確寫出才能運作,但最終這並沒有讓開發變得更容易.
於是我花費了幾天時間進行了一個小實驗,以不同的方式來解決這個問題。
恐龍實驗
調整您的桌面以符合您的風格和需求 - 自由軟體KDE桌面宣傳如此說。確實是一個可定制的桌面,作為KDE用戶,我有第一手的經驗來體驗其結果的優缺點。
我想擴展一個真實世界的應用程序,它不一定符合我的需求。通常,我會查找API和文檔來弄清楚如何編寫插件。
不是這次。
我首先從一個通用、不依賴應用的規範開始,作為一個需求。一個通用的檔案管理器,在本例中。我在那裡擬定預期的流程、API和鉤子,專注於自訂並省略其他內容。
只有在那之後,我才查閱文件和來源,以調和我的需求與我選擇的具體應用實際上提供。對應關係部分是手動設定,部分是自動化,並使用提示:親愛的代理,請使用可用的文件,如果有的話,否則分析代碼庫本身,將高層規格概念對應到具體的類和函數,並在過程中識別現有的擴展模式、插件基礎架構、鉤子,以及信號/槽。 我獨立開發了一個附加元件,嚴格對抗我自己的要求短暫的 API。
最後,隨著附加元件程式碼和對應方案可用,我請代理在本地將兩部分(主應用程式和附加元件)粘合起來。
我選擇了 KDE Dolphin:中規模專案,~500 個檔案,~80K 行程碼。
據我所知,它既沒有發布 API,也沒有開發文件。過去我從不會在沒有明確指導文件的情況下深入研究內部。儘管有源代碼可用,對於所有實際目的來說,它仍然是一個黑盒子。
嗯,不完全是。結果是內部是「悄悄地」有文件記錄 - Doxyfile 缺失,但代碼本身有註釋。不過,仍然沒有高層概述來開始。
我決定為實驗嵌入的附加元件,是一款有點傻氣的寵物小精靈遊戲,可以在文件管理器內玩:拖曳並放下檔案來滿足小精靈的需求;如果被忽略,小精靈可能會變得稍微惡作劇並以弄亂檔案(嗯,更頻繁地做備份)。
而且它成功了!這個插件,基於通用文件管理器API開發,根據提供的對應方式,非常貼合地安裝到了Dolphin上!
公開規範倉庫
它有什麼用處?
首先,符合規範所撰寫的插件,若在一個工具中運作順利,可以輕易地適應到另一個具有相同角色的工具。其次,還有一個相輔相成的情境(大都被忽略):將一個工具中的功能解耦,作為通用插件,並使其也能被其他人使用。真巧妙。
總體來說,這意味著我們現在能夠容忍供需之間的差距,客戶理解之合約與實際服務執行之間的差距,這總是一個主要的痛點。編碼代理越來越強大,能夠容忍的差距就越寬廣。
這開啟了維護一個通用規範的公共儲存庫的可能性,用於常見的桌面角色:通用郵件客戶端、日曆、檔案管理器等等。實際上與 FreeDesktop 標準或 schema.org 非常相似。不僅僅是另一個沒有人支持的規範,而是與非侵擾性映射配對,將常見角色投射到桌面動物園中的流行具體樣本上。
即時可用的規格。它們不需要大量的事前工作,也無需對現有專案進行深入的修改。專案可以隨著時間逐步更新,以更好地與它們所代表的角色保持一致。
它無法取代那些完全採納良好設計的可擴展插件式架構,並承諾維護穩定API和文件的重型產品。那仍然是確保穩定性、正確的品質保證和可管理的安全風險(以 upfront 工作為代價)的唯一方法。這也要求插件作者精確遵守合約,並在API中斷時每次更新他們的工作。
將此視為一個折衷方案,介於一個正確的插件式方法(__JHSNS_SEG_641d6e3b_49__),這並非總是可行的選項,以及純粹在自動化和個人化用戶工作流程以及提高生產力的道路上進行情緒編碼之間。
[附錄] 詳細規範
此規範是進步且分層的,最重要的項目在頂端,而先進細節則隱藏在下方。它不取代文件;它轉變視角以支援擴充性,並將通用角色映射到代碼中的具體類別、模組和符號。
我們需要知道在哪裡以及何時執行附加元件(在軟體語境中類似於時空座標)以修改或擴展行為。這需要捕捉靜態和動態的細節。
規範需要涵蓋至少4個方面:
UI結構:組件、小工具及其關係。這不僅限於GUI - 相同的結構經常反映在CLI、腳本API和IPC(例如D-Bus)中
流程
數據模型(例如檔案系統 API)。例如,要顯示 NextCloud 遠程檔案而不是本地資料夾,文件管理器必須在此時擴展。
持續性存儲:設定和附加元件特定數據
對於 UI,我終於得到這段摘錄:
- Main Window: root node, top-level application windowFolder Viewer: lists directory contents
- Side panels: additional dockable panels
- Bookmarks / Shortcuts Panel: lists bookmarked folders
- Details Panel: shows file or folder metadata
- Action bar: main toolbar with navigation and actions
- Status Bar: shows status and progress
此結構是通用的,可以對應到桌面、移動和雲端的文件管理器。此外,它並非GUI特定 - 它可以作為CLI、腳本API、IPC互動(例如FreeDesktop file-manager-interface D-Bus API與此結構也是兼容的),甚至還可以對應到代理端界面。
藉由編程代理程式,我接著分析過程式碼庫,並將通用檔案管理器規範對應到特定的Dolphin類別及其他符號。這個對應結果相當乾淨 - Dolphin遵循給定的藍圖相當嚴格。
關於流程:它們捕捉序列 - 控制流程、應用程式生命週期、使用者情境。一個流程包含開始、結束,以及選擇性的中間步驟。檔案管理器的典型流程有:
- App lifecycle: initialization, finalization
- Folder flow: enter folder, leave folder`
流程可以像UI元素或數據結構一樣嵌套。形式上,一個外部流程在任一內部流程之前開始,並在其之後結束。
將流程視為事件處理的泛化,信號/槽(Qt)、掛鉤、發布/訂閱模式、協程等。在流程中進行明確的推理(在形式證明中稱為模型檢查)有助於避免許多錯誤,因為初始化或清理並未在所有路徑上運行。事件驅動的系統通常具有隨心所欲、不一致的流程,這會導致過期狀態或無效緩存等問題。這只是換了件衣服的老舊GOTO指令。無害的流程相關錯誤很常見 - 例如,“選擇背景顏色”對話框有時在調整大小(刷新)之前無法渲染空白。
海豚並不遵循這種抽象的清晰邏輯。沒有明確的leave-folder最終化點;它可以通过截取changeUrl信號並為前一位置運行清理來模擬。代碼代理還識別DolphinMainWindow::changeUrl()為enter-folder步驟的入口點,但在實際操作中,它在每次導航中觸發兩次——在GUI應用中非常常見(類似信號交談)。
我所建立的一個最小型 Tamagotchi 代碼,根據抽象檔案管理器的藍圖使用 enter-folder 狀態來觸發互動(小寶寶會分析當前資料夾內容,並可能決定和蒼蠅玩一點小遊戲..) 以及 leave-folder 事件來清理留下的亂糟糟。最後,我請一個程式代碼代理來使用對應的映射將其粘合到 Dolphin 中,結果它成功了!











