

這是 AWS CDK v2 開發人員指南。較舊的 CDK v1 已於 2022 年 6 月 1 日進入維護，並於 2023 年 6 月 1 日結束支援。

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 重構 CDK 程式碼時保留已部署的資源
<a name="refactor"></a>

**重要**  
CDK 重構處於預覽版本中，可能會有所變更。

透過 AWS 雲端開發套件 (AWS CDK) 重構，您可以重構 CDK 程式碼，例如重新命名建構模組、在堆疊之間移動資源，以及重組應用程式，同時保留部署的資源，而不是取代它們。此功能可協助您維持良好的軟體工程最佳實務，而不會導致意外的資源替換。

## 什麼是資源保留的 CDK 重構？
<a name="refactor-intro"></a>

當您部署 CDK 應用程式時， AWS CloudFormation 會依其邏輯 IDs來識別資源。 AWS CDK 會根據建構IDs狀結構中的建構 ID 及其路徑產生這些邏輯 ID。如果您變更建構的 ID 或將其移至程式碼中的不同位置， AWS CloudFormation 通常會將此解譯為建立新資源並刪除舊資源的請求。對於資料庫、儲存貯體或佇列等具狀態資源，此取代可能會導致服務中斷或資料遺失。

CDK 重構透過以下方式解決此挑戰：
+ 偵測您的程式碼中何時移動或重新命名資源。
+ 使用 AWS CloudFormation 的重構功能來保留基礎實體資源。
+ 在不取代實際資源的情況下更新邏輯 IDs。
+ 維護堆疊中資源之間的參考。

您可以使用 CDK CLI `cdk refactor`命令或 CDK Toolkit Library `refactor`的動作來執行 CDK 重構。本指南主要討論 CLI 方法，但基礎原則適用於這兩種方法。如需使用 Toolkit Library 的資訊，請參閱[使用 CDK Toolkit Library 執行程式設計動作](toolkit-library.md)。

**重要**  
重構操作必須單獨執行，與其他動作分開，例如新增資源、刪除資源或修改資源屬性。  
如果您需要新增、刪除或修改資源以及重構，您應該先分別部署這些變更，然後使用重構來重新組織資源。

## CDK 重構的優點
<a name="refactor-benefits"></a>

CDK 重構為 AWS CDK 開發人員提供下列優點：
+  **改善程式碼組織** – 重新命名建構和重組 CDK 應用程式的結構，無需更換資源。
+  **建立可重複使用的元件** – 將重複的程式碼解壓縮為可重複使用的 L3 建構，同時保留已部署的資源。
+  **增強架構分離** – 在堆疊之間移動資源，以更好地隔離應用程式的不同部分。
+  **防止意外資源替換** – 重新命名建構時，避免意外資源重新建立。
+  **緩解第三方程式庫變更** – 保護您的應用程式免受您依賴的建構程式庫中的邏輯 ID 變更影響。
+  **套用軟體工程最佳實務** – 重構程式碼，而不犧牲您部署的基礎設施。

## CDK CLI `cdk refactor`命令的運作方式
<a name="refactor-how"></a>

**重要**  
您必須向 `--unstable=refactor`選項提供使用此功能的所有命令。

首先，部署初始 CDK 應用程式，以在 AWS 帳戶中建立基準資源。在重構您的 CDK 程式碼之後，例如重新命名建構或在堆疊之間移動資源，請使用 `cdk refactor`命令來開始重構已部署資源的程序。

當您執行 refactor 命令時，CDK CLI 會比較您目前的程式碼與部署狀態，以偵測您的本機變更。它會驗證您的 CDK 應用程式是否包含與部署狀態完全相同的一組資源，僅在其在建構樹狀結構中的位置中有所不同。然後，CDK CLI 會產生重構計畫，將舊資源位置映射至其新位置。CDK CLI 會顯示提議的變更，並在您確認後，使用 AWS CloudFormation 的重構 API 來更新資源IDs，而不會取代它們。

在幕後，CDK CLI 會透過比較其屬性和相依性來判斷哪些資源已移動，並識別在功能上同等但在建構樹狀結構中具有不同路徑的資源。如果偵測到任何資源新增、刪除或修改，重構操作將被拒絕，並顯示錯誤訊息。

## 重構 CDK 程式碼時保留資源的範例
<a name="refactor-example"></a>

在此範例中，我們會保留已部署的資源，同時使用 CDK CLI `cdk refactor`命令重構 CDK 程式碼。

我們的範例 CDK 應用程式包含單一堆疊，其中包含 S3 儲存貯體、CloudFront 分佈和 Lambda 函數。建構樹結構如下：

```
App
└─ MyStack
   ├─ Bucket
   ├─ Distribution
   └─ Function
```

以下是我們的應用程式程式碼範例：

```
const app = new cdk.App();
const myStack = new cdk.Stack(app, 'MyStack');

const bucket = new s3.Bucket(myStack, 'Bucket');
const distribution = new cloudfront.Distribution(myStack, 'Distribution', {
  defaultBehavior: { origin: new origins.S3Origin(bucket) }
});
const function = new lambda.Function(myStack, 'Function', {
  // function properties
});

// Synthesize the app
app.synth();
```

現在，假設您想要將此程式碼重構為：

1. 將儲存貯體從 重新命名`Bucket`為更具描述性的 `WebsiteOrigin`。

1. 將儲存貯體和分佈移至新的`WebStack`堆疊。

重構之後，建構樹看起來會如下所示：

```
App
├─ WebStack
│  ├─ WebsiteOrigin
│  └─ Distribution
└─ MyStack
   └─ Function
```

而重構程式碼為：

```
// Refactored structure
const app = new cdk.App();

// New WebStack with the bucket and distribution
const webStack = new cdk.Stack(app, 'WebStack');
const bucket = new s3.Bucket(webStack, 'WebsiteOrigin');
const distribution = new cloudfront.Distribution(webStack, 'Distribution', {
  defaultBehavior: { origin: new origins.S3Origin(bucket) }
});

// Original MyStack with just the function
const myStack = new cdk.Stack(app, 'MyStack');
const function = new lambda.Function(myStack, 'Function', {
  // function properties
});

// Synthesize the app
app.synth();
```

如果沒有 CDK 重構，這些變更會導致 AWS CloudFormation 建立新資源並刪除舊資源，因為邏輯 IDs 會變更：
+  `MyStack/Bucket/Resource` 會變成 `WebStack/WebsiteOrigin/Resource`。
+  `MyStack/Distribution/Resource` 會變成 `WebStack/Distribution/Resource`。

透過 CDK 重構，CDK CLI 會偵測這些路徑變更，並使用 AWS CloudFormation 的重構功能來保留基礎資源。當您執行 時`cdk refactor`，CLI 會顯示它將會進行的變更：

```
$ cdk refactor

The following resources were moved or renamed:

┌───────────────────────────────┬───────────────────────────────┬───────────────────────────────────┐
│ Resource Type                 │ Old Construct Path            │ New Construct Path                │
├───────────────────────────────┼───────────────────────────────┼───────────────────────────────────┤
│ AWS::S3::Bucket               │ MyStack/Bucket/Resource       │ WebStack/WebsiteOrigin/Resource   │
├───────────────────────────────┼───────────────────────────────┼───────────────────────────────────┤
│ AWS::CloudFront::Distribution │ MyStack/Distribution/Resource │ WebStack/Distribution/Resource    │
└───────────────────────────────┴───────────────────────────────┴───────────────────────────────────┘

Do you wish refactor these resources (y/n)?
```

當您輸入 進行確認時`y`，CDK CLI 會顯示重構操作的進度：

```
Refactoring...
✅  Stack refactor complete
```

確認後，CDK CLI 會執行重構操作，同時保留這兩個資源，同時更新其邏輯 IDs 以符合新的程式碼結構。

相同的映射也會顯示在 `cdk diff`命令的輸出中，依堆疊組織：

```
Stack MyStack
Resources
[-] AWS::S3::Bucket Bucket Bucket1234567 destroy (OR move to WebStack.WebsiteOrigin1234567 via refactoring)
[-] AWS::CloudFront::Distribution Distribution Distribution1234567 destroy (OR move to WebStack.Distribution1234567)
...

Stack WebStack
Resources
[+] AWS::S3::Bucket WebsiteOrigin WebsiteOrigin1234567 (OR move from MyStack.Bucket1234567)
[+] AWS::CloudFront::Distribution Distribution Distribution1234567 (OR move from MyStack.Distribution1234567)
...
```

## 開始使用 CDK 重構
<a name="_get_started_with_cdk_refactoring"></a>

若要開始使用重構，請完成下列先決條件：

 **使用最新的範本引導您的環境**   
CDK 重構功能需要引導堆疊中的新許可。為了確保您擁有必要的許可，請使用最新的範本來引導您的環境：  

```
cdk bootstrap
```
如需引導的詳細資訊，請參閱 [AWS CDK 的引導環境](bootstrapping-env.md)。

 **安裝最新的 CDK CLI 版本**   
CDK 重構需要最新版本的 CDK CLI。若要確保您擁有最新版本：  

```
npm install -g aws-cdk
```
如需詳細安裝說明，請參閱 [AWS CDK 入門](getting-started.md)。

## 使用覆寫檔案來解決重構中的模棱兩可情況
<a name="override-file"></a>

CDK CLI 會根據將您的程式碼與部署的資源進行比較，自動運算所有資源映射。在大多數情況下，此自動偵測運作良好，但在某些情況下，CLI 可能會遇到無法自行解決的模棱兩可情況。若要為 CDK CLI 提供指引，請使用覆寫檔案。

 **建立覆寫檔案以解決模棱兩可的問題**   
覆寫檔案是一種 JSON 檔案，可在 CDK CLI 無法判斷資源的重構解析度時提供映射。檔案包含依環境組織的資源映射：  

```
{
    "environments": [
        {
            "account": "123456789012",
            "region": "us-east-2",
            "resources": {
                "StackA.OldName": "StackB.NewName",
                "StackC.Foo": "StackC.Bar"
            }
        }
    ]
}
```
在此檔案中：  
+ `environments` 陣列包含一或多個具有帳戶和區域的環境項目。
+ 在每個環境中， `resources` 物件包含映射。
+ 金鑰代表格式為 的目前位置`<stack name>.<logical ID>`。
+ 值代表相同格式的新位置。
若要搭配 CDK CLI 使用覆寫檔案：  

```
cdk refactor --override-file=overrides.json
```

## 重構跨多個環境的堆疊
<a name="refactor-environments"></a>

CDK 應用程式可以包含多個堆疊，這些堆疊可部署到不同的環境 (AWS 帳戶和區域）。在重構這類應用程式中保留資源時，CDK CLI 會以特定方式處理環境：
+ CLI 會依環境分組堆疊，並在每個環境中分別執行重構。
+ 您可以在重構期間在堆疊之間移動資源，但所有涉及移動的堆疊都必須位於相同的環境中。
+ 嘗試跨環境移動資源會導致錯誤。

此行為可確保資源保留在其原始 AWS 帳戶和區域中，這是必要的，因為 CloudFormation 資源無法實際跨帳戶或區域邊界移動。

例如，如果您的 CDK 應用程式同時為開發和生產環境定義堆疊，則重構操作將在每個環境中獨立執行。資源可以在開發環境或生產環境中的堆疊之間移動，但不能從開發到生產，反之亦然。

## 處理旨在取代的資源
<a name="refactor-replaceable-resources"></a>

有些 CDK 建構仰賴 CloudFormation 的資源替換行為作為其設計的一部分。例如，API Gateway `Deployment`和 Lambda `Version` 的建構旨在在其屬性變更時建立新資源。

重構時，請勿包含任何應該導致資源取代的變更。否則，CDK CLI 可能會偵測並保留這些資源。這表示設計要取代的資源必須與重構操作分開處理。

若要正確管理設計為要取代的資源：

1. 首先，部署您的應用程式以視需要取代這些資源。

1. 然後，分別執行重構操作，以重組您的程式碼。

這種兩步驟方法可確保正確處理設計來取代的資源，同時仍可讓您受益於其他資源的 CDK 重構。

## 一般考量和限制
<a name="refactor-considerations"></a>

在 CDK 重構期間保留資源時，請記住下列考量事項：
+  **環境限制**：資源只能在相同環境中的堆疊之間移動。不支援跨環境移動。
+  **模棱兩可**：如果您有多個相同的資源同時重新命名，CDK CLI 可能無法自動判斷正確的映射。在這些情況下，您將需要使用覆寫檔案提供明確的映射。
+  **引導要求**：若要在重構期間保留資源，您需要使用包含必要許可的最新版本來更新引導堆疊。
+  **排除某些建構**：某些建構，例如 API Gateway `Deployment`和 Lambda 的 `Version`依賴於資源替換，並自動排除在重構之外。

## 使用 CI/CD 管道重構
<a name="refactor-pipelines"></a>

若要在 CI/CD 管道中使用重構功能，您需要能夠執行 CDK CLI 做為管道的一部分。以下是將重構整合至 CI/CD 工作流程的一些重要考量。

 **在 CI/CD 中使用重構的先決條件**   
您必須能夠在 CI/CD 環境中使用 CDK CLI，才能受益於此功能。

 **將重構整合到您的管道工作流程**   
如果您使用 CLI 在 CI/CD 管道中部署，您的指令碼通常如下所示：  

```
...
cdk deploy <stack filter>
...
```
如果您想要在工作流程中包含重構，以下是基本範例：  

```
...
cdk refactor <stack filter>
cdk deploy <stack filter>
...
```
您也可以將重構作為管道中的單獨步驟。

 **處理重構失敗**   
請注意，如果您的程式碼包含實際的資源修改以及重構， `cdk refactor`將會失敗。由於您在管道中自動呼叫重構，因此您需要處理潛在的故障：  

```
# Allow refactoring to fail but continue the pipeline
cdk refactor <stack filter> || true
cdk deploy <stack filter>
```
或者，您可能想要確保在您成功執行重構之前不會發生部署：  

```
# Only deploy if refactoring succeeds
cdk refactor <stack filter> && cdk deploy <stack filter>
```

 **CI/CD 環境的最佳實務**   
若要在 CI/CD 管道中有效使用重構：  
+  **與其他變更分開重構**：請記住，重構操作必須與資源新增、刪除或修改分開。在您的管道中，請考慮擁有專用遞交和部署以進行重構。
+  **適當使用覆寫檔案**：了解覆寫檔案僅由 CDK CLI 用作解決模棱兩可案例的備用檔案。
+  **管道`--force`中不需要 **：在 CI/CD 管道等非互動式環境中，CDK refactor 命令會自動繼續，而不會提示確認。只有在互動式環境中才需要 `--force`選項。

## 相關資源
<a name="refactor-resources"></a>

如需 CDK CLI `cdk refactor`命令之選項和引數的相關資訊，請參閱 ` cdk refactor `。

若要開始使用 CDK Toolkit Library `refactor`的動作，請參閱[使用 CDK Toolkit Library 執行程式設計動作](toolkit-library.md)。