Mensen vinden het moeilijk om het grote plaatje van een probleem te zien zonder er veel tijd en moeite in te steken. Dit gebeurt vooral bij het werken met grote en complexe applicaties. Wat zijn de neveneffecten van mijn wijzigingen? Waarom heeft deze regel hier invloed op de tests van een ander deel van de codebase? Een perfecte of complete oplossing bestaat niet, maar Shopify kwam met een tool die jou en je team waarschijnlijk zal helpen.
Inleiding
Om te praten over Packwerkmoeten we eerst een paar concepten introduceren.
- Cohesie: verwijst naar de mate waarin elementen in een module of klasse bij elkaar horen.
- Koppeling: verwijst naar de mate van afhankelijkheid tussen modules of klassen.
- Grenzenverwijst naar barrières tussen code. In dit geval verwijst een code boundary naar verschillende aandachtsdomeinen binnen dezelfde codebase.
- ModulariseringHet proces waarbij een softwaresysteem wordt opgedeeld in meerdere afzonderlijke modules waarbij elke module onafhankelijk werkt.
Problemen
Zoals we weten, Ruby biedt geen goede oplossing om codegrenzen af te dwingen. We kunnen de zichtbaarheid specificeren, maar alle afhankelijkheden worden in de globale naamruimte geladen. In grote of monolithische applicaties levert dit gebrek aan grenzen de volgende problemen op.
- Lage cohesie,
- Hoge koppeling,
- Spaghetti-code.
In een poging om de monoliet van Shopify te modulariseren en grenzen op te leggen, probeerden ze verschillende oplossingen zonder de verwachte resultaten te behalen:
- Privéconstanten instellen,
- Grenzen stellen met edelstenen,
- Tests gebruiken om componentoverschrijdende associaties te voorkomen,
- Gebruik maken van Ruby's Modulation gem,
- Microservices maken.
Met alle kennis van eerdere pogingen besloten ze hun eigen tool te maken: Packwerk.
Packwerk
Wat is Packwerk?
Packwerk is een statisch analysegereedschap dat wordt gebruikt om grenzen af te dwingen tussen groepen van Ruby bestanden genaamd pakketten.
Wat is een pakket?
A pakket is een map met automatisch geladen code. Shopify's team moedigt het gebruik van de beste ontwerppraktijken aan bij het maken van pakketten.
- We moeten samen dingen inpakken die een hoge functionaliteit hebben cohesie,
- Pakketten moeten relatief losjes aan elkaar gekoppeld zijn.
Soorten grenscontroles
We kunnen privacy- en afhankelijkheidsgrenzen afdwingen, schendingen van de grenzen en cyclische afhankelijkheden controleren.
Packwerk in de praktijk
Er is niet één specifieke manier om je applicatie te structureren of te herstructureren tijdens het maken van pakketten. In dit artikel volgen we de aanpak die wordt voorgesteld door
Stephan Hagemann in Geleidelijke modularisering voor Ruby on Rails.
Kies het project
U kunt een nieuwe project of kies een van je projecten. Ik besloot een open-source project te gebruiken met de naam CodeTriage. Het is belangrijk om te vermelden dat we een Rails 6-applicatie nodig hebben omdat Packwerk gebruikt Zeitwerk.
Packwerk initialiseren
Eerst moeten we de gem toevoegen aan ons Gemfile zoals juweel 'pakwerk
en voer dan bundel
in de console. Dan zijn we klaar om de gem te initialiseren met pakwerk init
.
Daarna zien we dat Packwerk heeft drie bestanden voor ons gegenereerd:
-
pakwerk.yml
-
package.yml
-
verbuigingen.yml
pakwerk.yml is het configuratiebestand van Packwerk waar we onder andere inbegrepen en uitgesloten bestanden definiëren, de laadpaden opsommen en het verbuigingsbestand definiëren;
package.yml is het configuratiebestand van een pakket. In dit bestand voegen we de configuratie toe voor de grenzen van ons pakket. Elke map met package.yml zal door Packwerk. Dat is het, Packwerk onze eerste
pakket en we noemen het de wortel pakket.
verbuigingen.yml is waar we onze aangepaste verbuigingen en acroniemen plaatsen voor het geval we ze gebruiken.
Meer informatie over de bestanden en hun configuratie vindt u in
Packwerk.
Packwerk eigenschappen
Om modularisatie te laten werken hebben we drie basiseigenschappen nodig: een container met naamzijn inhouden expliciet afhankelijkheden op andere containers. Dus laten we die eigenschappen definiëren in Packwerk:
-
Naam: De naam van een pakket is het relatieve pad vanaf de root van de
toepassing.
-
Inhoud: Wanneer we een package.yml in een map plaatsen, zijn alle bestanden in de map nu de inhoud van het pakket.
-
Afhankelijkheden: We kunnen afhankelijkheden van andere pakketten definiëren door de afhankelijkheden sleutel toe te voegen aan de package.yml.
Een ander bestand dat niet standaard wordt meegeleverd, maar wel wordt aanbevolen, is README. Het is belangrijk om informatie te geven over het gebruik van het pakket.
Het einde van aflevering I
Meer lezen
GraphQL Ruby. Hoe zit het met de prestaties?
Rails en andere transportmiddelen
Rails ontwikkelen met TMUX, Vim, Fzf + Ripgrep