> ## Content Index
> Fetch the complete content index at: https://www.cowsayso.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# KISS, YAGNI e DRY: tre adesivi e cosa vogliono dire davvero
- URL: https://www.cowsayso.com/it/kiss-yagni-dry-principi-programmazione/
- Published: 2025-10-14T07:00:00.000Z
- Updated: 2026-11-09T13:37:42.000Z
- Description: Tienilo semplice, non ti servirà, non ripeterti. Da dove vengono le tre sigle più citate del software (un aereo spia, l’Extreme Programming e un libro del 1999), cosa dicono davvero e cosa succede quando litigano. Con una fattoria, il prezzo del latte e nessun cammello.
- Author: Vittorio Scala
- Tags: Software Engineering, #semi-skimmed, #it

Sul portatile di ogni sviluppatore c’è almeno un adesivo con una sigla. Tre sono particolarmente famose, e sembrano usciti da un biscotto della fortuna: **KISS**, **YAGNI** e **DRY**. Tienilo semplice. Non ti servirà. Non ripeterti.

Si citano nelle code review per vincere le discussioni, e quasi sempre un po’ a sproposito. Così la mucca è tornata alle fonti: da dove viene ogni sigla, cosa dice davvero e cosa non dice. Con esempi in Python, tutti eseguiti davvero, e una fattoria che vende latte, che è la cosa più seria che conosciamo.

| Sigla     | Significa                | Nasce                                     | Senso vero                                                 | Usata male come                                  |
| --------- | ------------------------ | ----------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------ |
| **KISS**  | Keep it simple, stupid   | Kelly Johnson, Skunk Works della Lockheed | Meno pezzi, meno modi di rompersi                          | «Non voglio imparare niente di nuovo»            |
| **YAGNI** | You aren’t gonna need it | Extreme Programming, fine anni ’90        | Non costruite funzioni per un futuro che state indovinando | «Niente test, niente refactoring, niente design» |
| **DRY**   | Don’t repeat yourself    | *The Pragmatic Programmer*, 1999          | Ogni *conoscenza* vive in un posto solo                    | «Fondete due righe qualsiasi che si somigliano»  |

## KISS: keep it simple, stupid

KISS non viene dal software. Viene dagli aerei. La fonte più nota è Kelly Johnson, l’ingegnere che fondò gli «Skunk Works» della Lockheed, l’officina segreta che costruì l’aereo spia U-2 nel 1955 e poi l’SR-71 Blackbird, l’aereo più veloce e più alto del suo tempo. Nel ricordo scritto nel 1995 per la National Academy of Sciences americana da Ben Rich, che lavorò con lui agli Skunk Works, tra i motti di Johnson ci sono «Se funziona, non aggiustarlo» e questo:

> *«Keep it simple, stupid (KISS) è il nostro promemoria costante.»* (Tienilo semplice, stupido.)

La frase girava in quegli anni: un dizionario dello slang americano registra un «Project KISS» della Marina degli Stati Uniti già nel 1960\. Il senso è lo stesso. Se si può tenere semplice un aereo a Mach 3, si può tenere semplice anche la vostra fattura.

A proposito di fatture. Ecco come si calcola il prezzo di 12,5 litri di latte a 1,20 € al litro, scritto da qualcuno che ha appena letto un libro sui design pattern:

```python
from abc import ABC, abstractmethod

class PricingStrategy(ABC):
    @abstractmethod
    def price(self, liters: float) -> float: ...

class StandardMilkPricingStrategy(PricingStrategy):
    def __init__(self, rate: float):
        self.rate = rate

    def price(self, liters: float) -> float:
        return round(liters * self.rate, 2)

class PricingStrategyFactory:
    _registry = {"standard": StandardMilkPricingStrategy}

    @classmethod
    def create(cls, kind: str, **kwargs) -> PricingStrategy:
        return cls._registry[kind](**kwargs)

class MilkInvoiceService:
    def __init__(self, factory=PricingStrategyFactory):
        self.strategy = factory.create("standard", rate=1.20)

    def invoice(self, liters: float) -> float:
        return self.strategy.price(liters)

print(MilkInvoiceService().invoice(12.5))
```

Ed ecco la stessa cosa scritta dalla mucca:

```python
def milk_price(liters, rate=1.20):
    return round(liters * rate, 2)

print(milk_price(12.5))
```

```bash
$ python3 over.py
15.0
$ python3 simple.py
15.0
$ wc -l over.py simple.py
 33 over.py
  5 simple.py
 38 total
```

Stesso risultato, 15 €. Una versione ha una classe astratta, una strategia, una factory, un registro e un servizio: 33 righe per fare una moltiplicazione. L’altra ne ha 5\. Quando cambia il prezzo, tutte e due vanno modificate in un punto. Quando c’è un bug, però, una delle due ha cinque posti in cui nasconderlo.

🐄

Una factory con un registro per un’unica strategia che ha un’unica implementazione. **Sbagliato.** Questa non è architettura, è imballaggio. Il latte è lo stesso, ma adesso arriva in cinque scatole, una dentro l’altra.

🐄

Scrivere la funzione da cinque righe, e aggiungere la strategia il giorno in cui le regole di prezzo sono davvero due. **Giusto.** Il codice semplice è facile da complicare. Il contrario non succede quasi mai.

🐄

«Semplice» secondo chi? **Dipende.** Semplice non vuol dire corto, e non vuol dire «la prima cosa che mi è venuta in mente». Una riga furbissima che nessuno sa leggere non è semplice. Semplice vuol dire che un collega la capisce al primo colpo.

## YAGNI: you aren’t gonna need it

YAGNI nasce nell’Extreme Programming alla fine degli anni ’90\. Martin Fowler racconta com’è cominciata: sul progetto C3, Chet Hendrickson continuava a proporre funzionalità che un giorno sarebbero servite, e ogni volta Kent Beck rispondeva «non ti servirà». Ron Jeffries, un altro dei fondatori di XP, nel 1998 la riassunse così:

> *«Implementate le cose sempre quando vi servono davvero, mai quando prevedete soltanto che vi serviranno.»*

Ecco una funzione di mungitura scritta da qualcuno che «prevede» molto:

```python
def milk(animal, liters, species="cow", currency="EUR", blockchain=False, plugin=None):
    if species == "goat":
        raise NotImplementedError("goats: coming soon")
    if species == "camel":
        raise NotImplementedError("camels: phase 2")
    if blockchain:
        raise NotImplementedError("ask the investors")
    if plugin is not None:
        plugin.before_milking(animal)
    return f"{animal}: {liters} L"
```

Capre, cammelli, valute, plugin e una blockchain. Vediamo chi la chiama davvero, in tutto il progetto:

```bash
$ grep -rn "milk(" --include=*.py . | grep -v "def milk"
./evening.py:3:print(milk("Ercolina", 11.0, species="cow", currency="EUR"))
./morning.py:3:print(milk("Ercolina", 12.5, species="cow"))
./morning.py:4:print(milk("Carolina", 9.0))
```

Tre chiamate. Tutte per mucche, tutte in euro, mai un plugin, mai una blockchain. Il parametro `currency` non è nemmeno usato dentro la funzione. La versione onesta è questa:

```python
def milk(animal, liters):
    return f"{animal}: {liters} L"
```

Fowler spiega perché la versione «non si sa mai» costa più di quanto sembri, con quattro costi. Il *costo di costruzione*: il tempo passato a scrivere, testare e documentare i cammelli. Il *costo del ritardo*: quello che nel frattempo non avete costruito, e che i clienti aspettavano davvero. Il *costo di mantenimento*: ogni parametro inutile rende il codice più pesante da leggere e da cambiare, per sempre. E il *costo di riparazione*: quando i cammelli arriveranno davvero, i requisiti saranno diversi da quelli che avevate immaginato, e dovrete riscrivere tutto comunque. Il suo esempio è una startup che assicura spedizioni via mare: sta lavorando al rischio tempeste e sa già che tra sei mesi le servirà il rischio pirateria. YAGNI dice: la pirateria non costruitela adesso.

🐄

Supportare capre, cammelli e una blockchain in una fattoria con due mucche. **Sbagliato.** La mucca ha controllato: nella stalla non ci sono cammelli. Non ci sono mai stati.

🐄

Cancellare i parametri e i rami inutilizzati quando li trovate. **Giusto.** Se ne ricorda il controllo di versione al posto vostro. Se mai arriveranno i cammelli, il codice sarà nella storia, e comunque lo riscriverete meglio, sapendo cosa vogliono i cammelli.

Ma attenzione, perché YAGNI è la più abusata delle tre. Fowler è esplicito: YAGNI non vale per il lavoro che rende il codice *più facile da cambiare*, come i test, il refactoring e un design pulito. Anzi: YAGNI funziona solo se il codice è facile da cambiare, perché tutta la scommessa è «lo aggiungeremo dopo, quando servirà». Se aggiungerlo dopo è un incubo, la scommessa è persa.

🐄

«Non scriviamo test: YAGNI.» **Sbagliato.** I test sono proprio quello che vi permette di dire YAGNI senza paura. Senza, non è YAGNI, è YOLO.

## DRY: don’t repeat yourself

DRY viene da *The Pragmatic Programmer* di Andy Hunt e Dave Thomas, 1999\. La definizione originale è più precisa dell’adesivo:

> *«Ogni conoscenza deve avere una rappresentazione unica, non ambigua e autorevole all’interno di un sistema.»*

Notate la parola: *conoscenza*, non *codice*. Dave Thomas lo ha ripetuto in un’intervista del 2003: *«La maggior parte delle persone pensa che DRY voglia dire non duplicare il codice. Non è quello il suo scopo.»* La conoscenza di un sistema, dice, comprende anche gli schemi del database, i piani di test, il sistema di build e perfino la documentazione.

Ecco una vera violazione di DRY. Il prezzo del latte è scritto in due posti. Lunedì il prezzo sale a 1,35 €, e qualcuno aggiorna la fattura. L’etichetta sullo scaffale, invece, no:

```python
# invoice.py
def invoice_total(liters):
    return round(liters * 1.35, 2)  # new price since Monday

# shelf.py
def shelf_label(liters):
    return f"{liters} L - EUR {liters * 1.20:.2f}"
```

```bash
$ python3 main.py
shelf:   12.5 L - EUR 15.00
invoice: 16.88
```

Il cliente legge 15,00 € sullo scaffale e ne paga 16,88 alla cassa. Questo non è un problema di stile, è un reclamo. La correzione è dare al prezzo una casa sola:

```python
# prices.py
PRICE_PER_LITER = 1.35  # the one and only place where the price lives

# invoice.py
from prices import PRICE_PER_LITER

def invoice_total(liters):
    return round(liters * PRICE_PER_LITER, 2)

# shelf.py
from prices import PRICE_PER_LITER

def shelf_label(liters):
    return f"{liters} L - EUR {liters * PRICE_PER_LITER:.2f}"
```

```bash
$ python3 main.py
shelf:   12.5 L - EUR 16.88
invoice: 16.88
```

🐄

Il prezzo del latte, l’aliquota IVA, la dimensione di una pagina: scritti in un posto solo e importati ovunque. **Giusto.** Quando lo stesso fatto vive in due posti, prima o poi i due posti non saranno d’accordo. E il cliente troverà sempre quello più economico.

Ora il caso opposto. Queste due funzioni sono identiche, carattere per carattere (non le abbiamo eseguite, sono qui per essere guardate):

```python
def valid_ear_tag(code):
    return len(code) == 8 and code.isdigit()

def valid_invoice_number(code):
    return len(code) == 8 and code.isdigit()
```

Codice duplicato! Il riflesso DRY dice: unitele in una `valid_8_digit_code()`. Ma non sono la stessa conoscenza. Una è una regola sulle marche auricolari delle mucche, l’altra è una regola dell’ufficio contabilità. Oggi per caso coincidono. Il giorno in cui cambiano le regole delle marche auricolari, e quelle delle fatture no, la funzione unificata mette su un parametro. Poi un altro. Poi un altro ancora:

```python
def valid_code(code, *, is_ear_tag=False, country_prefix=False,
               invoice_year=None, legacy_mode=False, vet_mode=False):
    ...  # 60 lines of ifs. Nobody touches it. Nobody knows why.
```

Sandi Metz ha descritto questa storia passo per passo nel 2016, in «The Wrong Abstraction». Il programmatore A vede una duplicazione ed estrae un’astrazione. Arriva un nuovo requisito che ci sta quasi, e il programmatore B aggiunge un parametro e un `if`. Si ripete finché nessuno ci capisce più niente. La sua conclusione è diventata famosa: *«la duplicazione costa molto meno dell’astrazione sbagliata»*. E la cura va contro l’istinto: rimettete il codice duplicato dov’era, in ogni chiamante, togliete quello che a ciascuno non serve, e solo allora cercate l’astrazione giusta.

🐄

Unire due funzioni solo perché si somigliano. **Sbagliato.** Due mucche con le stesse macchie restano due mucche. Stesso codice non vuol dire stessa conoscenza.

Come si capisce quando unire? Una buona regola pratica è la *regola del tre*, che Martin Fowler riporta in *Refactoring* (1999) come consiglio di Don Roberts: la prima volta che fate una cosa, la fate e basta. La seconda volta fate una smorfia davanti alla duplicazione, ma la fate lo stesso. La terza volta, fate refactoring. Con tre esempi sotto mano è molto più facile vedere cosa hanno davvero in comune.

🐄

Copiare e incollare un blocco di codice. **Dipende.** La seconda volta va bene, con una smorfia. La terza volta la mucca si aspetta una funzione. Se si tratta di conoscenza, come un prezzo o una regola, già una volta è troppo.

## Quando le tre litigano

Le tre sigle non vanno sempre d’accordo. DRY spinge ad astrarre; KISS e YAGNI spingono a non costruire quello che non serve. La funzione con cinque parametri in più qui sopra è quello che succede quando DRY vince troppo presto: per non ripetervi, avete costruito qualcosa che non è semplice e che serve casi che forse non arriveranno mai. In questi casi l’ordine di precedenza della mucca è questo: prima, funziona e si legge? (KISS); poi, serve oggi? (YAGNI); e solo dopo, c’è una *conoscenza* ripetuta? (DRY).

🐄

Morale: tenetelo semplice, perché le cose semplici si rompono meno e si aggiustano più facilmente. Non costruite per i cammelli che immaginate, ma tenete il codice facile da cambiare, per quando arriveranno davvero. E non ripetete la conoscenza, ma non abbiate paura di un po’ di codice ripetuto. Gli adesivi vanno sui portatili, non nelle code review. La mucca ha parlato, e la mucca è legge.

Muuu. 🐄

Fonti

Gli esempi Python sono stati eseguiti con Python 3.13.5; gli output mostrati sono quelli reali. I due validatori e la funzione con i flag sono illustrativi e non sono stati eseguiti.

- [Ben R. Rich, “Clarence Leonard (Kelly) Johnson 1910–1990”, Biographical Memoir, NAS (1995)](https://www.nasonline.org/wp-content/uploads/2024/06/johnson-clarence.pdf?ref=cowsayso.com)
- [Wikipedia, “KISS principle”](https://en.wikipedia.org/wiki/KISS%5Fprinciple?ref=cowsayso.com)
- [Ron Jeffries, “You’re NOT gonna need it!” (1998)](https://ronjeffries.com/xprog/articles/practices/pracnotneed/?ref=cowsayso.com)
- [Martin Fowler, “Yagni” (2015)](https://martinfowler.com/bliki/Yagni.html?ref=cowsayso.com)
- [Wikipedia, “Don’t repeat yourself”](https://en.wikipedia.org/wiki/Don%27t%5Frepeat%5Fyourself?ref=cowsayso.com)
- [Bill Venners, “Orthogonality and the DRY Principle”, interview with Dave Thomas (2003)](https://www.artima.com/articles/orthogonality-and-the-dry-principle?ref=cowsayso.com)
- [Sandi Metz, “The Wrong Abstraction” (2016)](https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction?ref=cowsayso.com)
- [Wikipedia, “Rule of three (computer programming)”](https://en.wikipedia.org/wiki/Rule%5Fof%5Fthree%5F%28computer%5Fprogramming%29?ref=cowsayso.com)