Praktik terbaik untuk Workflows

Anda dapat melihat praktik terbaik yang tercantum di sini saat mengorkestrasi layanan menggunakan Workflows.

Ini bukanlah daftar rekomendasi lengkap dan tidak mengajari Anda dasar-dasar cara menggunakan Workflows. Dokumen ini mengasumsikan bahwa Anda sudah memiliki pemahaman umum tentang keseluruhan lanskap Google Cloud dan Workflows. Untuk mengetahui informasi selengkapnya, lihat Framework Arsitektur Google Cloud dan Ringkasan alur kerja.

Memilih pola komunikasi yang optimal

Saat mendesain arsitektur microservice untuk men-deploy beberapa layanan, Anda dapat memilih dari pola komunikasi berikut:

  • Komunikasi layanan-ke-layanan langsung

  • Komunikasi tidak langsung berbasis peristiwa (juga dikenal sebagai koreografi)

  • Konfigurasi, koordinasi, dan pengelolaan otomatis (juga dikenal sebagai orkestrasi)

Pastikan untuk mempertimbangkan manfaat dan kekurangan dari setiap opsi sebelumnya dan pilih pola yang optimal untuk kasus penggunaan Anda. Misalnya, komunikasi layanan-ke-layanan langsung mungkin lebih mudah diterapkan daripada opsi lain, tetapi metode ini memasangkan erat layanan Anda. Sebaliknya, arsitektur berbasis peristiwa memungkinkan Anda memasangkan layanan secara longgar; namun, pemantauan dan proses debug mungkin lebih rumit. Terakhir, orkestrasi pusat seperti Workflows, meskipun kurang fleksibel, memungkinkan Anda mengoordinasikan komunikasi antarlayanan tanpa hubungan erat antara komunikasi layanan-ke-layanan langsung, atau kerumitan peristiwa dengan koreografi.

Anda juga dapat menggabungkan pola komunikasi. Misalnya, dalam orkestrasi berbasis peristiwa, layanan yang terkait erat akan dikelola dalam orkestrasi yang dipicu oleh peristiwa. Demikian pula, Anda mungkin mendesain sistem dengan satu orkestrasi menghasilkan pesan Pub/Sub ke sistem orkestrasi lainnya.

Tips umum

Setelah Anda memutuskan untuk menggunakan Workflows sebagai orkestrasi layanan, ingat tips bermanfaat berikut.

Menghindari URL hardcode

Anda dapat mendukung alur kerja yang portabel di beberapa lingkungan dan lebih mudah dikelola dengan menghindari URL hardcode. Anda dapat melakukannya dengan cara berikut:

  • Tentukan URL sebagai argumen runtime.

    Hal ini dapat membantu saat alur kerja Anda dipanggil melalui library klien atau API. (Namun, cara ini tidak akan berfungsi jika alur kerja Anda dipicu oleh peristiwa dari Eventarc dan satu-satunya argumen yang dapat diteruskan adalah payload peristiwa.)

    Contoh

    main:
      params: [args]
      steps:
        - init:
            assign:
              - url1: ${args.urls.url1}
              - url2: ${args.urls.url2}

    Saat menjalankan alur kerja, Anda dapat menentukan URL. Misalnya:

    gcloud workflows run multi-env --data='{"urls":{"url1": "URL_ONE", "url2": "URL_TWO"}}'
  • Gunakan variabel lingkungan dan buat alur kerja yang dikonfigurasi secara dinamis bergantung pada lingkungan tempatnya di-deploy. Atau, buat alur kerja yang dapat digunakan kembali sebagai template dan dikonfigurasi sesuai dengan variabel lingkungan yang dikelola secara terpisah.

  • Gunakan teknik substitusi yang memungkinkan Anda membuat file definisi alur kerja tunggal, tetapi men-deploy varian menggunakan alat yang menggantikan placeholder dalam alur kerja Anda. Misalnya, Anda dapat menggunakan Cloud Build untuk men-deploy alur kerja dan menambahkan langkah untuk mengganti URL placeholder dalam file konfigurasi Cloud Build dalam file konfigurasi Cloud Build.

    Contoh

    steps:
    ‐ id: 'replace-urls'
      name: 'gcr.io/cloud-builders/gcloud'
      entrypoint: bash
      args:
        - -c
        - |
          sed -i -e "s~REPLACE_url1~$_URL1~" workflow.yaml
          sed -i -e "s~REPLACE_url2~$_URL2~" workflow.yaml
    ‐ id: 'deploy-workflow'
      name: 'gcr.io/cloud-builders/gcloud'
      args: ['workflows', 'deploy', 'multi-env-$_ENV', '--source', 'workflow.yaml']

    Anda kemudian dapat mengganti nilai variabel selama waktu build. Contoh:

    gcloud builds submit --config cloudbuild.yaml \
        --substitutions=_ENV=staging,_URL1="URL_ONE",_URL2="URL_TWO"

    Untuk mengetahui informasi selengkapnya, lihat Mengirim build melalui CLI dan API.

    Atau, Anda dapat menggunakan Terraform untuk menyediakan infrastruktur dan menentukan file konfigurasi yang membuat alur kerja untuk setiap lingkungan menggunakan variabel input.

    Contoh

    variable "project_id" {
      type = string
    }
    
    variable "url1" {
      type = string
    }
    
    variable "url2" {
      type = string
    }
    
    locals {
      env = ["staging", "prod"]
    }
    
    # Define and deploy staging and production workflows
    resource "google_workflows_workflow" "multi-env-workflows" {
      for_each = toset(local.env)
    
      name            = "multi-env-${each.key}"
      project         = var.project_id
      region          = "us-central1"
      source_contents = templatefile("${path.module}/workflow.yaml", { url1 : "${var.url1}-${each.key}", url2 : "${var.url2}-${each.key}" })
    }

    Jika variabel dideklarasikan dalam modul root konfigurasi, variabel dapat nilai yang ditetapkan dalam beberapa cara. Contohnya

    terraform apply -var="project_id=PROJECT_ID" -var="url1=URL_ONE" -var="url2=URL_TWO"
  • Gunakan konektor Secret Manager untuk menyimpan URL di Secret Manager dan mengambilnya dengan aman.

Menggunakan langkah bertingkat

Setiap alur kerja harus memiliki setidaknya satu langkah. Secara default, Workflows memperlakukan langkah seolah-olah berada dalam daftar yang diurutkan dan menjalankannya satu per satu hingga semua langkah telah berjalan. Secara logis, beberapa langkah harus dikelompokkan bersama dan Anda dapat menggunakan blok steps untuk menyusun bertingkat serangkaian langkah. Ini adalah cara yang mudah karena memungkinkan Anda menunjuk ke langkah atomik yang benar untuk memproses serangkaian langkah.

Contoh

main:
    params: [input]
    steps:
    - callWikipedia:
        steps:
        - checkSearchTermInInput:
            switch:
                - condition: ${"searchTerm" in input}
                  assign:
                    - searchTerm: ${input.searchTerm}
                  next: readWikipedia
        - getCurrentDate:
            call: http.get
            args:
                url: https://timeapi.io/api/Time/current/zone?timeZone=Europe/Amsterdam
            result: currentDate
        - setFromCallResult:
            assign:
                - searchTerm: ${currentDate.body.dayOfWeek}
        - readWikipedia:
            call: http.get
            args:
                url: https://en.wikipedia.org/w/api.php
                query:
                    action: opensearch
                    search: ${searchTerm}
            result: wikiResult
    - returnOutput:
            return: ${wikiResult.body[1]}

Gabungkan ekspresi

Semua ekspresi harus dimulai dengan $ dan diapit dalam tanda kurung kurawal:

${EXPRESSION}

Untuk menghindari masalah penguraian YAML, Anda dapat menggabungkan ekspresi dalam tanda kutip. Misalnya, ekspresi yang berisi titik dua dapat menyebabkan perilaku yang tidak terduga jika titik dua ditafsirkan sebagai menentukan peta. Anda dapat mengatasi masalah ini dengan menggabungkan ekspresi YAML dalam tanda kutip tunggal:

'${"Name: " + myVar}'

Anda juga dapat menggunakan ekspresi yang mencakup beberapa baris. Misalnya, Anda mungkin perlu menggabungkan kueri SQL dalam tanda kutip saat menggunakan konektor BigQuery Workflow.

Contoh

- runQuery:
    call: googleapis.bigquery.v2.jobs.query
    args:
        projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
        body:
            useLegacySql: false
            useQueryCache: false
            timeoutMs: 30000
            # Find top 100 titles with most views on Wikipedia
            query: ${
                "SELECT TITLE, SUM(views)
                FROM `bigquery-samples.wikipedia_pageviews." + table + "`
                WHERE LENGTH(TITLE) > 10
                GROUP BY TITLE
                ORDER BY SUM(VIEWS) DESC
                LIMIT 100"
                }
    result: queryResult

Untuk mengetahui definisi alur kerja secara keseluruhan, lihat Menjalankan beberapa tugas BigQuery secara paralel.

Menggunakan panggilan deklaratif

Gunakan Workflows untuk memanggil layanan dari alur kerja itu sendiri dan menangani hasilnya, serta untuk menjalankan tugas sederhana seperti membuat panggilan HTTP. Alur kerja dapat memanggil layanan, mengurai respons, dan membuat input untuk layanan lain yang terhubung. Memanggil layanan memungkinkan Anda menghindari detail pemanggilan tambahan, dependensi tambahan, dan panggilan layanan. Pertimbangkan untuk mengganti layanan yang bebas dari logika bisnis dengan panggilan API deklaratif dan gunakan Alur kerja untuk menghilangkan kompleksitas.

Namun, Anda harus membuat layanan untuk melakukan tugas apa pun yang terlalu kompleks untuk Workflows; misalnya, menerapkan logika bisnis yang dapat digunakan kembali, komputasi kompleks, atau transformasi yang tidak didukung oleh Ekspresi alur kerja dan library standarnya. Kasus yang rumit biasanya lebih mudah diimplementasikan dalam kode, daripada menggunakan YAML atau JSON dan sintaksis alur kerja.

Simpan hanya yang Anda butuhkan

Pertahankan konsumsi memori agar Anda tidak mengalami batas resource atau error yang menunjukkan hal ini seperti ResourceLimitError, MemoryLimitExceededError, atau ResultSizeLimitExceededError.

Anda harus selektif dalam menyimpan data di variabel, serta memfilter dan menyimpan hanya yang Anda butuhkan. Jika layanan menampilkan payload yang terlalu besar, gunakan fungsi terpisah untuk melakukan panggilan untuk Anda dan hanya tampilkan yang diperlukan.

Anda dapat mengosongkan memori dengan membersihkan variabel. Misalnya, Anda mungkin ingin mengosongkan memori yang diperlukan untuk langkah berikutnya. Atau, mungkin ada panggilan dengan hasil yang tidak penting, dan Anda dapat menghilangkan hasil tersebut sepenuhnya.

Anda dapat menghapus variabel dengan menetapkan null. Dalam YAML, Anda juga dapat menetapkan nilai kosong atau ~ ke suatu variabel. Cara ini mengidentifikasi memori yang dapat diklaim kembali dengan aman.

Contoh

  - step:
      assign:
        - bigVar:

Menggunakan subalur kerja dan alur kerja eksternal

Anda dapat menggunakan sub-alur kerja untuk menentukan bagian logika atau serangkaian langkah yang ingin Anda panggil beberapa kali, sehingga menyederhanakan definisi alur kerja. Sub-alur mirip dengan fungsi atau rutin dalam bahasa pemrograman. API ini dapat menerima parameter dan nilai yang ditampilkan, sehingga Anda dapat membuat alur kerja yang lebih kompleks dengan berbagai aplikasi.

Perhatikan bahwa sub-alur kerja bersifat lokal untuk definisi alur kerja Anda dan tidak dapat digunakan kembali di alur kerja lain. Namun, Anda dapat memanggil alur kerja dari alur kerja lain. Konektor Workflows dapat membantu Anda terkait hal ini. Untuk mengetahui informasi selengkapnya, lihat ringkasan konektor untuk Workflow Executions API dan Workflows API.

Menggunakan konektor Workflows

Workflows menyediakan sejumlah connectors yang mempermudah akses ke produk Google Cloud lainnya dalam alur kerja. Konektor menyederhanakan layanan panggilan karena menangani pemformatan permintaan untuk Anda, menyediakan metode dan argumen sehingga Anda tidak perlu mengetahui detail Google Cloud API. Konektor juga memiliki perilaku bawaan untuk menangani percobaan ulang dan operasi yang berjalan lama sehingga Anda dapat menghindari iterasi dan menunggu panggilan selesai; konektor akan menanganinya untuk Anda.

Jika Anda perlu memanggil Google Cloud API, periksa terlebih dahulu apakah konektor alur kerja untuknya ada atau tidak. Dan jika tidak melihat konektor untuk produk Google Cloud, Anda dapat memintanya.

Pelajari cara menggunakan konektor dan, untuk referensi mendetail tentang konektor yang tersedia, lihat Referensi konektor.

Menjalankan langkah-langkah alur kerja secara paralel

Meskipun Workflows dapat menjalankan langkah secara berurutan, Anda juga dapat menjalankan langkah-langkah independen secara paralel. Pada beberapa kasus, hal ini dapat mempercepat eksekusi alur kerja Anda secara signifikan. Untuk mengetahui informasi selengkapnya, lihat Menjalankan langkah-langkah alur kerja secara paralel.

Terapkan percobaan ulang dan pola saga

Mendesain alur kerja yang tangguh dan dapat menangani kegagalan layanan sementara dan permanen. Error untuk Alur Kerja dapat muncul, misalnya, oleh permintaan HTTP yang gagal, fungsi, konektor, atau dihasilkan oleh kode alur kerja Anda sendiri. Tambahkan penanganan error dan percobaan ulang agar kegagalan dalam satu langkah tidak menyebabkan seluruh alur kerja gagal.

Beberapa transaksi bisnis menjangkau beberapa layanan, sehingga Anda memerlukan mekanisme untuk menerapkan transaksi yang mencakup layanan. Pola desain saga adalah cara untuk mengelola konsistensi data di seluruh microservice dalam skenario transaksi terdistribusi. Saga adalah urutan transaksi yang memublikasikan peristiwa untuk setiap transaksi dan yang memicu transaksi berikutnya. Jika transaksi gagal, saga akan mengeksekusi transaksi kompensasi yang melawan kegagalan sebelumnya dalam urutan. Coba tutorial Retries and Saga Pattern in Workflows di GitHub.

Untuk mengetahui informasi selengkapnya, lihat Alur kerja transaksional dalam arsitektur microservice di Google Cloud.

Menggunakan callback untuk menunggu

Callback memungkinkan eksekusi alur kerja menunggu layanan lain membuat permintaan ke endpoint callback; permintaan tersebut melanjutkan eksekusi alur kerja.

Dengan callback, Anda dapat memberi tahu alur kerja bahwa peristiwa tertentu telah terjadi, dan menunggu peristiwa tersebut tanpa melakukan polling. Misalnya, Anda dapat membuat alur kerja yang memberi tahu Anda saat produk kembali tersedia atau saat item telah dikirim; atau yang menunggu interaksi manusia seperti meninjau pesanan atau memvalidasi terjemahan. Anda juga dapat menunggu peristiwa menggunakan callback dan pemicu Eventarc.

Mengorkestrasi tugas yang berjalan lama

Jika perlu menjalankan workload batch processing yang berjalan lama, Anda dapat menggunakan tugas Batch atau Cloud Run, serta menggunakan Alur kerja untuk mengelola layanan. Hal ini memungkinkan Anda menggabungkan keunggulan serta menyediakan dan mengorkestrasi seluruh proses secara efisien.

Batch adalah layanan terkelola sepenuhnya yang dapat Anda gunakan untuk menjadwalkan, memasukkan dalam antrean, dan menjalankan beban kerja batch pada instance virtual machine (VM) Compute Engine. Anda dapat menggunakan konektor alur kerja untuk Batch guna menjadwalkan dan menjalankan tugas Batch. Untuk mengetahui detailnya, coba tutorial.

Tugas Cloud Run digunakan untuk menjalankan kode yang menjalankan tugas (tugas) dan keluar saat tugas tersebut selesai. Dengan alur kerja, Anda dapat mengeksekusi tugas Cloud Run sebagai bagian dari alur kerja untuk melakukan pemrosesan data yang lebih kompleks atau mengorkestrasi sistem tugas yang ada. Coba tutorial yang menunjukkan cara menggunakan Workflows untuk menjalankan tugas Cloud Run.

Menyimpan tugas yang berjalan lama ke dalam container

Anda dapat mengotomatiskan eksekusi container yang berjalan lama menggunakan Alur kerja dan Compute Engine. Misalnya, Anda dapat memasukkan tugas yang berjalan lama ke dalam container sehingga dapat berjalan di mana saja, kemudian menjalankan container tersebut di VM Compute Engine selama durasi maksimum eksekusi alur kerja (satu tahun).

Dengan Workflows, Anda dapat mengotomatiskan pembuatan VM, menjalankan container di VM, dan penghapusan VM. Dengan begitu, Anda dapat menggunakan server dan menjalankan container, tetapi mengurangi kerumitan pengelolaan keduanya. Selain itu, hal ini berguna jika Anda menghadapi batasan waktu saat menggunakan layanan seperti Cloud Functions atau Cloud Run. Coba tutorial Container yang berjalan lama dengan Workflows dan Compute Engine di GitHub.

Menjalankan alat command line dari Workflows

Cloud Build adalah layanan yang mengeksekusi build Anda di Google Cloud sebagai serangkaian langkah build. Setiap langkah build dijalankan dalam container Docker. Menjalankan langkah build sama dengan mengeksekusi perintah dalam skrip.

Google Cloud CLI mencakup alat command line gcloud, gsutil, bq, dan kubectl, tetapi tidak ada cara langsung untuk menjalankan perintah gcloud CLI dari Workflows. Namun, Cloud Build menyediakan image container yang menyertakan gcloud CLI. Anda dapat menjalankan perintah gcloud CLI di container tersebut dari langkah Cloud Build, dan membuat langkah tersebut di Workflows menggunakan konektor Cloud Build.

Contoh

Jalankan gcloud dalam alur kerja:

# This example shows how to execute gcloud commands from Workflows
# using Cloud Build and returns the output

main:
  steps:
  - execute_command:
      call: gcloud
      args:
          args: "workflows list"
      result: result
  - return_result:
      return: ${result}

gcloud:
  params: [args]
  steps:
  - create_build:
      call: googleapis.cloudbuild.v1.projects.builds.create
      args:
        projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
        parent: ${"projects/" + sys.get_env("GOOGLE_CLOUD_PROJECT_ID") + "/locations/global"}
        body:
          serviceAccount: ${sys.get_env("GOOGLE_CLOUD_SERVICE_ACCOUNT_NAME")}
          options:
            logging: CLOUD_LOGGING_ONLY
          steps:
          - name: gcr.io/google.com/cloudsdktool/cloud-sdk
            entrypoint: /bin/bash
            args: ${["-c", "gcloud " + args + " > $$BUILDER_OUTPUT/output"]}
      result: result_builds_create
  - return_build_result:
      return: ${text.split(text.decode(base64.decode(result_builds_create.metadata.build.results.buildStepOutputs[0])), "\n")}

Jalankan kubectl dalam alur kerja:

# This example shows how to execute kubectl commands from Workflows
# using Cloud Build and returns the output

main:
  steps:
  - execute_command:
      call: kubectl
      args:
          args: "--help"
      result: result
  - return_result:
      return: ${result}

kubectl:
  params: [args]
  steps:
  - create_build:
      call: googleapis.cloudbuild.v1.projects.builds.create
      args:
        projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
        parent: ${"projects/" + sys.get_env("GOOGLE_CLOUD_PROJECT_ID") + "/locations/global"}
        body:
          serviceAccount: ${sys.get_env("GOOGLE_CLOUD_SERVICE_ACCOUNT_NAME")}
          options:
            logging: CLOUD_LOGGING_ONLY
          steps:
          - name: gcr.io/cloud-builders/kubectl
            entrypoint: /bin/bash
            args: ${["-c", "kubectl " + args + " > $$BUILDER_OUTPUT/output"]}
      result: result_builds_create
  - return_build_result:
      return: ${text.split(text.decode(base64.decode(result_builds_create.metadata.build.results.buildStepOutputs[0])), "\n")}

Menggunakan Terraform untuk membuat alur kerja Anda

Terraform adalah alat infrastruktur sebagai kode yang memungkinkan Anda membuat, mengubah, dan meningkatkan infrastruktur cloud secara terprediksi menggunakan kode.

Anda dapat menentukan dan men-deploy alur kerja menggunakan resource google_workflows_workflow Terraform. Untuk mengetahui informasi lebih lanjut, baca bagian Membuat alur kerja menggunakan Terraform.

Untuk membantu mengelola dan mempertahankan alur kerja besar, Anda dapat membuat alur kerja dalam file YAML terpisah dan mengimpor file tersebut ke Terraform menggunakan fungsi templatefile yang membaca file di jalur tertentu dan merender kontennya sebagai template.

Contoh

  # Define a workflow
  resource "google_workflows_workflow" "workflows_example" {
    name            = "sample-workflow"
    region          = var.region
    description     = "A sample workflow"
    service_account = google_service_account.workflows_service_account.id
    # Import main workflow YAML file
    source_contents = templatefile("${path.module}/workflow.yaml",{})
  }

Demikian pula, jika Anda memiliki alur kerja utama yang memanggil beberapa sub-alur kerja, Anda dapat menentukan alur kerja utama dan sub-alur kerja dalam file terpisah, serta menggunakan fungsi templatefile untuk mengimpornya.

Contoh

  # Define a workflow
  resource "google_workflows_workflow" "workflows_example" {
    name            = "sample-workflow"
    region          = var.region
    description     = "A sample workflow"
    service_account = google_service_account.workflows_service_account.id
    # Import main workflow and subworkflow YAML files
    source_contents = join("", [
      templatefile(
        "${path.module}/workflow.yaml",{}
      ),

      templatefile(
        "${path.module}/subworkflow.yaml",{}
      )])
  }

Perlu diperhatikan bahwa jika Anda merujuk pada nomor baris saat men-debug alur kerja, semua file YAML yang diimpor melalui file konfigurasi Terraform akan digabungkan dan di-deploy sebagai satu alur kerja.

Men-deploy alur kerja dari repositori Git

Cloud Build menggunakan pemicu build untuk mengaktifkan otomatisasi CI/CD. Anda dapat mengonfigurasi pemicu untuk memproses peristiwa masuk, seperti saat commit baru didorong ke repositori atau saat permintaan pull dimulai, lalu otomatis mengeksekusi build saat peristiwa baru masuk.

Anda dapat menggunakan pemicu Cloud Build untuk otomatis memulai build dan men-deploy alur kerja dari repositori Git. Anda dapat mengonfigurasi pemicu untuk men-deploy alur kerja pada perubahan apa pun pada repositori sumber, atau men-deploy alur kerja hanya jika perubahan tersebut cocok dengan kriteria tertentu.

Pendekatan ini dapat membantu Anda mengelola siklus proses deployment. Misalnya, Anda dapat men-deploy perubahan ke alur kerja di lingkungan staging, menjalankan pengujian terhadap lingkungan tersebut, lalu meluncurkan perubahan ini secara bertahap ke lingkungan produksi. Untuk mengetahui informasi selengkapnya, lihat Men-deploy alur kerja dari repositori Git menggunakan Cloud Build.

Mengoptimalkan penggunaan

Biaya untuk menjalankan alur kerja minimal. Namun, untuk penggunaan bervolume tinggi, terapkan panduan berikut untuk mengoptimalkan penggunaan dan mengurangi biaya:

  • Daripada menggunakan domain kustom, pastikan setiap panggilan ke layanan Google Cloud menggunakan *.appspot.com, *.cloud.goog, *.cloudfunctions.net, atau *.run.app sehingga Anda akan ditagih untuk langkah internal, bukan eksternal.

  • Terapkan kebijakan percobaan ulang kustom yang menyeimbangkan kebutuhan latensi dan keandalan Anda dengan biaya. Lebih sering mencoba ulang latensi yang lebih rendah dan meningkatkan keandalan, tetapi juga dapat meningkatkan biaya.

  • Saat menggunakan konektor yang menunggu operasi yang berjalan lama, tetapkan kebijakan polling kustom yang mengoptimalkan latensi untuk biaya. Misalnya, jika Anda memperkirakan operasi memerlukan waktu lebih dari satu jam, Anda mungkin ingin kebijakan yang awalnya melakukan polling setelah satu menit jika terjadi kegagalan langsung, lalu setiap 15 menit setelahnya.

  • Gabungkan tugas menjadi satu langkah.

  • Hindari penggunaan sys.log langkah yang berlebihan. Pertimbangkan untuk menggunakan logging panggilan.

Ringkasan praktik terbaik

Tabel berikut merangkum tips umum dan praktik terbaik yang direkomendasikan dalam dokumen ini.

Tips umum
Praktik terbaik

Langkah selanjutnya