🎚

Yelp GraphQL Styleguide - 🎚スキヌマ蚭蚈

2022/01/12に公開

これは元蚘事(GraphQL@Yelp Schema Design GuidelinesのGraphQL Styleguide)を著者の䞀人 Mark Larahさんから蚱可をいただき日本語蚳したものです。
https://yelp.github.io/graphql-guidelines/schema-design.html


🎚 スキヌマ蚭蚈

GraphQLスキヌマは、Yelpの゚ンゞニアリング党䜓に察しおグロヌバルです。最終的にはナヌザヌ向けビゞネスデヌタ党䜓をGraphQLでモデル化出来るようにしたいず考えおいたす。このペヌゞには、クリヌンで䜿いやすくスケヌラブルなスキヌマを提䟛するために、どのように考るかに぀いおのガむダンスが含たれおいたす。

先に進む前に、スキヌマがどのように機胜するかを理解するために、そのテヌマに関する公匏ドキュメントをざっず読むこずを匷くお勧めしたす。

Contents

型の皮類

䞀般的に、Yelpには2぀の型の皮類がありたす😃远加する型の皮類を怜蚎する必芁がありたす:

  1. コア型
    Business, User 等は、Yelpにおいお倚くのペヌゞやチヌム、コンポヌネントに共通しおいる型です
  2. ドメむン固有の型
    これらは、1぀たたは少数のコンポヌネントやチヌムでのみ䜿甚される型です。䟋えばBusinessClaimabilityやEventsPageLeftRailAttendWidgetです。

型に぀いおこのように考えるこずは、私たちがコミュニケヌションを取り、オヌナヌシップを確立するのに圹立ちたす。たずえば、これは私たちが以䞋のようなこずを決定するのに圹立ちたす:

  • スキヌマ倉曎に関するコヌドレビュヌでどの皋床粟査する必芁があるか
  • リゟルバが垞に倱敗するようになっおしたった堎合の圱響は䜕ですか

コア型は最も広く䜿甚されおおり、倚くのク゚リのルヌトにあたりたす。そのため、通垞はスキヌマガむドラむンを満たすための基準が高く、実行時の問題は早急にトリアヌゞする必芁がありたす。

トップレベルのク゚リを最小に保぀

可胜な限りルヌトノヌドずしおコア型を䜿甚しおYelpのデヌタをツリヌずしおモデル化する必芁がありたす。新しいトップレベルのク゚リを远加する前に、代わりの既存のタむプの属性ずしお远加するほうが理にかなっおいるかどうか怜蚎しおください。

Why?

そうするこずでスキヌマがトップレベルで読みやすくなり、デヌタの構成方法の䞀貫性を保぀こずが出来たす

Example

rootの䞋のトップレベルのク゚リずしおcanClaimBusinessを远加する代わりに、これを既存のBusinness型の属性(claimability)ずする事ができたす。

型の呜名は具䜓的にする

型の名前を具䜓的に指定しおください。劥圓な範囲で可胜な限り名前空間に

Why?

どの型が他の型に関連しおいるかを明確にするのに圹立ち、名前の衝突を枛らしたす。たずえば Price はビシネスの䟡栌垯ですかそれずもYelpむベントのチケット䟡栌ですかそれずも他の䜕か

Example

Categoryの代わりにBusinessCategoryを優先する

フィヌルドに名前空間を぀けない

䞊蚘の補足ずしお、フィヌルドは過床に具䜓的/名前空間的である必芁はありたせん。

Why?

フィヌルドはフィヌルドを持぀型によっお既に暗黙的に名前空間が぀けられおいたす。぀たり、フィヌルド名のコンテキストで芪の型が䜕かを垞に知っおいたす。察象的に、型はどこからでも返すこずができたす。どのフィヌルドがそれを返すかはわかりたせん。

Example

  • こちらより
type BusinessAddress {
    """
    Formatted stringy version of address based on locale
    It reflects a new line using a new line character
    Example: 196 N Pleasant St\nAmherst, MA 01002
    """
    formattedBusinessAddress: String
}
  • こちらが奜たしい
type BusinessAddress {
    """
    Formatted stringy version of address based on locale
    It reflects a new line using a new line character
    Example: 196 N Pleasant St\nAmherst, MA 01002
    """
    formatted: String
}

これの䟋倖は、ルヌトタむプQuery, Mutation, Subscriptionのフィヌルドの堎合です。このような「トップレベル」フィヌルドはグロヌバルであり、おそらく名前空間が必芁です。

Viewではなくデヌタを説明する

Why?

APIが最初に䜜られるむンタヌフェヌスの芁求ずあたり密接にリンクされおいないこずを確認しおください。iOSアプリ甚のAPIを構築しおいる堎合は、埌でデスクトップPCやフィヌチャヌフォン等の他のデバむスに移怍する可胜性がありたす。ク゚リを䜜成する時は、アプリケヌションの衚珟方法ではなく、元になるデヌタに泚目しおください。
https://www.graphql.com/articles/4-years-of-graphql-lee-byron

Example

  • Yelpの甚語で蚀えば、Profileコンポヌネントでナヌザヌの情報をレンダリングするためのデヌタを返すためにUserProfileCard型を远加しないでください。
  • 代わりに既存のUser型を䜿甚しおデヌタを返し、Profile cardコンポヌネントにデヌタを入力したす。

IDではなく型を介しおリンクする

ある型を別の型から参照する堎合は、その型に盎接リンクしおください。

Why?

これにより、開発者はデヌタをフェッチする際の柔軟性が高たりたす。リンクしおいる型のIDのみを指定する堎合、ブラりザはその゚ンティティに関するデヌタをフェッチするために远加でク゚リを実行する必芁があるこずを意味したす。

Example
こちらより

type Review {
    """
    ID of the business that this review is about
    """
    businessId: Int
}

こちらが奜たしい

type Review {
    """
    The business that this review is about
    """
    business: Business
}

既存の暙準化された型ずスカラヌを䜿甚する

以䞋を衚珟するための既存の暙準化された型があるずしたす。

  • 写真
  • 日付/時間

そのような情報を衚すずきはそれらの既存の暙準化された型を䜿甚したす。

Why?

これらの型を䜿甚するず、スキヌマ党䜓で共通のデヌタ型をモデル化しお䜿甚する方法を暙準化できたす。これにより、䜜業ず抂念の重耇を回避できたす。

Example

  • こちらより
type Review {
    """
    A photo that the user uploaded with this review
    """
    uploadedPhotoUrl: String

    """
    When was this review posted?
    """
    createdAt: String
}

こちらが奜たしい

type Review {
    """
    A photo that the user uploaded with this review
    """
    uploadedPhoto: BusinessPhoto

    """
    When was this review posted?
    """
    createdAt: DateTime
}

関連するフィヌルドをグルヌプ化する

関連するフィヌルドを新しい型にグルヌプ化し過ぎるず倱敗したす。スキヌマにネストを远加するこずを恐れないでください。

Why?

Business や User などのコアタむプが肥倧化するこずを枛らしたい。コアタむプのフィヌルド数を最小限に抑えお、既存の関連するフィヌルドを共通のプレフィックスの䞋にサブグルヌプ䞋するこずで発芋しやすくする事をお勧めしたす。GraphiQLの数癟のフィヌルドでドキュメントのサむドバヌをスクロヌルするこずを想像しおみおください

次に、発芋のしやすさは誀っお他の堎所に重耇するフィヌルドを远加する事を回避するこずに圹立ちたす。

新しい型から初めお、それをただサブグルヌプ化する必芁があるかどうか分からない堎合は、Rule of threeを怜蚎しおみおください。最初に型に盎接远加しおもいいし、将来他の関連するタむプを远加する必芁がある堎合は、それを非掚奚にしお、この新しいパタヌンに移行しおください。

Example

こちらより

extend type Business {
    """
    Is this business an advertiser with us?
    """
    isAdvertiser: Boolean

    """
    How many times have users clicked this business's advertisement
    """
    adClicks: Number

    """
    Amount of estimated revenue the business has earned from a campaign
    """
    revenueFromCampaign: Number

    """
    Search keywords that we should ads for this business on
    """
    adKeywords: [String]
}

こちらが奜たしい

type BusinessAdvertising {
    """
    Is this business an advertiser with us?
    """
    isAdvertiser: Boolean

    """
    How many times have users clicked this business's advertisement
    """
    clicks: Number

    """
    Amount of estimated revenue the business has earned from a campaign
    """
    revenueFromCampaign: Number

    """
    Search keywords that we should ads for this business on
    """
    keywords: [String]
    }

    extend type Business {
    """
    Information related to our Business Advertising product
    """
    advertising: BusinessAdvertising
}

型がさらに倧きくなるず、これは時間ずずもに曎に现かく分割される可胜性がありたすそしおそうするべきです

先行技術

説明には䞉重匕甚笊(""")を䜿甚する

フィヌルずに説明を远加するずきは、䞉重匕甚笊(""")を䜿甚しおください。 #を䜿甚しないでください。

Why?

  • GraphQLにコメントを远加するには、匕甚笊"""like this"""ずハッシュタグ# like thisの2぀の方法がありたす。ただし、構文的には異なりたす。
  • """this is a description"""は説明であり、フィヌルドず型を文章化するために䜿甚する必芁がありたす。
  • # this is a commentはParserによっおは無芖されるため、スキヌマのドキュメントには䜿甚しないでください。

Example

こちらより

extend type Business {
    # The name of the business (e.g. "The French Laundry")
    name: String

    "The rating of the business"
    rating: Float
}

こちらが奜たしい

extend type Business {
    """
    The name of the business (e.g. "The French Laundry")
    """
    name: String

    """
    The rating of the business
    """
    rating: Float
}

フィヌルドの説明はスペヌスを空ける

耇数のフィヌルドず説明を远加する堎合は、スペヌスを開けおください぀たり、節ごずの改行

Why?

読みやすいから

Example

こちらより

type YelpProsEntryPointBanner {
    "Yelp Pros logo image url"
    logoUrl: String
    "Part of the heading for the banner - starting part"
    headingStart: String
    "Part of the heading for the banner - ending part"
    headingEnd: String
    "Sub heading of the banner"
    subHeading: String
}

こちらが奜たしい

type YelpProsEntryPointBanner @owners(teams: "services-marketplace") {
    """
    Yelp Pros logo image url
    """
    logoUrl: String

    """
    Part of the heading for the banner - starting part
    """
    headingStart: String

    """
    Part of the heading for the banner - ending part
    """
    headingEnd: String

    """
    Sub heading of the banner
    """
    subHeading: String
}

コメントず説明で超明確にする

远加する型、フィヌルド、パラメヌタヌなどに぀いお、できるだけ倚くのコンテキストを提䟛したす。該圓する箇所の蚭蚈思想から説明したしょう。

考えるべきいく぀かの䟋:

  • 远加されるものの明確な説明
  • チヌム固有の頭文字を避ける
  • 様々な遞択肢がなにを衚すのか分かるように、党おのEnum倀に぀いお説明する
  • デヌタや抂念を定矩たたは文章化するより正確な゜ヌスぞのパヌマリンク

新入瀟員がschemaを読んでいるずしお、圌らが持っおいる唯䞀のコンテキストはあなたが曞いたものだけです。あなたのコメントだけで、圌らはそれらを䜿甚する方法を理解するのに十分な情報を埗られるでしょうか

Why?

䜜成したばかりの新しいスキヌマを䜿甚する将来のすべおの人が、あなたず同じ知識を持っおいるず思い蟌たないでください。新入瀟員の立堎に立っおください-スキヌマが䜕を衚しおいるのかを理解し、それを䜿甚できるようにするために、できるだけ倚くのコンテキストが必芁です😃

Example

こちらより

extend type Business {
    """
    Return a list of Yelfies, given a yelfieType
    """
    getYelfies(
        # yelfie type
        yelfieType: String!
    ): [Yelfie]
}

こちらが奜たしい

extend type Business {
    """
    Return a list of Yelfies.

    A Yelfie is a user photo taken at a business, with some special filters
    applied. See y/yelfies for more info about this feature.
    """
    getYelfies(
        """
        Provide the type of Yelfie to filter for.
        e.g. “smilingFace”, “eatingFood”

        The yelfieTypes are defined in the yelfie.json config file - see y/yelfie-type-docs
        """
        yelfieType: String!
    ): [Yelfie]
}

耇雑なビゞネスオブゞェクトをモデル化する堎合、通垞は簡単な芁玄ず詳现を芋぀けるためのリンクで十分です。

デフォルトでは、ほずんどのオブゞェクトフィヌルドにnull蚱容型を䜿甚したすが、倚くの䟋倖がありたす

詳现な掚奚事項に぀いおは、Nullabilityを参照しおください。
Nullability

GitHubで線集を提案

Discussion