成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

與AI結對:一位高級開發人員構建插件的歷程

人工智能
James 使用 ChatGPT 來啟動訪問者模式在 Go 中的慣用實現。這包括學習如何為訪問者函數定義一個類型,然后聲明一個函數來滿足類型。

作者分享了他使用 ChatGPT 學習 Go、瀏覽 Kolide API 以及構建一個復雜的 Steampipe 插件的經驗。

譯自Pairing With AI: A Senior Developer's Journey Building a Plugin,作者 Jon Udell。

雖然改進開發人員文檔始終有幫助,但許多人(包括我自己)更喜歡在實踐中學習。這是我在七項指導原則中提出的第七項,也是最重要的一項:因為你在面向任務的可教授時刻獲取知識,所以學習不是前瞻性的,而是直接且切實的。

當經驗豐富的開發人員與 LLM 合作時,其機器智能會支持并增強你的智力。

好處對我來說很明顯。在 LLM 時代編寫Steampipe 的 ODBC 插件比我在沒有此類幫助的情況下編寫插件的體驗容易得多。但那公認是一個主觀評估,所以我一直在尋找一個機會與另一位插件開發人員比較筆記,當James Ramirez在我們的社區 Slack 中出現并宣布一個新插件用于Kolide API時。我邀請他告訴我他構建它的經歷,他親切地帶我進行了一次與 ChatGPT 的長時間對話,在此對話中,他熟悉了三個對他來說都是新知識的技術領域:Kolide API、Go 語言和 Steampipe 插件架構。

作為一個額外的挑戰:雖然插件開發人員通常為其插件針對的 API 找到合適的 Go SDK,但這里并非如此。因此,有必要為 Kolide API 創建一個 Go 封裝,然后將其集成到插件中。

測試 ChatGPT 的 Go 能力

James 從一些熱身練習開始。首先,為了測試 ChatGPT 的 Go 能力,他提供了一對 Go 函數,他編寫了這些函數來調用相關的 API/devices/和/devices/ID,并要求對它們之間的共享邏輯進行慣用重構。

接下來,他使用簡單的可變參數而不是更復雜的函數選項模式探索了函數的可選參數,并確定了簡單的方法——使用Search結構的切片來封裝 Kolide 的查詢參數的字段/運算符/值樣式——就足夠了。他要求一個函數將Search結構的切片序列化為一個 REST URL,然后優化 ChatGPT 提出的版本以創建最終的serializeSearches,該版本增加了對將友好名稱映射到參數的支持并使用字符串構建器。

AI 處理吹毛求疵,并經常提供可提交的建議。

其中一些優化,包括使用字符串構建器,是由 AI 驅動的機器人CodeRabbit提出的,它提供了有用的代碼審查。他說,這是幫助你和你的團隊專注于全局的反饋,因為它處理吹毛求疵,并經常(但并非總是)提供可提交的建議。它還采取更廣泛的視角來總結拉取請求并評估已關閉的 PR 是否解決了其關聯問題中陳述的目標。

映射運算符

他繼續探索將 Steampipe 運算符(如QualOperatorEqual)映射到 Kolide 運算符(如Equals)的方法。同樣,ChatGPT 提出的方法也變成了一個一次性方案,朝著一個干凈簡單的方案前進。但正如 James 在我們的采訪中證實的那樣,由于你無論如何都會迭代一次性版本,所以能夠生成合理的迭代而不是通過手工更繁瑣地對它們進行編碼是有幫助的。在此過程中,他正在學習基本的 Go 慣用語。

James:

Go 中有 do-while 循環嗎?

ChatGPT

沒有,但是……

James:

Go 中有三元運算符嗎?

ChatGPT

沒有,但是……

James:

我如何追加到map[string]string?

ChatGPT

像這樣……

使用反射增強的訪問者模式

在理解了基礎知識并為 Kolide API 開發了一個 Go 客戶端后,James 準備解決插件開發的實際工作:定義從 API 封裝返回的 Go 類型映射到控制針對這些表的 SQL 查詢的 Steampipe 架構的表。

與所有插件開發者一樣,他從一個可以列出資源集的表開始,然后通過過濾和分頁對其進行增強。在添加第二個表后,是時候考慮如何抽象出公共模式和行為。最終結果是訪問者模式的優雅實現。以下是與表kolide_device和kolide_issue相對應的 SteampipeList函數。

func listDevices(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
  var visitor ListPredicate = func(client *kolide.Client, cursor string, limit int32, searches ...kolide.Search) (interface{}, error) {
    return client.GetDevices(cursor, limit, searches...)
  }


  return listAnything(ctx, d, h, "kolide_device.listDevices", visitor, "Devices")
}




func listAdminUsers(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) {
  var visitor ListPredicate = func(client *kolide.Client, cursor string, limit int32, searches ...kolide.Search) (interface{}, error) {
    return client.GetAdminUsers(cursor, limit, searches...)
  }


  return listAnything(ctx, d, h, "kolide_admin_user.listAdminUsers", visitor, "AdminUsers")
}

以下是所有插件表通用的列表清單函數。

func listAnything(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData, callee string, visitor ListPredicate, target string) (interface{}, error) {
  // Create a slice to hold search queries
  searches, err := query(ctx, d)
  if err != nil {
    plugin.Logger(ctx).Error(callee, "qualifier_operator_error", err)
    return nil, err
  }


  // Establish connection to Kolide client
  client, err := connect(ctx, d)
  if err != nil {
    plugin.Logger(ctx).Error(callee, "connection_error", err)
    return nil, err
  }


  // Iterate through pagination cursors, with smallest number of pages
  var maxLimit int32 = kolide.MaxPaging
  if d.QueryContext.Limit != nil {
    limit := int32(*d.QueryContext.Limit)
    if limit < maxLimit {
      maxLimit = limit
    }
  }


  cursor := ""


  for {
    // Respect rate limiting
    d.WaitForListRateLimit(ctx)


    res, err := visitor(client, cursor, maxLimit, searches...)
    if err != nil {
      plugin.Logger(ctx).Error(callee, err)
      return nil, err
    }


    // Stream retrieved results
    collection := reflect.ValueOf(res).Elem().FieldByName(target)
    if collection.IsValid() {
      for i := 0; i < collection.Len(); i++ {
        d.StreamListItem(ctx, collection.Index(i).Interface())


        // Context can be cancelled due to manual cancellation or the limit has been hit
        if d.RowsRemaining(ctx) == 0 {
          return nil, nil
        }
      }
    }


    next := reflect.ValueOf(res).Elem().FieldByName("Pagination").FieldByName("NextCursor")
    if next.IsValid() {
      cursor = next.Interface().(string)
    }


    if cursor == "" {
      break
    }
  }


  return nil, nil
}

有了此設置,向插件添加新表幾乎完全是聲明式的:你僅需定義架構及 KeyColumns,以及在 SQL 查詢中的 where(或 join)子句與 API 級過濾器之間形成橋梁的相關運算符。然后編寫一個微小的 List 函數,該函數定義一個訪問器,并將該函數傳遞到 common listAnything 函數中,該函數封裝查詢參數編組、連接至 API 客戶端、調用 API、將響應解壓縮到一個集合中以及迭代集合以將數據項傳輸到 Steampipe 的外部數據包裝器的功能。

James 使用 ChatGPT 來啟動訪問者模式在 Go 中的慣用實現。這包括學習如何為訪問者函數定義一個類型,然后聲明一個函數來滿足類型。每個表的訪問者都封裝對 API 客戶端的調用,并返回一個接口。所有這些都相當通用,但訪問者的響應特定于包裝的 API 響應的 Go 類型,這意味著需要為每個表編寫一個不同的 List 函數。如何避免這種情況?James 問道:“res 變量上的字段引用需要是可變類型,在執行時指定。你能建議一種方法嗎?”

ChatGPT 的建議(他采納了)是使用反射,以便調用 listAnything(如 listAnything(ctx, d, h, “kolide_device.listDevices”, visitor, “Devices”))可以傳遞一個名稱("Devices"),使 listAnything 能夠以與類型無關的方式訪問響應結構的字段,例如,此處的 Devices 字段。

type DeviceListResponse struct {
      Devices    []Device   `json:"data"`
      Pagination Pagination `json:"pagination"`
    }

正因如此,listAnything 終于如其名,成為一個通用的 Steampipe List 函數。該解決方案很少使用反射,并在 API 層和 Steampipe 層中都保留了 Go 的強類型檢查。

LLM 協助真正意味著什么?

它肯定不意味著 LLM 根據以下提示編寫了一個體現復雜設計模式的插件:“我需要一個用于 Kolide API 的 Steampipe 插件,請創建它。”對我來說,以及對 James 來說,它的含義更有趣:“讓我們討論為 Kolide API 編寫插件的過程?!边@就像與一只橡皮鴨交談,以便大聲思考需求和策略。但 LLM 是一只會說話的橡皮鴨。有時響應直接適用,有時不適用,但無論哪種方式,它們通??梢詭椭惬@得清晰度。

作為一名經驗豐富的軟件工程師,James 本可以想出辦法——但這需要更長的時間。

James 說:“對話要求我對所問的問題非常具體?!彪m然他從頭開始使用 Go,但他帶來了豐富的經驗,使他能夠快速定位并找出哪些是需要問的正確問題。作為一名經驗豐富的軟件工程師,James 本可以自己想出所有這些。但這需要更長的時間,而且他將花費大量時間預先閱讀文章和文檔,而不是通過實踐學習。而且可能沒有時間!正如我現在從許多其他人那里聽到的那樣,LLM 提供的加速通常決定了擁有一個想法和能夠執行它之間的區別。

James 還提到了我未考慮過的開源角度。在 LLM 之前,他不會以完全公開的方式完成這項工作?!拔視恢北C?,直到我更有信心,”他說,“但這從一開始就在那里,我很高興它在那里。”這使得與 Turbot 團隊的接觸盡早成為可能。

這不是一個自動化故事,而是一個增強故事。當像 James Ramirez 這樣的經驗豐富的開發人員與 LLM 合作時,其機器智能支持并放大了他的智力。兩者協同工作——不僅編寫代碼,更重要的是,思考架構和設計。

     

責任編輯:武曉燕 來源: 云云眾生s
相關推薦

2024-01-04 10:02:55

開發插件

2019-08-07 11:00:07

程序員技能開發者

2013-09-25 09:20:39

iOS開發iOS7iPhone5s

2025-04-09 08:10:00

AI代碼生成器網絡安全人工智能

2010-08-09 16:09:25

2012-05-30 15:15:42

ibmdw

2023-03-15 07:12:53

企業開發人員提供商

2009-11-23 20:07:51

ibmdw開發

2021-02-19 09:33:01

kubernetesJAVA服務

2009-12-11 14:50:14

Visual Basi

2020-01-27 16:28:57

開發命令遠程服務器

2021-01-30 10:51:07

Python編程語言開發

2024-09-27 17:06:13

2022-02-17 16:05:58

SQL開發招聘

2023-02-17 15:01:15

2010-08-16 09:21:35

Windows Pho

2012-12-14 08:55:45

開發人員產品經理

2009-07-20 16:11:41

JRuby Swing

2021-12-10 23:48:19

Java開發技術

2021-02-16 16:44:40

RustJavaScript開發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久精品久久 | 黑人中文字幕一区二区三区 | 污污免费网站 | 国产日韩欧美另类 | 国产精品久久久爽爽爽麻豆色哟哟 | 国产成人在线播放 | 精品一区二区三区在线观看国产 | 精品一区二区久久久久久久网精 | 在线成人福利 | 四虎在线观看 | 欧美a∨ | 一区二区三区四区国产 | 国产乱码精品一品二品 | 久精品久久| 精品国产乱码久久久 | 狠狠色狠狠色综合日日92 | 一区二区三区高清在线观看 | 国产精品久久久久久久久免费软件 | 天天天天操 | 国产精品美女久久久久久久网站 | 黄色毛片在线播放 | 久久爱综合 | 国产精品视频久久久 | 999re5这里只有精品 | 日韩视频在线免费观看 | 大象视频一区二区 | 99婷婷 | 国产福利在线免费观看 | 亚洲av一级毛片 | 先锋资源网 | 亚洲精品99 | 久久国产精品-久久精品 | 最新国产精品精品视频 | 日日夜精品视频 | 国产色网站| 成人福利在线观看 | 亚洲精品美女视频 | 91av视频在线播放 | 国产日韩一区二区 | 欧美日一区二区 | 国产精品久久久久久久久图文区 |