Schema Design Patterns
Schema yang baik = API yang mudah dipakai dan berkembang. Schema yang buruk = tech debt yang mahal.
1. Noun-based Types, Verb-based Mutations
# ✅ Good
type User { ... }
type Mutation {
createUser(...): User!
updateUser(...): User!
}
# ❌ Bad — verb di type
type CreateUserResponse { ... }
2. Input Types untuk Mutations
# ✅ Grouped input
mutation {
createUser(input: CreateUserInput!) { ... }
}
# ❌ Banyak arguments
mutation {
createUser(name: String!, email: String!, age: Int, role: Role!) { ... }
}
3. Nullable by Default, Non-null Deliberately
type User {
id: ID! # Always exists
name: String! # Always exists
bio: String # Might be null — that is OK
avatar: String # Might be null
}
4. Connection Pattern untuk Lists
# Relay-style connections
type Query {
users(first: Int, after: String): UserConnection!
}
# Bukan:
type Query {
users: [User!]! # No pagination, no metadata
}
5. Schema Evolution (No Versioning)
# Tambah field baru — non-breaking
type User {
name: String!
displayName: String! # NEW — clients yang tidak query ini tidak terpengaruh
}
# Deprecate field — jangan hapus langsung
type User {
name: String! @deprecated(reason: "Use displayName instead")
displayName: String!
}
6. Avoid Anemic Types
# ❌ Anemic — just data
type User {
id: ID!
name: String!
}
# ✅ Rich — includes related data and computed fields
type User {
id: ID!
name: String!
posts(first: Int): PostConnection!
postCount: Int!
isOnline: Boolean!
memberSince: String!
}