Ruby, code die je met plezier terugleest

Er zijn weinig talen waarin je een idee zo mooi en leesbaar kunt opschrijven als in Ruby. We werken ermee sinds onze oprichting in 2013 en doen er nog veel doorontwikkelwerk in. Inmiddels gebruikt ongeveer de helft van onze projecten TypeScript, maar onze liefde voor Ruby is nooit verdwenen. En als de aanpak van Ruby on Rails bij je project past, kun je er heel snel iets goeds mee bouwen.

  • Sinds 2013 onderdeel van ons werk

  • Elegante code die dicht bij gewone taal komt

  • Snel bouwen met de conventies van Rails

Bauke en Roland werken samen aan software bij 10KB.

Ruby bij 10KB

Een taal waar we graag in denken

Toen Ewout en Roland in 2013 samen 10KB begonnen, hadden ze vooral in PHP ontwikkeld. Rails voelde toen als een volwassener framework en de standaardbibliotheek van Ruby was uitgebreider en fijner om mee te werken. Maar wat misschien wel het meest aansprak: je kon er zulke mooie code in schrijven.

Dat plezier is gebleven. 5.times leest als “vijf keer”. Met Rails erbij wordt 3.days.ago gewoon “drie dagen geleden”. Je hoeft minder door technische notatie heen te kijken om de bedoeling te zien. Dat klinkt als iets voor developers, maar bij software die je jaren blijft aanpassen is begrijpelijke code ook voor de klant waardevol.

Developers van 10KB bekijken samen de code van een applicatie.

Waarom wij Ruby en Rails gebruiken

Prettig schrijven, prettig onderhouden

Ruby laat je code schrijven die bijna als een zin leest. Een lijst doorlopen, bedragen optellen of een voorwaarde benoemen: vaak heb je weinig extra notatie nodig. We vinden dat een van de mooiste kanten van de taal. Je aandacht gaat naar wat de code doet, en dat helpt ook de collega die er later mee verdergaat.

We kunnen Ruby uitbreiden met begrippen die bij een applicatie horen. Denk aan een herinneringsplan dat letterlijk zegt: na drie dagen een e-mail, na zeven dagen bellen. Zo'n kleine domeintaal, of DSL, maakt terugkerende regels makkelijk te lezen en aan te passen. Verderop laten we zien hoe weinig code daarvoor nodig is.

Rails heeft een vaste aanpak voor onder meer formulieren, databasegebruik, e-mail en achtergrondtaken. Het framework bepaalt hoe die onderdelen samenwerken. Als dat aansluit op je applicatie, hoeven we weinig tijd te besteden aan de inrichting en kunnen we snel aan de functies werken die je nodig hebt.

De bedoeling staat in de code

Ruby laat je code schrijven die bijna als een zin leest. Een lijst doorlopen, bedragen optellen of een voorwaarde benoemen: vaak heb je weinig extra notatie nodig. We vinden dat een van de mooiste kanten van de taal. Je aandacht gaat naar wat de code doet, en dat helpt ook de collega die er later mee verdergaat.

Onze afweging

Past jouw project bij de Rails-manier?

Rails is uitgesproken eigenzinnig: het heeft een mening over hoe je een webapplicatie opbouwt. Die conventies zijn een groot voordeel als je project erbij past. Een portal met accounts, formulieren, overzichten en vaste werkprocessen kan daardoor snel vorm krijgen.

Als we voor veel onderdelen van die standaardaanpak moeten afwijken, wordt het voordeel kleiner. Dan besteden we meer tijd aan uitzonderingen en kan een andere taal of een ander framework beter passen. We kijken daarom naar de gewenste interactie, bestaande systemen en het team dat de applicatie gaat onderhouden.

Statische typecontrole weegt ook mee: feedback over gegevenstypes voordat de code draait. Ruby heeft daar hulpmiddelen voor, maar in ons werk vinden we die minder ver ontwikkeld dan bij TypeScript. Dat is één afweging naast bouwsnelheid, leesbaarheid en de aansluiting op het project. Dat circa 50% van onze projecten inmiddels TypeScript gebruikt, doet niets af aan het plezier waarmee we Ruby schrijven.

Bespreek welke aanpak bij je project past
Twee developers van 10KB bespreken een technische keuze.

In ons werk

Ruby in bedrijfsapplicaties

Voor LiVvE bouwden we een Rails-applicatie voor VvE-beheer, met boekhouding, documentverwerking en een portal voor beheerders en leden. Terugkerende bijdragen en herinneringen worden vanuit dezelfde omgeving verwerkt.

Bij SGI Compliance ontwikkelen we Werkplanner door, met configureerbare formulieren en projectdocumenten. En bij Smartfile verbeterden we onder meer de autorisatie, tests en deployments van bestaande Rails-software. Ruby komt in ons werk dus terug bij zowel het bouwen als het verder ontwikkelen van bedrijfsapplicaties.

Bekijk LiVvE in de praktijk
Bauke en Roland bekijken samen software op een beeldscherm.

De structuur achter Rails

Model, View, Controller: ieder een eigen taak

Rails heeft MVC groot gemaakt bij webframeworks. Het patroon bestond al, maar Rails maakte het een herkenbaar vertrekpunt: gegevens en bedrijfsregels, de weergave en de afhandeling van een verzoek krijgen elk een eigen plek.

Neem een klant die een factuur opent. De Controller ontvangt het verzoek en laat de juiste factuur ophalen. Het Model bevat de gegevens en regels, bijvoorbeeld hoe het totaal wordt berekend. De View maakt daar het scherm van dat de klant ziet.

Daardoor hoeft een andere vormgeving van de factuur niet de berekening te veranderen. En een aangepaste berekening hoeft niet in ieder scherm opnieuw te worden geschreven. Die vaste indeling helpt ons om snel te vinden waar een wijziging thuishoort.

MVC in Rails: een verzoek komt bij de Controller, die het Model aanspreekt en de View laat renderen. De View levert het scherm voor de gebruiker.

Lees het eens hardop

Vijf keer? Gewoon 5.times

Een teller aanmaken, ophogen en controleren of je klaar bent: dat kan, maar Ruby laat je ook gewoon 5.times schrijven. Het blok erachter vertelt wat er vijf keer moet gebeuren. En met sum tel je een lijst bedragen op.

Dat is het plezier van Ruby in het klein: de code laat de bedoeling zien. In dit voorbeeld maken we vijf factuurnamen en tellen we bedragen in hele euro's op.

ruby
# Ruby leest bijna als een zin
invoices = []

5.times do |number|
  invoices << "Factuur #{number + 1}"
end

puts invoices
# Factuur 1, Factuur 2, ... Factuur 5
# Elke naam verschijnt op een eigen regel.

amounts = [20, 35, 45]
puts amounts.sum
# 100 euro, zonder zelf een teller bij te houden.

Rails bouwt daarop voort

Drie dagen geleden: 3.days.ago

Active Support, een onderdeel van Rails, voegt woorden als days en ago toe. Daardoor kun je “drie dagen geleden” schrijven zonder zelf seconden uit te rekenen. 2.weeks.from_now werkt dezelfde kant op voor de toekomst.

Hier gebruiken we dat om te bepalen of een factuur ouder is dan drie dagen. 5.times hoort bij Ruby zelf; de tijdsuitdrukkingen komen uit Active Support. Die bibliotheek kun je ook buiten een volledige Rails-applicatie gebruiken.

ruby
# Tijd in gewone woorden
require "active_support/all"

# Active Support voegt deze tijdsuitdrukkingen toe.
cutoff = 3.days.ago
issued_at = 5.days.ago

if issued_at < cutoff
  puts "Deze factuur is ouder dan drie dagen."
end

# Ook een tijdstip in de toekomst is goed leesbaar.
next_review = 2.weeks.from_now
puts next_review.to_date
# De datum over twee weken.

# Geen losse getallen waarvan je de eenheid moet raden.
# 3.days is een tijdsduur; 3.days.ago een tijdstip.

De woorden van je applicatie

Na drie dagen mailen, na zeven dagen bellen

Die leesbaarheid kunnen we zelf verder brengen. Een DSL is een kleine taal voor één onderwerp. Hier maken we after 3.days, via: :email tot een geldige regel in een herinneringsplan. Het blijft gewone Ruby-code; wij geven er de woorden en betekenis aan.

De klasse legt vast wat after doet. Daaronder lees je het plan bijna als een werkinstructie. Een termijn aanpassen hoeft dan maar op één duidelijke plek. Dit voorbeeld beschrijft alleen de stappen; het plant geen taken in en verstuurt geen berichten.

ruby
# Een eigen taal voor herinneringen
class ReminderPlan
  attr_reader :steps

  def initialize(&rules)
    @steps = []
    instance_eval(&rules)
  end

  def after(delay, via:)
    @steps << { delay: delay, via: via }
  end
end

# Dit is onze eigen DSL, geschreven in gewone Ruby.
plan = ReminderPlan.new do
  after 3.days, via: :email
  after 7.days, via: :phone
end

# Bekijk de afspraken die we hebben vastgelegd.
plan.steps.each do |step|
  days = step[:delay].in_days.to_i
  puts "Na #{days} dagen: #{step[:via]}"
end
# Na 3 dagen: email
# Na 7 dagen: phone

# De termijnen zijn relatief aan het begin van het plan.
# Berichten versturen en taken inplannen horen elders.
ruby
# Ruby leest bijna als een zin
invoices = []

5.times do |number|
  invoices << "Factuur #{number + 1}"
end

puts invoices
# Factuur 1, Factuur 2, ... Factuur 5
# Elke naam verschijnt op een eigen regel.

amounts = [20, 35, 45]
puts amounts.sum
# 100 euro, zonder zelf een teller bij te houden.

# Tijd in gewone woorden
require "active_support/all"

# Active Support voegt deze tijdsuitdrukkingen toe.
cutoff = 3.days.ago
issued_at = 5.days.ago

if issued_at < cutoff
  puts "Deze factuur is ouder dan drie dagen."
end

# Ook een tijdstip in de toekomst is goed leesbaar.
next_review = 2.weeks.from_now
puts next_review.to_date
# De datum over twee weken.

# Geen losse getallen waarvan je de eenheid moet raden.
# 3.days is een tijdsduur; 3.days.ago een tijdstip.

# Een eigen taal voor herinneringen
class ReminderPlan
  attr_reader :steps

  def initialize(&rules)
    @steps = []
    instance_eval(&rules)
  end

  def after(delay, via:)
    @steps << { delay: delay, via: via }
  end
end

# Dit is onze eigen DSL, geschreven in gewone Ruby.
plan = ReminderPlan.new do
  after 3.days, via: :email
  after 7.days, via: :phone
end

# Bekijk de afspraken die we hebben vastgelegd.
plan.steps.each do |step|
  days = step[:delay].in_days.to_i
  puts "Na #{days} dagen: #{step[:via]}"
end
# Na 3 dagen: email
# Na 7 dagen: phone

# De termijnen zijn relatief aan het begin van het plan.
# Berichten versturen en taken inplannen horen elders.

Ruby en Rails blijven zich ontwikkelen

Van onze start tot nu

We werken al sinds 2013 met Ruby. In die tijd zijn de taal, de ontwikkeltools en de manier om Rails-applicaties uit te rollen flink veranderd.

2013

10KB

We beginnen 10KB met Ruby

Ewout en Roland richten 10KB op. Na hun ervaring met PHP kiezen ze voor de volwassen aanpak van Rails en het plezier van elegante, leesbare Ruby-code.

2020

Ruby 3 geeft types een eigen plek

Ruby 3 introduceert RBS om types te beschrijven en TypeProf om code te analyseren. Ruby blijft dynamisch, maar krijgt meer gereedschap om vóór uitvoering iets over gegevenstypes te weten.

2021

Rails 7 kiest voor Hotwire

Met Hotwire kunnen interactieve schermen grotendeels vanuit HTML op de server worden opgebouwd. Een aparte frontendapplicatie is daardoor niet voor iedere interactieve pagina nodig.

2023

Ruby 3.3 verbetert YJIT

YJIT zet veelgebruikte Ruby-code tijdens het draaien om naar machinecode. Ruby 3.3 verbetert de prestaties en het geheugengebruik van die compiler. Hoeveel een applicatie daaraan heeft, hangt af van het werk dat ze doet.

2024

Rails 8 neemt meer van de uitrol mee

Rails 8 levert Kamal 2 voor deployments en Solid Queue voor achtergrondtaken standaard mee. De vaste Rails-aanpak strekt zich zo verder uit van code schrijven naar het draaien van de applicatie.

Ruby en Rails bij andere bedrijven

Van snowboardwinkel naar webshopplatform

Shopify begon in 2004 met twee developers en een vroege Rails-versie. De voorloper, snowboardwinkel Snowdevil, werd volgens de toenmalige Rails-aankondiging in minder dan vier maanden gebouwd. Oprichter Tobias Lütke schreef die productiviteit mede toe aan Rails.

Dat is de aantrekkingskracht bij een goede match: met een klein team snel een werkend product neerzetten en van daaruit verder bouwen. Bij Shopify groeide dat uit tot een platform waarop andere ondernemers hun winkel konden beginnen.

AI-gegenereerd vierkant sfeerbeeld van een ondernemer die een pakket inpakt naast een laptop met orderbeheer, bij het verhaal over Shopify.

Ruby en Rails bij andere bedrijven

In drie maanden naar een eerste bèta

GitHub begon in oktober 2007 als avond- en weekendproject. Medeoprichter Tom Preston-Werner beschreef hoe Chris Wanstrath de Rails-applicatie bouwde, terwijl hij aan de Git-koppeling en interface werkte. Drie maanden later ging de besloten bèta open.

Die taakverdeling laat zien hoe Rails bij zo'n start kan helpen: een bestaande basis voor de webapp, met ruimte voor het eigen productidee. Het team kon vroeg iets bruikbaars aanbieden en met gebruikers verder ontwikkelen.

AI-gegenereerd vierkant sfeerbeeld van twee developers die samen code bekijken, bij het verhaal over GitHub.
AI-gegenereerd vierkant sfeerbeeld van een ondernemer die een pakket inpakt naast een laptop met orderbeheer, bij het verhaal over Shopify.AI-gegenereerd vierkant sfeerbeeld van twee developers die samen code bekijken, bij het verhaal over GitHub.

Ewout

Contactpersoon: Ewout

Past Ruby on Rails bij jouw plannen?

Wil je snel een eerste versie bouwen of een bestaande Rails-applicatie verder brengen? Bespreek het met Ewout. We kijken naar je werkprocessen, het team en hoe goed de aanpak van Rails daarbij past.

CONTACT

Neem contact met ons op

Heb je een vraag of wil je sparren over je software? Laat je gegevens achter, dan nemen we snel contact met je op.