Dividere un'applicazione potenzialmente monolitica in più applicazioni più piccole aiuta a prevenire i bug? [chiuso]


48

Un altro modo di chiedere questo è; perché i programmi tendono ad essere monolitici?

Sto pensando a qualcosa come un pacchetto di animazione come Maya, che le persone usano per diversi flussi di lavoro.

Se le capacità di animazione e modellazione fossero suddivise in una propria applicazione separata e sviluppate separatamente, con i file che passavano tra loro, non sarebbe più facile da mantenere?


9
If the animation and modelling capabilities were split into their own separate application and developed separately, with files being passed between them, would they not be easier to maintain?Non mescolare più facilmente per estenderlo con più facile da mantenere un modulo -per se- non è privo di complicazioni o progetti dubbi. Maya può essere l'inferno sulla terra da mantenere, mentre i suoi plugin non lo sono. O vice versa.
Laiv

37
Aggiungerò che un singolo programma monolitico tende a essere più facile da vendere e più facile da usare per la maggior parte delle persone .
DarthFennec,

2
@DarthFennec Le migliori app sembrano una app per l'utente ma utilizzano tutto ciò che è necessario sotto il cofano. Quanti microservizi alimentano i vari siti Web visitati? Quasi nessuno di loro è più un monolite!
corsiKa

23
@corsiKa Di solito non c'è nulla da guadagnare scrivendo un'applicazione desktop come programmi multipli che comunicano sotto il cofano, che non si ottiene semplicemente scrivendo più moduli / librerie e collegandoli insieme in un binario monolitico. I microservizi hanno uno scopo completamente diverso, in quanto consentono a una singola applicazione di funzionare su più server fisici, consentendo di ridimensionare le prestazioni con il carico.
DarthFennec,

5
@corsiKa - Immagino che il numero schiacciante di siti Web che utilizzo siano ancora monoliti. La maggior parte di Internet, dopo tutto, funziona su Wordpress.
Assapora Ždralo il

Risposte:


94

Sì. In genere due applicazioni più piccole e meno complesse sono molto più facili da gestire rispetto a una singola grande.

Tuttavia, si ottiene un nuovo tipo di bug quando tutte le applicazioni lavorano insieme per raggiungere un obiettivo. Per farli lavorare insieme devono scambiarsi messaggi e questa orchestrazione può andare storta in vari modi, anche se ogni applicazione potrebbe funzionare perfettamente. Avere un milione di piccole applicazioni ha i suoi problemi speciali.

Un'applicazione monolitica è davvero l'opzione predefinita che si ottiene quando si aggiungono sempre più funzionalità a una singola applicazione. È l'approccio più semplice se si considera ciascuna caratteristica da sola. È solo una volta cresciuto che puoi guardare il tutto e dire "sai cosa, funzionerebbe meglio se separassimo X e Y".


6
Sì e ci sono anche considerazioni sulle prestazioni, ad esempio il costo del passaggio di un puntatore rispetto alla serializzazione dei dati.
JimmyJames

65
"In genere 2 applicazioni più piccole e meno complesse sono molto più facili da gestire rispetto a una singola grande." - è vero, tranne quando non lo è. Dipende fortemente da dove e come queste due applicazioni devono interfacciarsi tra loro.
Doc Brown

10
"In genere 2 applicazioni più piccole e meno complesse sono molto più facili da gestire rispetto a una singola grande." Penso che vorrò qualche spiegazione in più per questo. Perché esattamente il processo di generazione di due anziché di un eseguibile da una base di codice renderebbe magicamente più semplice il codice? Ciò che decide quanto sia facile ragionare sul codice, è quanto sia strettamente associato e cose simili. Ma questa è una separazione logica e non ha nulla a che fare con quella fisica .
Voo

11
@Ew La separazione fisica non forza una separazione logica, questo è il problema. Posso facilmente progettare un sistema in cui due applicazioni separate sono strettamente accoppiate. Sicuramente c'è una correlazione qui coinvolta dal momento che le persone che trascorrono il tempo a separare un'applicazione sono molto probabilmente abbastanza competenti da considerare queste cose, ma ci sono poche ragioni per assumere qualsiasi causalità . Con la stessa logica posso affermare che l'uso dell'ultima versione di C # rende il codice molto più semplice da mantenere, poiché il tipo di team che si tiene aggiornato con i propri strumenti probabilmente si preoccuperà anche della manutenzione del codice.
Voo

9
Penso che la discussione qui possa essere riassunta in 2 affermazioni: 1) Dividere un'app in sé non rende un'app più gestibile - al contrario, fornisce un altro possibile punto di errore 2) Dividere un'app ti costringe a pensare a dove dividere esso, che offre un vantaggio rispetto a un monolite dove non è mai stato fatto.
R. Schmitz,

51

Dividere un'applicazione potenzialmente monolitica in diverse applicazioni più piccole aiuta a prevenire i bug

Le cose raramente sono così semplici nella realtà.

La divisione non aiuta sicuramente a prevenire questi bug in primo luogo. A volte può aiutare a trovare i bug più velocemente. Un'applicazione che consiste di componenti piccoli e isolati può consentire test più individuali (tipo di "unità" -) per quei componenti, il che può rendere talvolta più facile individuare la causa principale di alcuni bug e quindi consentirli di risolverli più velocemente.

Però,

  • anche un'applicazione che sembra essere monolitica dall'esterno può consistere in molti componenti testabili dall'interno, quindi i test unitari non sono necessariamente più difficili per un'app monolitica

  • come già accennato da Ewan, l'interazione di diversi componenti introduce ulteriori rischi e bug. E il debug di un sistema applicativo con complesse comunicazioni tra processi può essere significativamente più difficile del debug di un'applicazione a processo singolo

Ciò dipende anche da quanto bene un'app più grande può essere suddivisa in componenti, da quanto sono ampie le interfacce tra i componenti e da come vengono utilizzate.

In breve, questo è spesso un compromesso e nulla in cui una risposta "sì" o "no" è corretta in generale.

perché i programmi tendono ad essere monolitici?

Fanno? Guardati intorno, ci sono milioni di app Web nel mondo che non mi sembrano molto monolitiche, al contrario. Ci sono anche molti programmi disponibili che forniscono un modello di plug-in (AFAIK anche il software Maya che hai citato lo fa).

non sarebbero più facili da mantenere

La "manutenzione più semplice" qui spesso deriva dal fatto che diverse parti di un'applicazione possono essere sviluppate più facilmente da diversi team, quindi carico di lavoro meglio distribuito, team specializzati con focus più chiaro e così via.


4
Nella tua ultima frase, la legge di Conway afferma che la struttura del sistema tende a imitare l'organizzazione. struttura: gli sviluppatori / team hanno più familiarità con alcune parti rispetto ad altre, quindi mentre correzioni / miglioramenti dovrebbero avvenire nella parte più pertinente, potrebbe essere più facile per uno sviluppatore hackerarlo nelle "loro" parti piuttosto che (a) apprendere come l'altra parte funziona o (b) lavora con qualcuno che ha più familiarità con quella parte. Ciò è legato alle menzioni "cuciture" di @TKK e alla difficoltà a trovare e applicare quelle "corrette" / semplici.
Warbo

38

Dovrò essere in disaccordo con la maggioranza su questo. La suddivisione di un'applicazione in due distinti non rende di per sé il codice più facile da mantenere o ragionare.

Separare il codice in due eseguibili cambia semplicemente la struttura fisica del codice, ma non è questo ciò che è importante. Ciò che decide quanto sia complessa un'applicazione è quanto siano strettamente collegate le diverse parti che la compongono. Questa non è una proprietà fisica, ma logica .

Puoi avere un'applicazione monolitica che ha una chiara separazione tra diversi problemi e semplici interfacce. È possibile avere un'architettura di microservizi che si basa sui dettagli di implementazione di altri microservizi ed è strettamente accoppiata con tutti gli altri.

Ciò che è vero è che il processo di suddivisione di una grande applicazione in applicazioni più piccole è molto utile quando si cerca di stabilire interfacce e requisiti chiari per ciascuna parte. In DDD parla che verrebbe fuori con i tuoi contesti limitati. Ma se poi crei molte piccole applicazioni o una grande che ha la stessa struttura logica, è più una decisione tecnica.


Ma cosa succede se uno prende un'applicazione desktop con più modalità di modifica e invece crea un'applicazione desktop per ciascuna modalità che un utente aprirà individualmente invece di avere un'interfaccia. Ciò non eliminerebbe una quantità non banale di codice dedicato alla produzione della "caratteristica" di "utente in grado di passare da una modalità di modifica"?
The Great Duck

3
@TheGreatDuck Sembra che eliminerebbe anche una quantità non banale di utenti a cui non piace passare da un'applicazione all'altra. ;) Sì, l'eliminazione delle funzionalità generalmente porta a un codice più semplice. Elimina il controllo ortografico e eliminerai la possibilità di avere bug per il controllo ortografico. È fatto raramente perché la funzione è stata aggiunta perché qualcuno l'ha voluta.
Odalrick,

1
@TheGreatDuck Sicuramente il design della UX dovrebbe venire prima di qualsiasi decisione architettonica. Non ha senso avere la migliore architettura progettata se nessuno usa il tuo programma. Decidi prima cosa vuoi costruire e in base a decidere sui dettagli tecnici. Se si preferiscono due applicazioni separate, provare. Puoi comunque condividere molto codice tramite librerie condivise.
Voo

È davvero vero dire che la complessità del sistema è dovuta allo stretto accoppiamento delle parti? Vorrei dire che la complessità totale aumenta se si suddivide il sistema mentre si introducono la comunicazione indiretta e la comunicazione, sebbene la complessità dei singoli componenti specifici sia isolata in uno stato limitato di complessità più limitata.
Alex

1
@TheGreatDuck Il presupposto di base qui era che i sistemi hanno qualcosa in comune e in realtà devono comunicare in un modo o nell'altro. Non credo che il PO chiedesse se due applicazioni completamente diverse che sono raggruppate insieme per qualche strana ragione sarebbero più facili da mantenere se separate. Sembra un caso strano che non si presenta spesso in pratica (anche se sono sicuro che qualcuno da qualche parte lo abbia fatto).
Voo

15

Più facile da mantenere una volta che hai finito di dividerli, sì. Ma dividerli non è sempre facile. Cercare di dividere un pezzo di programma in una libreria riutilizzabile rivela dove gli sviluppatori originali non sono riusciti a pensare a dove dovrebbero essere le cuciture . Se una parte dell'applicazione arriva in profondità in un'altra parte dell'applicazione, può essere difficile da risolvere. Strappare le cuciture ti costringe a definire le API interne in modo più chiaro, e questo è ciò che alla fine rende più semplice la manutenzione della base di codice. Riusabilità e manutenibilità sono entrambi prodotti di cuciture ben definite.


ottimo post. penso che un esempio classico / canonico di ciò di cui parli sia un'applicazione GUI. molte volte un'applicazione GUI è un programma e il backend / frontend sono strettamente accoppiati. col passare del tempo sorgono problemi ... come se qualcun altro ha bisogno di usare il backend ma non può perché è legato al frontend. oppure l'elaborazione del backend impiega troppo tempo e impantana il frontend. spesso l'unica grande applicazione della GUI è suddivisa in due programmi: uno è la GUI front-end e l'altro è un back-end.
Trevor Boyd Smith,

13

È importante ricordare che la correlazione non è causalità.

Costruire un grande monolite e poi dividerlo in più parti piccole può o meno portare a un buon design. ( Può migliorare il design, ma non è garantito.)

Ma un buon design spesso porta alla costruzione di un sistema composto da più parti piccole piuttosto che da un grande monolite. (Un monolite può essere il miglior design, è molto meno probabile che lo sia.)

Perché le parti piccole sono migliori? Perché sono più facili da ragionare. E se è facile ragionare sulla correttezza, è più probabile che tu ottenga un risultato corretto.

Per citare Hoare CAR:

Esistono due modi per costruire un progetto software: un modo è renderlo così semplice che non ci siano ovviamente carenze e l'altro è renderlo così complicato che non ci sono carenze evidenti .

In tal caso, perché qualcuno dovrebbe costruire una soluzione inutilmente complicata o monolitica? Hoare fornisce la risposta nella frase successiva:

Il primo metodo è molto più difficile.

E più tardi nella stessa fonte (la conferenza del Premio Turing del 1980):

Il prezzo dell'affidabilità è la ricerca della massima semplicità. È un prezzo che i più ricchi trovano più difficile da pagare.


6

Questa non è una domanda con una risposta sì o no. La domanda non è solo facilità di manutenzione, ma è anche una questione di uso efficiente delle competenze.

Generalmente, un'applicazione monolitica ben scritta è efficiente. La comunicazione tra processi e tra dispositivi non è economica. La rottura di un singolo processo riduce l'efficienza. Tuttavia, l'esecuzione di tutto su un singolo processore può sovraccaricare il processore e rallentare le prestazioni. Questo è il problema di base della scalabilità. Quando la rete entra in scena, il problema diventa più complicato.

Un'applicazione monolitica ben scritta che può funzionare in modo efficiente come un singolo processo su un singolo server può essere facile da mantenere e priva di difetti, ma non è ancora un uso efficiente delle competenze di codifica e architettura. Il primo passo è suddividere il processo in librerie che eseguono ancora lo stesso processo, ma sono codificate in modo indipendente, seguendo le discipline della coesione e dell'accoppiamento libero. Un buon lavoro a questo livello migliora la manutenibilità e raramente influenza le prestazioni.

La fase successiva è quella di dividere il monolito in processi separati. Questo è più difficile perché entri in un territorio difficile. È facile introdurre errori nelle condizioni di gara. Il sovraccarico di comunicazione aumenta e devi stare attento alle "interfacce chiacchierone". I vantaggi sono eccezionali perché si rompe una barriera di scalabilità, ma aumenta anche il potenziale di difetti. Le applicazioni multi-processo sono più facili da mantenere a livello di modulo, ma l'intero sistema è più complicato e più difficile da risolvere. Le correzioni possono essere diabolicamente complicate.

Quando i processi sono distribuiti su server separati o su un'implementazione in stile cloud, i problemi diventano più difficili e le ricompense maggiori. La scalabilità sale. (Se stai prendendo in considerazione un'implementazione cloud che non produce scalabilità, rifletti attentamente.) Ma i problemi che entrano in questa fase possono essere incredibilmente difficili da identificare e riflettere.


4

No . non facilita la manutenzione. Semmai benvenuti a più problemi.

Perché?

  • I programmi non sono ortogonali di cui hanno bisogno per preservare il lavoro reciproco nella misura del ragionevole, il che implica una comprensione comune.
  • Gran parte del codice di entrambi i programmi sono identici. Stai mantenendo una libreria condivisa comune o due copie separate?
  • Ora hai due team di sviluppo. Come stanno comunicando?
  • Ora hai due prodotti che richiedono:

    • uno stile di interfaccia utente comune, meccanismi di interazione, ecc ... Quindi ora hai problemi di progettazione. (Come stanno comunicando di nuovo i team di sviluppo?)
    • compatibilità con le versioni precedenti (è possibile importare modeller v1 in animator v3?)
    • l'integrazione di cloud / rete (se è una funzione) ora deve essere aggiornata con il doppio dei prodotti.
  • Ora hai tre mercati di consumo: modellisti, animatori e animatori modellisti

    • Avranno priorità contrastanti
    • Avranno esigenze di supporto contrastanti
    • Avranno stili di utilizzo contrastanti
  • Gli animatori Modeller devono aprire due applicazioni separate per lavorare sullo stesso file? Esiste una terza applicazione con entrambe le funzioni, un'applicazione carica le funzioni dell'altra?
  • eccetera...

Detto questo, basi di codice più piccole sono più facili da mantenere a livello di applicazione, non avrai un pranzo gratuito. Questo è lo stesso problema alla base dell'architettura Micro-Service / Any-Modular. Non è una panacea, le difficoltà di manutenzione a livello di applicazione vengono scambiate con difficoltà di manutenzione a livello di orchestrazione. Questi problemi sono ancora problemi, semplicemente non sono più nella base di codice, dovranno essere evitati o risolti.

Se risolvere il problema a livello di orchestrazione è più semplice di risolverlo a ciascun livello di applicazione, ha senso dividerlo in due basi di codice e gestire i problemi di orchestrazione.

Altrimenti no, semplicemente non farlo, si sarebbe meglio serviti migliorando la modularità interna dell'applicazione stessa. Distribuisci sezioni di codice in librerie coerenti e più facili da gestire per cui l'applicazione funge da plug-in. Dopotutto un monolite è solo lo strato di orchestrazione di un paesaggio di biblioteca.


3

Ci sono state molte buone risposte ma dato che c'è quasi una spaccatura morta, getterò anche il mio cappello sul ring.

Nella mia esperienza come ingegnere del software, ho scoperto che questo non è un problema semplice. Dipende davvero dalle dimensioni , dalla scala e dallo scopo dell'applicazione. Le applicazioni più vecchie in virtù dell'inerzia richiesta per cambiarle, sono generalmente monolitiche poiché questa era una pratica comune da molto tempo (Maya si qualificherebbe in questa categoria). Presumo che tu stia parlando di nuove applicazioni in generale.

In applicazioni abbastanza piccole che sono più o meno singole riguardano l'overhead richiesto per mantenere molte parti separate generalmente supera l'utilità di avere la separazione. Se può essere mantenuto da una persona, probabilmente può essere reso monolitico senza causare troppi problemi. L'eccezione a questa regola è quando si hanno molte parti diverse (un frontend, un backend, forse alcuni strati di dati in mezzo) che sono convenientemente separati (logicamente).

Nella mia esperienza, in applicazioni molto vaste, anche singole, la suddivisione ha senso. Hai il vantaggio di ridurre un sottoinsieme della classe di bug possibile in cambio di altri bug (a volte più facili da risolvere). In generale, puoi anche avere team di persone che lavorano in isolamento, il che migliora la produttività. Molte applicazioni in questi giorni sono tuttavia suddivise in modo piuttosto fine, a volte a loro svantaggio. Sono stato anche in team in cui l'applicazione è stata suddivisa in così tanti microservizi inutilmente che ha introdotto un sacco di sovraccarico quando le cose smettono di parlare tra loro. Inoltre, dover tenere tutta la conoscenza di come ogni parte parla alle altre parti diventa molto più difficile con ogni divisione successiva. C'è un equilibrio, e come puoi vedere dalle risposte qui il modo di farlo non è molto chiaro,


2
Il mio primo lavoro come programmatore è stato come programmatore di bug del millennio. Il software su cui stavo lavorando era diviso in centinaia di piccoli programmi che facevano tutti una piccola parte, uniti con file batch e usando file per comunicare lo stato. Era un gran casino, inventato in un'epoca in cui i computer erano lenti, con poca memoria e spazio di archiviazione costoso. Quando ci ho lavorato, il codice aveva già 10-15 anni. Una volta terminato, hanno chiesto il mio consiglio e il mio consiglio era di convertire tutto in una nuova applicazione monolitica. Lo hanno fatto e un anno dopo ho ricevuto un grande grazie.
Pieter B,

@PieterB Ho avuto un'esperienza simile. La tecnologia "all'avanguardia" è purtroppo un grande cult del carico in molti modi. Invece di scegliere il metodo migliore per il lavoro, molte aziende seguiranno qualunque cosa FAANG stia facendo in quel momento senza alcuna domanda.
CL40,

e anche: una volta compilata, quella che potrebbe venire fuori come un'applicazione monolitica potrebbe essere un'applicazione molto modulare, per quanto riguarda il codice.
Pieter B,

1

Per le app UI è improbabile che diminuisca la quantità complessiva di bug, ma sposterà l'equilibrio del mix di bug verso i problemi causati dalla comunicazione.

Parlando di applicazioni / siti dell'interfaccia utente rivolti all'utente, gli utenti sono estremamente non pazienti e richiedono tempi di risposta bassi. Ciò rende eventuali ritardi di comunicazione in bug. Di conseguenza, si scambierà la potenziale diminuzione dei bug a causa della ridotta complessità di un singolo componente con bug molto rigidi e requisiti di temporizzazione della comunicazione tra processi / tra macchine.

Se le unità di dati di cui il programma tratta sono grandi (ad es. Immagini), eventuali ritardi tra i processi sarebbero più lunghi e più difficili da eliminare - qualcosa come "applica trasformazione all'immagine a 10 MB" otterrà istantaneamente + 20 MB di I / O su disco / rete a 2 conversione dal formato in memoria al formato serializabe e viceversa. Non c'è davvero molto che puoi fare per nascondere all'utente il tempo necessario per farlo.

Inoltre, qualsiasi comunicazione, in particolare l'IO del disco, è soggetta a controlli AntiVirus / Firewall: ciò aggiunge inevitabilmente un altro livello di bug difficili da riprodurre e ancor più ritardi.

La suddivisione del "programma" monolitico brilla laddove i ritardi di comunicazione non sono critici o già inevitabili

  • elaborazione in blocco delle informazioni parallelizzabile in cui è possibile scambiare piccoli ritardi extra per un significativo miglioramento dei singoli passaggi (a volte eliminando la necessità di componenti personalizzati utilizzando una volta disponibile). Un ingombro ridotto può consentire di utilizzare più macchine più economiche invece di una singola costosa, ad esempio.
  • suddividere i servizi monolitici in micro-servizi meno accoppiati: chiamare più servizi in parallelo anziché uno molto probabilmente non aggiungerà ulteriori ritardi (può anche ridurre il tempo complessivo se ciascuno è più veloce e non ci sono dipendenze)
  • spostando le operazioni che gli utenti si aspettano di impiegare molto tempo: rendering di scene / film in 3D complessi, elaborazione di metriche complesse sui dati, ...
  • tutti i tipi di "completamento automatico", "controllo ortografico" e altri ausili opzionali possono e sono spesso resi esterni - l'esempio più ovvio sono i suggerimenti automatici per l'URL del browser in cui l'input viene inviato al servizio esterno (motore di ricerca) in ogni momento .

Si noti che ciò vale sia per le app desktop che per i siti Web - la parte del programma rivolta agli utenti tende a essere "monolitica" - tutto il codice di interazione dell'utente associato a un singolo dato è in genere eseguito in un singolo processo (non è insolito suddividere processi su base dati come pagina HTML o immagine ma è ortogonale a questa domanda). Anche per la maggior parte dei siti di base con input dell'utente vedrai la logica di validazione in esecuzione sul lato client anche se renderlo lato server sarebbe più modulare e ridurrebbe la duplicazione di complessità / codice.


0

Aiuta a prevenire i bug?

Impedire? Beh, no, non proprio.

  • Aiuta a rilevare i bug .
    Vale a dire tutti i bug che non sapevi nemmeno di avere, che hai scoperto solo quando hai provato a dividere l'intero casino in parti più piccole. Quindi, in un certo senso, ha impedito a quegli insetti di fare la loro comparsa in produzione - ma gli insetti erano già lì.
  • Aiuta a ridurre l'impatto dei bug .
    I bug nelle applicazioni monolitiche hanno il potenziale per far crollare l'intero sistema e impedire all'utente di interagire con la tua applicazione. Se si suddivide l'applicazione in componenti, la maggior parte dei bug, in base alla progettazione, interesserà solo uno dei componenti.
  • Crea uno scenario per nuovi bug .
    Se si desidera mantenere la stessa esperienza utente, sarà necessario includere una nuova logica affinché tutti quei componenti comunichino (tramite i servizi REST, tramite le chiamate di sistema del sistema operativo, quali sono) in modo che possano interagire perfettamente dal POV dell'utente.
    Come semplice esempio: la tua app monolitica consente agli utenti di creare un modello e animarlo senza uscire dall'app. Dividi l'app in due componenti: modellazione e animazione. Ora i tuoi utenti devono esportare il modello dell'app di modellazione in un file, quindi trovare il file e quindi aprirlo con l'app di animazione ... Ammettiamolo, ad alcuni utenti non piacerà, quindi devi includere una nuova logica per app di modellazione per esportare il file eavvia automaticamente l'app di animazione e aprila. E questa nuova logica, per quanto semplice, può avere una serie di bug riguardanti la serializzazione dei dati, l'accesso ai file e le autorizzazioni, gli utenti che cambiano il percorso di installazione delle app, ecc.
  • È la scusa perfetta per applicare il refactoring tanto necessario .
    Quando decidi di dividere un'app monolitica in componenti più piccoli, (si spera) lo fai con molta più conoscenza ed esperienza sul sistema rispetto a quando è stato progettato per la prima volta, e grazie a ciò puoi applicare un certo numero di refactor per rendere il codice più pulito, più semplice, più efficiente, più resistente, più sicuro. E questo refactoring può, in un certo senso, aiutare a prevenire i bug. Ovviamente, potresti anche applicare lo stesso refactoring all'app monolitica per evitare gli stessi bug, ma non lo fai perché è così monolitico che hai paura di toccare qualcosa nell'interfaccia utente e rompere la logica aziendale ¯ \ _ (ツ) _ / ¯

Quindi non direi che stai evitando i bug semplicemente rompendo un'app monolitica in componenti più piccoli, ma stai davvero rendendo più facile raggiungere un punto in cui i bug possono essere prevenuti più facilmente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.