Mennesker har vanskelig for å se helheten i et problem uten å bruke mye tid og krefter på det. Dette skjer spesielt når man jobber med store og komplekse applikasjoner. Hva er bivirkningene av endringene mine? Hvorfor påvirker denne linjen testene av en ekstern del av kodebasen? Det finnes ingen perfekt eller komplett løsning, men Shopify har utviklet et verktøy som sannsynligvis vil hjelpe deg og teamet ditt.
Innledning
For å kunne snakke om Packwerkmå vi først introdusere noen begreper.
- Samhold: er et mål på hvor mye elementene i en modul eller klasse hører sammen.
- Kobling: refererer til graden av avhengighet mellom moduler eller klasser.
- Grenser: refererer til barrierer mellom kode. I dette tilfellet refererer en kodegrense til ulike problemområder innenfor samme kodebase.
- Modularisering: prosessen med å dele et programvaresystem inn i flere separate moduler der hver modul fungerer uavhengig av hverandre.
Problemer
Som vi vet, Ruby gir ikke en god løsning for å håndheve kodegrenser. Vi kan spesifisere synligheten, men alle avhengigheter vil bli lastet inn i det globale navnerommet. I store eller monolittiske applikasjoner skaper denne mangelen på grenser følgende problemer.
- Lavt samhold,
- Høy kobling,
- Spagettikode.
I et forsøk på å modularisere Shopifys monolitt og håndheve grenser, prøvde de forskjellige løsninger uten å oppnå de forventede resultatene:
- Innstilling av private konstanter,
- Etablering av grenser gjennom perler,
- Bruk av tester for å forhindre kryss-sammenhenger,
- Ved hjelp av Rubys moduleringsperle,
- Opprettelse av mikrotjenester.
Med all kunnskapen fra tidligere forsøk bestemte de seg for å lage sitt eget verktøy: Packwerk.
Packwerk
Hva er Packwerk?
Packwerk er et statisk analyseverktøy som brukes til å håndheve grenser mellom grupper av Ruby filer som heter pakker.
Hva er en pakke?
A pakke er en mappe som inneholder autoladet kode. Shopifys team oppfordrer til å bruke de beste designpraksisene når du lager pakker.
- Vi bør pakke sammen ting som har høy funksjonell samhørighet,
- Pakkene bør være relativt løst koblet til hverandre.
Typer av grensekontroller
Vi kan håndheve personvern og avhengighetsgrenser, kontrollere brudd på grensene og sykliske avhengigheter.
Packwerk i praksis
Det finnes ikke én bestemt måte å strukturere eller restrukturere applikasjonen din på når du oppretter pakker. I denne artikkelen skal vi følge tilnærmingen som er foreslått av
Stephan Hagemann i Gradvis modularisering for Ruby on Rails.
Velg prosjekt
Du kan opprette en ny prosjekt eller velg et av prosjektene dine. Jeg bestemte meg for å bruke et åpen kildekode-prosjekt som heter CodeTriage. Det er viktig å nevne at vi trenger en Rails 6-applikasjon siden Packwerk bruker Zeitwerk.
Initialiser Packwerk
Først må vi legge til gemmen i Gemfilen vår på følgende måte gem 'packwerk'
og kjør deretter pakke
i konsollen. Så er vi klare til å initialisere perlen ved å kjøre packwerk init
.
Etter det legger vi merke til at Packwerk genererte tre filer for oss:
-
packwerk.yml
-
package.yml
-
bøyninger.yml
packwerk.yml er konfigurasjonsfilen til Packwerk der vi blant annet definerer inkluderte og ekskluderte filer, lister opp lastestier og definerer bøyningsfilen;
package.yml er konfigurasjonsfilen for en pakke. I denne filen legger vi til konfigurasjonen for grensene for pakken vår. Enhver mappe med package.yml vil bli gjenkjent som en pakke av Packwerk. Sånn, ja, Packwerk skapte vår første
pakken, og vi kaller den rot pakke.
bøyninger.yml er der vi plasserer våre egendefinerte bøyninger og akronymer i tilfelle vi bruker dem.
Du finner mer informasjon om filene og konfigurasjonen av dem i
Packwerk.
Packwerk eiendommer
For at modularisering skal fungere, trenger vi tre grunnleggende egenskaper: en navngitt beholder, dens innhold, og eksplisitt avhengigheter på andre containere. Så la oss definere disse egenskapene i Packwerk:
-
Navn: Navnet på en pakke er den relative banen fra roten til
søknad.
-
Innhold: Når vi plasserer en package.yml i en mappe, er alle filene i mappen nå innholdet i pakken.
-
Avhengigheter: Vi kan definere avhengigheter til andre pakker ved å legge til avhengighetsnøkkelen i package.yml.
En annen fil som ikke er inkludert som standard, men som anbefales, er README. Den er viktig for å gi informasjon om bruken av pakken.
Slutten på Episode I
Les mer
GraphQL Ruby. Hva med ytelse?
Skinner og andre transportmidler
Rails-utvikling med TMUX, Vim, Fzf + Ripgrep