Guide

Kontrakt først eller data først?

Du kan skrive datakontrakten før dataene finnes, eller lage den fra data du allerede har. Her er når hver vei passer, og hva de har felles.

Når et team bestemmer seg for å bruke datakontrakter, kommer det raskt et praktisk spørsmål: hvor begynner vi? Noen vil skrive kontrakten før en eneste tabell er bygget. Andre vil starte med tabellene de allerede har, og beskrive dem. Begge deler går an, og veiledningen Adopting Data Contracts beskriver dem som to måter å ta i bruk datakontrakter på: kontrakt først og data først. Rådet der er å velge den som passer situasjonen.

Denne artikkelen sammenligner de to veiene, med nettbutikken og datasettene kunde, ordre og produkt som eksempel. Den ene veien er ikke bedre enn den andre. De passer til ulike utgangspunkt, og de ender på samme sted.

Kontrakt først: start med kravene

Med kontrakt først skriver du kontrakten før dataproduktet finnes. Utgangspunktet er kravene fra dem som skal bruke dataene, ikke det som tilfeldigvis ligger i en database i dag.

Tenk deg at økonomiavdelingen i nettbutikken trenger et nytt datasett: daglig omsetning per produktkategori, til en rapport de skal sende ledelsen hver måned. Ingen har bygget det ennå. Før dataplattformteamet skriver noe kode, setter de seg ned med økonomi og blir enige om hva datasettet skal inneholde. Én rad per dag og kategori. Beløpet skal være uten merverdiavgift. Dataene skal være klare før arbeidsdagen begynner.

Den avtalen skrives ned som en kontrakt. I Open Data Contract Standard kan et første utkast se slik ut:

apiVersion: v3.2.0
kind: DataContract
id: omsetning-per-dag
version: 0.1.0
status: draft
description:
  purpose: Daglig omsetning per produktkategori til økonomis månedsrapport.
schema:
  - name: omsetning_per_dag
    properties:
      - name: dato
        logicalType: date
        required: true
      - name: produktkategori
        logicalType: string
        required: true
      - name: belop_eks_mva
        logicalType: number
        required: true

Kontrakten har status draft, fordi den ennå ikke er et løfte noen har tatt på seg. Versjonen er 0.1.0 av samme grunn. Når produsent og konsument er enige, settes status til active, og versjonen økes.

Fra her går arbeidet i en fast rekkefølge. Kontrakten kontrolleres mot standarden, for eksempel med datacontract lint fra Data Contract CLI. Så bygger dataplattformteamet datasettet etter kontrakten, mens økonomi kan begynne på rapporten sin samtidig, fordi de vet hva de vil få. Ut fra kontrakten kan det også lages startkode for begge sider, for eksempel dbt-modeller for produsenten og dbt-kilder for konsumenten. Til slutt testes det som ble bygget, mot kontrakten.

Når kontrakt først passer

Kontrakt først passer best når tre ting er sanne:

  • Dataproduktet er nytt. Det finnes ingen tabell å beskrive, så kontrakten er det første som kan skrives ned.
  • Konsumentene er kjent. Noen kan si hva de trenger. Uten konsumenter å spørre blir kravene gjetning, og kontrakten blir det også.
  • Det er verdt å bli enige først. Endringer er billigst før noe er bygget. Å gi en kolonne nytt navn i et utkast koster en linje. Å gjøre det samme etter at tre rapporter bruker kolonnen, koster en kontraktsendring med varsel og overgangsperiode.

Ulempen er at det tar tid før noe er i drift. Kontrakten må skrives, diskuteres og godkjennes før den første raden er levert. Og selv en god kontrakt kan møte virkeligheten dårlig: kildesystemet har kanskje ikke kategorien på hver ordre, eller beløpet uten avgift må beregnes på en måte ingen tenkte på. Da må kontrakten justeres mens den fortsatt er et utkast, og det er nettopp det utkastet er til for.

Data først: start med det som finnes

Med data først lager du kontrakten fra data som allerede finnes. Utgangspunktet er det faktiske skjemaet, ikke kravene.

I nettbutikken har kunde, ordre og produkt eksistert i flere år. De har konsumenter, rapporter og integrasjoner som bygger på dem, men ingen kontrakt. Her gir det lite mening å starte med blanke ark. Tabellene finnes, kolonnene har navn og typer, og det er de konsumentene faktisk bruker i dag.

Første steg er derfor å hente skjemaet inn, for eksempel med Data Contract CLI. Den kan importere et skjema fra blant annet SQL DDL, BigQuery, AWS Glue og Avro, og dokumentasjonen viser hvordan en kontrakt kan lages rett fra en eksisterende tabell. Resultatet er en kontrakt med tabeller, kolonner og typer, men uten det som ikke står i databasen: hva kolonnene betyr, hvem som eier dem, og hva som er lovet.

Det er dette som er arbeidet i data først. Teamet går gjennom kontrakten og legger til det som mangler:

  • Beskrivelser. Er belop i ordre med eller uten merverdiavgift? Svaret står ikke i skjemaet, men noen vet det.
  • Eier. Hvem svarer når noe er galt med kunde?
  • Kvalitetsregler. Én regel om gangen, for eksempel at ordre_id er unik, og med en kontroll for hver ny regel av at dataene fortsatt oppfyller den.
  • Status. Hvilke tabeller er i bruk, og hvilke er på vei ut?

Veiledningen Adopting Data Contracts beskriver data først som den raskeste måten å komme i gang på og få tilbakemelding fra konsumentene. Det gir mening: kontrakten beskriver noe som allerede virker, og konsumentene kan straks se om den stemmer med det de bruker.

Når data først passer

Data først passer best når kildene allerede finnes og er i bruk. Har dere en dataplattform i drift, gjelder det trolig mange av tabellene der.

Ulempen er at kontrakten i starten bare beskriver det som er, ikke det som er ønsket. Har ordre en kolonne med et uklart navn eller feil type, blir den med inn i kontrakten. Det er ikke galt, for kontrakten skal beskrive det konsumentene faktisk bygger på. Men det betyr at en import er et utgangspunkt, ikke en ferdig kontrakt. Uten beskrivelser, eier og regler er det bare skjemaet, skrevet ned i et nytt format.

Begge ender med en kontrakt i Git

Forskjellen mellom de to veiene ligger i hvor du starter. Hvor du ender, er det samme: en kontrakt som er gyldig mot standarden, som sier hva produsenten lover, og som ligger i versjonskontroll sammen med koden.

Fra det punktet er det ingen forskjell på en kontrakt som ble skrevet først, og en som ble importert. Begge endres gjennom samme prosess. En endring foreslås, gjennomgås og godkjennes i Git, og verktøy kan vise hva som er endret mellom to versjoner av kontrakten, for eksempel med datacontract changelog fra Data Contract CLI. Da kan de som gjennomgår endringen, se om den berører noe konsumentene er avhengige av. Begge testes mot dataene på samme måte, og begge kan vise historikken over hva som ble lovet når.

Ingenting hindrer dere i å bruke begge veiene samtidig. De eksisterende tabellene får kontrakter med data først, og nye dataprodukter skrives med kontrakt først. I nettbutikken kan kunde, ordre og produkt importeres og beskrives, mens det nye datasettet for omsetning per dag skrives som et utkast før noe bygges. Det nye datasettet bygger på de gamle, så de ender med kontrakter som henger sammen.

Hvordan du velger

Spørsmålet er ikke hvilken vei som er riktig, men hvilken som passer til datasettet foran deg. To spørsmål avgjør det meste:

  • Finnes dataene allerede? Hvis ja, start med data først. Det er raskere, og det beskriver det konsumentene faktisk bruker.
  • Vet du hvem som skal bruke dataene, og hva de trenger? Hvis dataene ikke finnes ennå og du har konsumenter å spørre, start med kontrakt først. Det gir dere en avtale før noe er bygget.

Finnes ingen av delene, er det verdt å finne konsumentene før du skriver kontrakten. Ellers skriver du ned dine egne antakelser og kaller dem en avtale.

Uansett hvilken vei du velger, er det første steget det samme: ett datasett. Velg en eksisterende tabell som mange bruker, eller et nytt datasett med en konsument som venter på det, og skriv kontrakten for det. Hvordan en kontrakt er bygget opp, og hvilke felt standarden har, står i artikkelen om Open Data Contract Standard.

Kilder