کتابخانه‌ی استاندارد · زبان و اجرا

وابستگی dependency

تزریق وابستگی به سبک google/wire: فراهم‌کننده‌های نام‌دار، اتصال میانجی، پاکسازی و بررسی گراف برای وابستگی گم‌شده و چرخه.

واردسازی وابستگی

نام آرگومان‌ها شناسه‌ی خود کد است و معادل فارسی ندارد؛ گونه‌ها، کلیدواژه‌ها و نام بسته‌ها با معادل فارسی نوشته می‌شوند.

وابستگی لایه‌های برنامه را به هم وصل می‌کند: یک مخزن، سرویسی که از آن استفاده می‌کند و کنترل‌کننده‌ای که از سرویس استفاده می‌کند. برای هر جزء یک فراهم‌کننده ثبت می‌کنید، نیازهایش را نام می‌برید و بالای گراف را می‌خواهید. هر جزء یک بار ساخته می‌شود و بستن پاکسازی‌ها را به ترتیب معکوس ساخت اجرا می‌کند.

سلام اطلاعات نوع در زمان اجرا ندارد، پس فراهم‌کننده‌ها با نامی که خودتان می‌گذارید، معمولاً نام نوع، شناخته می‌شوند. فراهم‌کننده تابعی است که ظرف را می‌گیرد و جزء را برمی‌گرداند و وابستگی‌هایش را با گرفتن می‌خواند. رشته دوم فراهم کردن همین وابستگی‌ها را فهرست می‌کند تا ساختن گراف پیش از اجرا کل گراف را بررسی کند.

فراهم‌کننده‌ها و بررسی گراف

ساختن گراف رشته خالی برمی‌گرداند اگر گراف سالم باشد و در غیر این صورت پیامی که مشکل را نام می‌برد: وابستگی گم‌شده، فراهم‌کننده تکراری یا چرخه وابستگی با مسیر کامل.

dependency-quickstart.salam
واردسازی وابستگی

ساختار Repo:
    همگانی rows: صحیح = 0
پایان

ساختار Service:
    همگانی repo: Repo = Repo {}
    همگانی تابع Count(): صحیح:
        برگشت این.repo.rows
    پایان
پایان

ساختار Handler:
    همگانی svc: Service = Service {}
    همگانی تابع Serve(): رشته:
        برگشت "rows=" + این.svc.Count()
    پایان
پایان

تابع ریشه:
    c := وابستگی.ساخت()
    وابستگی.فراهم کردن(c، "Repo"، ""، Repo {}، (_c: وابستگی.ظرف): برگشت Repo { rows = 3 } پایان)
    وابستگی.فراهم کردن(c، "Service"، "Repo"، Service {}، (cx: وابستگی.ظرف):
        ناپایا r := Repo {}
        _ok := وابستگی.گرفتن(cx، "Repo"، r)
        برگشت Service { repo = r }
    پایان)
    وابستگی.فراهم کردن(c، "Handler"، "Service"، Handler {}، (cx: وابستگی.ظرف):
        ناپایا s := Service {}
        _ok := وابستگی.گرفتن(cx، "Service"، s)
        برگشت Handler { svc = s }
    پایان)
    err := وابستگی.ساختن گراف(c)
    اگر err نابرابر "":
        سرچاپ err
        برگشت 1
    پایان
    ناپایا h := Handler {}
    _ok := وابستگی.گرفتن(c، "Handler"، h)
    سرچاپ h.Serve()
    وابستگی.بستن(c)
پایان
خروجیrows=3

گرفتن جزء را در صورت نبودن می‌سازد و در خروجی کپی می‌کند. اگر نام ناشناخته باشد یا در زمان اجرا به چرخه برسد نادرست برمی‌گرداند و خطا را پر می‌کند.

میانجی، مقدار و پاکسازی

پیوند نام یک میانجی را به فراهم‌کننده پیاده‌سازی آن وصل می‌کند. مقدار مقدار آماده‌ای مانند تنظیمات را ثبت می‌کند. هنگام بستن پاکسازی را به یک فراهم‌کننده می‌چسباند و بستن پاکسازی اجزای ساخته‌شده را از آخرین ساخته‌شده شروع می‌کند و ظرف را آزاد می‌کند.

خواندن خطاها

ساختن گراف فقط نام‌های ثبت‌شده و فهرست نیازهایشان را نگاه می‌کند و هیچ کارخانه‌ای را اجرا نمی‌کند. گراف سالم رشته خالی می‌دهد و سه پیام دیگر این‌ها هستند: missing dependency: Service needs Repo، duplicate provider: Repo و dependency cycle: A -> B -> C -> A. آن را یک بار هنگام شروع برنامه صدا بزنید و اگر متن خالی نبود همان‌جا بایستید. گرفتن با نامی که کسی ثبت نکرده نادرست برمی‌گرداند و missing provider: Nope را در خطا می‌گذارد.

dependency-guide-errors.salam
واردسازی وابستگی

تابع report(label: رشته، c: وابستگی.ظرف):
    msg := وابستگی.ساختن گراف(c)
    سرچاپ label + ":"، msg == "" ? "sound" : msg
    وابستگی.بستن(c)
پایان

تابع ریشه:
    ok := وابستگی.ساخت()
    وابستگی.فراهم کردن(ok، "Repo"، ""، 0، (_c: وابستگی.ظرف): برگشت 1 پایان)
    report("fine"، ok)

    missing := وابستگی.ساخت()
    وابستگی.فراهم کردن(missing، "Service"، "Repo"، 0، (_c: وابستگی.ظرف): برگشت 1 پایان)
    report("missing"، missing)

    twice := وابستگی.ساخت()
    وابستگی.فراهم کردن(twice، "Repo"، ""، 0، (_c: وابستگی.ظرف): برگشت 1 پایان)
    وابستگی.فراهم کردن(twice، "Repo"، ""، 0، (_c: وابستگی.ظرف): برگشت 2 پایان)
    report("duplicate"، twice)

    loop := وابستگی.ساخت()
    وابستگی.فراهم کردن(loop، "A"، "B"، 0، (_c: وابستگی.ظرف): برگشت 1 پایان)
    وابستگی.فراهم کردن(loop، "B"، "C"، 0، (_c: وابستگی.ظرف): برگشت 2 پایان)
    وابستگی.فراهم کردن(loop، "C"، "A"، 0، (_c: وابستگی.ظرف): برگشت 3 پایان)
    report("cycle"، loop)

    empty := وابستگی.ساخت()
    ناپایا n := 0
    سرچاپ "get:"، وابستگی.گرفتن(empty، "Nope"، n)، وابستگی.خطا(empty)
    وابستگی.بستن(empty)
پایان
خروجیfine: sound missing: missing dependency: Service needs Repo duplicate: duplicate provider: Repo cycle: dependency cycle: A -> B -> C -> A get: false missing provider: Nope

انتخاب پیاده‌سازی در محل سیم‌کشی

انتخاب را در یک تابع که ظرف را می‌سازد نگه دارید. اینجا مقدار تنظیمات را نگه می‌دارد، دو فراهم‌کننده به دو روش یک Store می‌سازند و پیوند بسته به محیط نام Store را به یکی از آن‌ها وصل می‌کند. کدی که Store می‌خواهد تغییری نمی‌کند. فقط اجزایی ساخته می‌شوند که کسی واقعاً خواسته است: از ۴ نام ثبت‌شده، ساخته شده در ظرف آزمایشی ۱ نام و در ظرف تولید ۲ نام را نشان می‌دهد.

dependency-guide-swap.salam
واردسازی وابستگی

ساختار Config:
    همگانی env: رشته = ""
پایان

ساختار Store:
    همگانی kind: رشته = ""
پایان

تابع build(env: رشته): وابستگی.ظرف:
    c := وابستگی.ساخت()
    وابستگی.مقدار(c، "Config"، Config { env = env })
    وابستگی.فراهم کردن(c، "Mem"، ""، Store {}، (_c: وابستگی.ظرف): برگشت Store { kind = "memory" } پایان)
    وابستگی.فراهم کردن(c، "Disk"، "Config"، Store {}، (cx: وابستگی.ظرف):
        ناپایا cfg := Config {}
        _ok := وابستگی.گرفتن(cx، "Config"، cfg)
        برگشت Store { kind = "disk for " + cfg.env }
    پایان)
    اگر env == "test":
        وابستگی.پیوند(c، "Store"، "Mem")
    وگرنه:
        وابستگی.پیوند(c، "Store"، "Disk")
    پایان
    برگشت c
پایان

تابع ریشه:
    for_env := ["test"، "prod"]
    هر env در for_env:
        c := build(env)
        سرچاپ env + ":"، وابستگی.ساختن گراف(c) == "" ? "sound" : "broken"
        ناپایا s := Store {}
        _ok := وابستگی.گرفتن(c، "Store"، s)
        سرچاپ "  store is"، s.kind
        built := وابستگی.ساخته شده(c)
        سرچاپ "  built"، built.طول()، "of"، وابستگی.تعداد(c)
        built.آزادکن()
        وابستگی.بستن(c)
    پایان
پایان
خروجیtest: sound store is memory built 1 of 4 prod: sound store is disk for prod built 2 of 4

یک بار ساختن، به ترتیب معکوس بستن

هر فراهم‌کننده تک‌نمونه است: دو بار خواستن Cache کارخانه‌اش را یک بار اجرا می‌کند و از همان مقدار دو نسخه می‌دهد. پاکسازی‌هایی که با هنگام بستن ثبت شده‌اند از آخرین جزء ساخته‌شده تا اولین اجرا می‌شوند، پس کش پیش از پایگاه داده‌ای که در دست دارد بسته می‌شود. بستن دوم کاری نمی‌کند.

dependency-guide-lifecycle.salam
واردسازی وابستگی

ناپایا made := 0

ساختار Db:
    همگانی id: صحیح = 0
پایان

ساختار Cache:
    همگانی db: Db = Db {}
پایان

تابع ریشه:
    c := وابستگی.ساخت()
    وابستگی.فراهم کردن(c، "Db"، ""، Db {}، (_c: وابستگی.ظرف):
        made++
        برگشت Db { id = 7 }
    پایان)
    وابستگی.فراهم کردن(c، "Cache"، "Db"، Cache {}، (cx: وابستگی.ظرف):
        ناپایا d := Db {}
        _ok := وابستگی.گرفتن(cx، "Db"، d)
        برگشت Cache { db = d }
    پایان)
    وابستگی.هنگام بستن(c، "Db"، Db {}، (d: Db): سرچاپ "closing db"، d.id پایان)
    وابستگی.هنگام بستن(c، "Cache"، Cache {}، (k: Cache): سرچاپ "closing cache over"، k.db.id پایان)

    before := وابستگی.ساخته شده(c)
    سرچاپ "before"، before.طول()
    before.آزادکن()
    ناپایا a := Cache {}
    ناپایا b := Cache {}
    _x := وابستگی.گرفتن(c، "Cache"، a)
    _y := وابستگی.گرفتن(c، "Cache"، b)
    سرچاپ "factory runs"، made
    built := وابستگی.ساخته شده(c)
    سرچاپ "order"، built.بگیر(0)، built.بگیر(1)
    built.آزادکن()
    وابستگی.بستن(c)
    وابستگی.بستن(c)
    سرچاپ "done"
پایان
خروجیbefore 0 factory runs 1 order Db Cache closing cache over 7 closing db 7 done

گونه‌ها

ظرف Container

ساختار ظرف
یک ظرف وابستگی: فراهم‌کننده‌های ثبت‌شده و اجزایی که تا اینجا ساخته شده‌اند. نسخه‌های آن وضعیت مشترک دارند.
نامانگلیسیگونهتوضیح
وضعیتstState*وضعیت مشترک ظرف.

تابع‌ها

ساخت New

تابع ساخت(): ظرف
یک ظرف خالی می‌سازد.
dependency-Provide.salam
واردسازی وابستگی

تابع ریشه:
    c := وابستگی.ساخت()
    وابستگی.فراهم کردن(c، "Base"، ""، 0، (_c: وابستگی.ظرف): برگشت 10 پایان)
    وابستگی.فراهم کردن(c، "Double"، "Base"، 0، (cx: وابستگی.ظرف):
        ناپایا b := 0
        _ok := وابستگی.گرفتن(cx، "Base"، b)
        برگشت b * 2
    پایان)
    ناپایا d := 0
    اگر وابستگی.گرفتن(c، "Double"، d):
        سرچاپ d
    پایان
    وابستگی.بستن(c)
پایان
خروجی20

فراهم کردن Provide

تابع فراهم کردن<T>(c: ظرف، name: رشته، needs: رشته، _witness: T، factory: تابع(ظرف): T)
فراهم‌کننده‌ای را با یک نام ثبت می‌کند. needs فهرستی از نام فراهم‌کننده‌هاست که با ویرگول جدا شده‌اند، شاهد مقداری از گونه جزء است و فقط T را مشخص می‌کند و factory جزء را می‌سازد.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: dependency-Provide.salam

مقدار Value

تابع مقدار<T>(c: ظرف، name: رشته، v: T)
مقدار آماده‌ای مانند تنظیمات را با یک نام ثبت می‌کند.
dependency-Value.salam
واردسازی وابستگی

ساختار Config:
    همگانی port: صحیح = 0
پایان

تابع ریشه:
    c := وابستگی.ساخت()
    وابستگی.مقدار(c، "Config"، Config { port = 8080 })
    ناپایا cfg := Config {}
    اگر وابستگی.گرفتن(c، "Config"، cfg):
        سرچاپ cfg.port
    پایان
    وابستگی.بستن(c)
پایان
خروجی8080

پیوند Bind

تابع پیوند(c: ظرف، iface: رشته، concrete: رشته)
نام iface را به فراهم‌کننده concrete وصل می‌کند.
dependency-Bind.salam
واردسازی وابستگی

میانجی Greeter:
    تابع Hello(): رشته
پایان

ساختار English:
    همگانی تابع Hello(): رشته:
        برگشت "hello"
    پایان
پایان

تابع ریشه:
    c := وابستگی.ساخت()
    وابستگی.فراهم کردن(c، "English"، ""، English {}، (_c: وابستگی.ظرف): برگشت English {} پایان)
    وابستگی.پیوند(c، "Greeter"، "English")
    ناپایا g := English {}
    اگر وابستگی.گرفتن(c، "Greeter"، g):
        سرچاپ g.Hello()
    پایان
    وابستگی.بستن(c)
پایان
خروجیhello

هنگام بستن OnClose

تابع هنگام بستن<T>(c: ظرف، name: رشته، _witness: T، f: تابع(T))
پاکسازی را به یک فراهم‌کننده می‌چسباند. اگر جزء ساخته شده باشد بستن آن را صدا می‌زند.
dependency-OnClose.salam
واردسازی وابستگی

ساختار Conn:
    همگانی id: صحیح = 0
پایان

تابع ریشه:
    c := وابستگی.ساخت()
    وابستگی.فراهم کردن(c، "Conn"، ""، Conn {}، (_c: وابستگی.ظرف): برگشت Conn { id = 7 } پایان)
    وابستگی.هنگام بستن(c، "Conn"، Conn {}، (v: Conn): سرچاپ "closing"، v.id پایان)
    ناپایا x := Conn {}
    _ok := وابستگی.گرفتن(c، "Conn"، x)
    وابستگی.بستن(c)
پایان
خروجیclosing 7

ساختن گراف Build

تابع ساختن گراف(c: ظرف): رشته
گراف را بدون ساختن چیزی بررسی می‌کند. اگر سالم باشد متن خالی برمی‌گرداند و در غیر این صورت پیامی که وابستگی گم‌شده، فراهم‌کننده تکراری یا چرخه را نام می‌برد.
dependency-Build.salam
واردسازی وابستگی

تابع ریشه:
    c := وابستگی.ساخت()
    وابستگی.فراهم کردن(c، "Service"، "Repo"، 0، (_c: وابستگی.ظرف): برگشت 1 پایان)
    سرچاپ وابستگی.ساختن گراف(c)
    وابستگی.فراهم کردن(c، "Repo"، "Service"، 0، (_c: وابستگی.ظرف): برگشت 2 پایان)
    سرچاپ وابستگی.ساختن گراف(c)
    وابستگی.بستن(c)
پایان
خروجیmissing dependency: Service needs Repo dependency cycle: Service -> Repo -> Service

گرفتن Get

تابع گرفتن<T>(c: ظرف، name: رشته، out &: T): منطقی
اگر جزء هنوز وجود نداشته باشد آن را می‌سازد و در out کپی می‌کند. اگر نام ناشناخته باشد یا به چرخه برسد نادرست برمی‌گرداند و خطا را پر می‌کند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: dependency-Provide.salam

خطا Error

تابع خطا(c: ظرف): رشته
آخرین خطای ظرف که اگر خطایی نباشد خالی است.

تعداد Count

تابع تعداد(c: ظرف): صحیح
شمار نام‌های ثبت‌شده.

ساخته شده Built

تابع ساخته شده(c: ظرف): وکتور<رشته>
نام‌هایی که ساخته شده‌اند، به ترتیب ساخته شدن.

بستن Close

تابع بستن(c: ظرف)
پاکسازی‌ها را از آخرین جزء ساخته‌شده شروع می‌کند و ظرف را آزاد می‌کند. دوبار صدا زدنش بی‌خطر است.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: dependency-OnClose.salam