「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > モノリポジトリ内の共有ライブラリの実際の例

モノリポジトリ内の共有ライブラリの実際の例

2024 年 11 月 9 日に公開
ブラウズ:485

A practical example of shared libraries in a monorepo

モノリポジトリでの作業の最も強力な側面の 1 つは、パッケージ/チーム/階層間でコードを共有できることです。この投稿では、非常に単純な現実世界のシナリオを説明してみます

シナリオ例

モノリポジトリの他の部分に役立つと思われるファイル サイズをメガバイト単位で表示するライブラリを開発したいと想像してください。ライブラリはサイズを整数 (例: 2048 バイト) として受け入れ、人間化された文字列 (例: 2 MB) を返すことができます。品質保証を追加するために、同じためのテストも作成します。

Bazel はどのようにしてコードの共有を可能にしますか?

上記のシナリオから、この関数を共有ライブラリとして開発し、使用するために別のパッケージによってインポートする必要があることがわかりました。 Bazel では、ライブラリ内で関数を定義し、それを必要とする他のサービスにエクスポートできるため、これが非常に簡単になります。この投稿の下部にリンクされている以前の投稿で説明したように、他のどのライブラリがそれをインポートして使用できるようにするかを制御することもできます。

コーディングを始めましょう

コードを整理するために、ワークスペースのルートにライブラリ ディレクトリを作成し、humanize_filesize という子ディレクトリを作成します。そこにライブラリ コードを記述します。

humanize_filesize.go に非常に初歩的な Go コードを書いてみましょう

package humanize_filesize

import "fmt"

// GetHumanizedFilesize takes size_in_bytes as an int32 pointer and returns the size in megabytes.
func GetHumanizedFilesize(size_in_bytes *int32) string {
    if size_in_bytes != nil {
        size_in_megabytes := float64(*size_in_bytes) / (1024 * 1024)
        return fmt.Sprintf("%.4f MB", size_in_megabytes)
    }
    return "0 MB"
}

このコードは単純に int32 を入力として受け取り、計算された読み取り可能なメガバイト文字列を 40 進精度で返します

この関数は決して包括的ではなく、間違いなく改善の余地がありますが、それはこの演習の目的ではありません。

また、ロジックが意図したとおりに動作していることを主張します。humanize_filesize_test.go
というファイルに go コードと一緒に非常に基本的なテストを追加します。

package humanize_filesize

import (
    "testing"
)

func TestHumanizeFilesize(t *testing.T) {
    tests := []struct {
        name          string
        size_in_bytes *int32
        expected      string
    }{
        {
            name:          "nil bytes",
            size_in_bytes: nil,
            expected:      "0 MB",
        },
        {
            name:          "2048 bytes",
            size_in_bytes: int32Ptr(2048),
            expected:      "0.0020 MB",
        },
        {
            name:          "0 bytes",
            size_in_bytes: int32Ptr(0),
            expected:      "0.0000 MB",
        },
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := GetHumanizedFilesize(tt.size_in_bytes)
            if result != tt.expected {
                t.Errorf("expected %s, got %s", tt.expected, result)
            }
        })
    }
}

func int32Ptr(n int32) *int32 {
    return &n
}

入力として nil、int32、0 の基本的なテストを行う非常に単純なテスト

次に、この関数をエクスポートして、他のパッケージまたはサービス内にインポートできるようにする方法の重要な部分を説明します。ここで BUILD.bazel ファイルを定義する必要があります。

load("@rules_go//go:def.bzl", "go_library", "go_test")

go_library(
    name = "humanize_filesize",
    srcs = ["humanize_filesize.go"],
    importpath = "basil/libraries/humanize_filesize",
    visibility = ["//visibility:public"],
)

go_test(
    name = "humanize_filesize_test",
    srcs = ["humanize_filesize_test.go"],
    embed = [":humanize_filesize"],
)

ここでは 2 つの主要なルールを定義します。 1 つは実際のライブラリ用で、もう 1 つは作成したテスト ファイル用です。

go_library は、ターゲットの humanize_filesize が、importpath で指定されたパスによってインポートできるソースの 1 つとして humanize_filesize.go を使用することを定義し、インポートする他のパッケージのワークスペース内で公開されます。可視性を制御する方法については、今後の投稿で学びます。

go_test は、go_library の出力からコードを埋め込むテスト ターゲットを定義します。

この時点で、次のようにテスト スイートを実行してライブラリをテストできるはずです

bazel ビルド //... && bazel 実行 //libraries/humanize_filesize:humanize_filesize_test

次のようなテスト出力が表示され、すべてのテストが成功したことがわかります。

INFO: Analyzed target //libraries/humanize_filesize:humanize_filesize_test (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //libraries/humanize_filesize:humanize_filesize_test up-to-date:
  bazel-bin/libraries/humanize_filesize/humanize_filesize_test_/humanize_filesize_test
INFO: Elapsed time: 0.392s, Critical Path: 0.24s
INFO: 5 processes: 1 internal, 4 darwin-sandbox.
INFO: Build completed successfully, 5 total actions
INFO: Running command line: external/bazel_tools/tools/test/test-setup.sh libraries/humanize_filesize/humanize_filesize_test_/humanize_filesize_test
exec ${PAGER:-/usr/bin/less} "$0" || exit 1
Executing tests from //libraries/humanize_filesize:humanize_filesize_test
-----------------------------------------------------------------------------
PASS

?うわー!! ?これで、ライブラリが意図したとおりに動作していることがわかりました。

次に、次の go コードと BUILD.bazel ファイルを使用してワークスペースのルートに作成するサービス ディレクトリ内のサービス service1 でこのライブラリを使用しましょう。

service1.go

package main

import (
    "basil/libraries/humanize_filesize"
    "fmt"
    "math/rand"
)

func main() {
    v := rand.Int31n(1000000)
    fmt.Printf(`%d bytes = %s\n`, v, humanize_filesize.GetHumanizedFilesize(&v))
}

BUILD.bazel

load("@rules_go//go:def.bzl", "go_binary", "go_library")

go_library(
    name = "service1_lib",
    srcs = ["service1.go"],
    importpath = "basil/services/service1",
    visibility = ["//visibility:private"],
    deps = ["//libraries/humanize_filesize"],
)

go_binary(
    name = "service1",
    embed = [":service1_lib"],
    visibility = ["//visibility:public"],
)

go コードは非常に単純で、前に宣言したライブラリをインポートし、ライブラリから GetHumanizedFilesize 関数を使用してランダムな整数値を渡し、出力を出力します。

ここで bazel build //services/service1 を実行すると、bazel は開発したライブラリを含むターゲットのすべての依存関係を解決してビルドします。

バイナリ ターゲットが 1 つだけ定義されているため、

service1 は bazel run //services/service1 を使用して実行できるようになりました。複数のバイナリ ターゲット (例:serviceX) がある場合は、bazel run //services/service1:serviceX を使用してそれを実行できます。デフォルトでは、ターゲットを指定しない場合、bazel は常にディレクトリと同じ名前のバイナリ ターゲットを見つけて実行しようとします。

それでは...それで。モノリポジトリの他の部分で使用できる最初の共有ライブラリを作成しました。

この例のすべてのコードは、https://github.com/nixclix/basil/pull/3/commits/61c673b8757860bd5e60eb2ab6c35f3f4da78c87 にあります。

この投稿の内容が気に入ったら、お気軽に共有してください。また、この投稿についてどう思うか、改善してほしい点がある場合は、購読してコメントを残してください。

リリースステートメント この記事は次の場所に転載されています: https://dev.to/nikhildev/a-practical-example-of-shared-libraries-in-a-monorepo-2548?1 侵害がある場合は、[email protected] までご連絡ください。それを削除するには
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3