Self-Documenting Scripts

Lambda Smalltalk's syntax reads like English. Your scripts become their own documentation.

The Problem with Traditional Scripts

Shell script:

#!/bin/bash
for h in $(cat hosts.txt); do
  ssh $h "systemctl restart nginx" && \
  curl -s -o /dev/null -w "%{http_code}" http://$h/health | grep -q 200 && \
  echo "$h: OK" || echo "$h: FAILED"
done

What does this do? You need to parse the syntax mentally.

Python:

for host in open('hosts.txt'):
    subprocess.run(['ssh', host.strip(), 'systemctl restart nginx'])
    r = requests.get(f'http://{host.strip()}/health')
    print(f"{host.strip()}: {'OK' if r.status_code == 200 else 'FAILED'}")

Better, but still requires programming knowledge to read.

The Smalltalk Way

"Restart nginx on all servers and verify health"

hosts := (File read: 'hosts.txt') lines.

hosts do: [:host |
    host restart: 'nginx'.

    (host healthCheck)
        ifTrue:  [ (host, ': OK') printNl ]
        ifFalse: [ (host, ': FAILED') printNl ].
].

Read it aloud:

The code is the documentation.


Why This Matters

1. Auditable Operations

When regulators ask "what does this script do?", you can show them the code directly:

"Daily backup procedure"

Database dump: 'production' to: '/backup/daily/'.
S3 upload: '/backup/daily/' to: 'company-backups' prefix: (Date today asString).
Slack notify: '#ops' message: 'Daily backup completed'.

No separate runbook needed. The script is the runbook.

2. Reduced Bus Factor

New team members can read and understand operations scripts immediately:

"Deploy to staging"

Git pull: 'origin/main'.
Docker build: '.' tag: 'app:staging'.
Kubernetes apply: 'k8s/staging.yaml'.

(App healthCheck: 'staging')
    ifTrue:  [ Slack notify: 'Staging deploy successful' ]
    ifFalse: [ Slack notify: 'Staging deploy FAILED' ].

No tribal knowledge required.

3. Fewer Mistakes

When the intent is clear, mistakes are obvious:

"Archive old logs (WRONG - deletes instead of archiving!)"
Logs olderThan: 30 days delete.

"Archive old logs (CORRECT)"
Logs olderThan: 30 days moveTo: '/archive/'.

The bug is visible to anyone who reads the code.


Real-World Patterns

Health Monitoring

"Check all services every 5 minutes"

services := #('web-01' 'web-02' 'db-primary' 'cache-01').

services do: [:svc |
    (svc isHealthy) ifFalse: [
        PagerDuty alert: svc , ' is DOWN'.
        svc restart.

        (svc isHealthy)
            ifTrue:  [ PagerDuty resolve: svc , ' recovered after restart' ]
            ifFalse: [ PagerDuty escalate: svc , ' still DOWN after restart' ].
    ].
].

Data Pipeline

"ETL: Extract from source, transform, load to warehouse"

data := Postgres query: 'SELECT * FROM events WHERE date = today()'.

data := data
    select: [:row | row at: 'status' = 'completed']
    collect: [:row | row transform: TransformRules].

BigQuery insert: data into: 'analytics.daily_events'.

('Processed ', data size asString, ' records') printNl.

Deployment with Rollback

"Blue-green deployment with automatic rollback"

| previousVersion |
previousVersion := App currentVersion.

App deploy: newVersion to: 'green'.

(App healthCheck: 'green')
    ifTrue: [
        LoadBalancer switchTo: 'green'.
        Slack notify: 'Deployed ', newVersion, ' successfully'.
    ]
    ifFalse: [
        App rollbackTo: previousVersion.
        Slack notify: 'Deploy failed, rolled back to ', previousVersion.
        PagerDuty alert: 'Deployment failure'.
    ].

Getting Started

Lambda Smalltalk provides the building blocks. Combine them with:

See Examples for more patterns.