Perché sviluppare librerie interne per applicazioni interne?


10

Ho difficoltà a capire perché dovresti sviluppare librerie interne da utilizzare esclusivamente per lo sviluppo di applicazioni interne. Apprezzo che se voglio usare un software scritto da qualcuno al di fuori dell'organizzazione, possono inviarmi i loro file di intestazione e file .a o .so e posso semplicemente collegarlo al mio progetto (supponendo che siano compilati nello stesso ambiente) .

Ma perché una libreria interna dovrebbe essere sviluppata solo per essere collegata a un'applicazione interna quando ho accesso all'intestazione e ai file di implementazione e posso semplicemente includerli nel mio albero dei sorgenti e compilarli tutti insieme?

In altre parole: se viene scritto un codice sorgente, come si decide se deve essere compilato in una libreria binaria e collegato alla propria applicazione o semplicemente incluso nei file sorgente del progetto e compilato regolarmente?

Quando dico "includi" file in ciascun progetto, non intendo copiare e incollare ciascun file nella struttura di origine del progetto attualmente in fase di sviluppo. Intendo sviluppare una directory / libreria (separata da qualsiasi progetto) contenente codice sorgente comune che può essere incluso nei file di un progetto nel solito modo, ad esempio #include.

ps Sto parlando di sviluppo c / c ++ qui per più applicazioni desktop.


Risposte:


25

Esistono numerosi motivi per creare librerie e librerie condivise (in file .dll o .so) anche per uso interno:

  1. Il riutilizzo in tutti i progetti è molto più pulito
  2. Separazione di responsabilità: parte del codice potrebbe essere più adatta a sviluppatori o team diversi
  3. Puoi trarre vantaggio dai miglioramenti delle librerie realizzati da altri team senza dover individuare il codice specifico
  4. Tempi di costruzione più rapidi, se la libreria è stabile non è necessario ricostruirla.
  5. Spazio su disco: puoi avere solo la libreria e le intestazioni nel progetto
  6. Se si utilizzano librerie condivise è possibile risparmiare memoria con una sola copia caricata nella RAM anche se la stanno utilizzando diversi programmi
  7. In genere si finisce con una migliore documentazione e test delle librerie
  8. Design e codice più puliti: pensare a strutturare le cose in librerie dovrebbe tradursi in gruppi correlati di funzionalità in ciascuna libreria e si tende a separare il codice generico, nelle librerie , dalle specifiche dell'applicazione, nell'app .
  9. Se nelle librerie sono presenti algoritmi proprietari, è possibile limitare l'accesso alla fonte, ad es. Non consentire agli appaltatori o ai team di provenienza di accedere alla fonte.
  10. Il codice della biblioteca può essere posto sotto una diversa licenza per l'Applicazione di cui era stato originariamente scritto, alcune aziende sono persino conosciute dalle biblioteche Open Source di cui sono orgogliose - guadagnando grandi complimenti nella comunità Open Source e qualche volta hanno apportato importanti miglioramenti indietro.

Alcune aziende hanno persino una pratica contabile in cui i progetti che creano biblioteche ottengono un rimborso per ogni riutilizzo.


1
O in una variante del punto 9, è possibile rilasciare la libreria con una licenza diversa rispetto al codice dell'applicazione principale.
Michael Borgwardt,

@MichaelBorgwardt - Buon punto che spinge il punto 10 sopra.
Steve Barnes,

Inoltre, avere un po 'di codice come libreria separata aiuta ad evitare le scorciatoie durante la programmazione, come "Aggiungerò solo questo parametro extra qui ..." e aiuta a trovare modi migliori per implementare le funzionalità richieste.
Valdas,

11

Alcune altre possibili ragioni che possono applicarsi a progetti più grandi e non banali:

  • Tempi di compilazione: enormi progetti monolitici in C ++ con migliaia di file, migliaia di classi, funzioni, ecc. Possono richiedere molto tempo per essere compilati (il che danneggia la produttività se si desidera ricompilare ogni volta che si cambiano alcune righe di codice). Le librerie collegate staticamente e dinamicamente vengono compilate in modo indipendente e non devono essere ricompilate se la loro fonte non è cambiata.

  • Separazione logica di moduli o sottosistemi distinti : i sistemi di grandi dimensioni sono in genere più facili da gestire se aree distinte di funzionalità sono collocate in moduli separati e gli sviluppatori non devono affrontare ricerche in enormi cartelle / progetti contenenti migliaia di file / classi.

  • Limiti tra sviluppatori / team : gli sviluppatori che creano nuove funzionalità separate allo stesso tempo possono ridurre il potenziale di unire conflitti se è possibile far lavorare ciascuno sviluppatore in moduli diversi.

  • Codice che non deve essere rilasciato in un ambiente live : ad esempio librerie di unit test o librerie "finte" che vengono utilizzate per i test degli sviluppatori in sostituzione di un componente di sistema live (hardware, API, sistemi remoti, database, ecc.)

  • Flag del compilatore : se ti trovi nella sfortunata posizione di integrazione con alcune API di terze parti che prevedono uno strano flag di compilazione, la libreria può essere un "livello di decontaminazione" che si trova tra l'API di terze parti e il resto dell'applicazione.

  • Funzionalità opzionali / Ottimizzazione : in sistemi di grandi dimensioni, un'applicazione potrebbe attendere prima di caricare determinati moduli collegati dinamicamente in memoria in fase di esecuzione se non sono fondamentali per la funzionalità di base dell'applicazione.


In generale, molti progetti interni sono spesso piccole micro-app che non beneficiano della suddivisione in librerie separate. Se stai lavorando a un piccolo progetto come sviluppatore solitario, allora potresti non aver bisogno di preoccuparti di dividere il tuo codice in librerie (ancora ...). Non dimenticare il principio YAGNI .


3
@downvoter - potresti spiegare il motivo del downvote? Il feedback sulle risposte è utile per migliorare la qualità di questo sito per tutti.
Ben Cottrell,

4

La tua domanda originale potrebbe aver causato un malinteso qui per la maggior parte di quelle altre risposte. Dal momento che non si intende copiare codice esistente su più progetti, ma includere come riferimento gli stessi file di origine da progetti diversi , qualsiasi argomento "codice duplicato" diventa inutile, così come molti altri argomenti presentati.

Nota che questa è talvolta (- non sempre -) una tecnica sensata . In effetti, quando si mettono tutti i file di origine che si desidera riutilizzare tra i progetti in una cartella di inclusione separata, è già stata creata anche una libreria binaria: una libreria di codice sorgente, non una libreria binaria. Soprattutto in C ++, quando si creano librerie generiche con modelli, non è insolito avere librerie solo intestazione, che richiedono solo una semplice inclusione e nessuna preparazione di collegamento separata.

Quindi immagino che la tua vera domanda sia: quando creare librerie di codice sorgente o quando preferire librerie binarie precompilate? In questa vecchia risposta su questo sito , ho discusso alcuni pro e contro delle librerie solo intestazione, forse ti aiuta. Il vantaggio principale delle librerie di codice sorgente è che non devono essere compilate con gli stessi flag di compilatore / linker runtime e / o compatibili dell'applicazione che le utilizza. Gli svantaggi sono i tempi di compilazione aggiuntivi e la necessità di fornire l'accesso al codice sorgente (che ovviamente non è un problema per il tipo di progetti "interni" che hai in mente).


È vero che intendevo una libreria di codici sorgente che è comune a più progetti in cui fai riferimento ai file di cui hai bisogno attraverso la tipica direttiva #include - Non sapevo il termine fino a quando non l'hai detto e modificherò il domanda ora. Anche la tua risposta collegata è molto utile.
Andrew Murtagh,

@AndrewMurtagh: il fatto che tu stia accettando così rapidamente la risposta di MichaelBorgwardt mi ha stupito, perché quello che ha scritto sembra essere un mio malinteso o mio.
Doc Brown,

beh, ha chiarito la confusione iniziale che avevo di quando raggruppare il codice che sarebbe comune a più progetti in un singolo pacchetto (sia che si trovasse nelle librerie binarie o nelle librerie del codice sorgente) ma concesso, stavo parlando di avere una singola directory di sorgente codice che potrebbe essere condiviso tra i progetti e non copiare e incollare ogni file in ciascun progetto perché potrei averne bisogno.
Andrew Murtagh,

2

Sono d'accordo con altri commentatori quando scrivono che non dovresti duplicare il codice. Nel tuo caso, tuttavia, sembra che tu (o le persone con cui lavori) crei librerie per codice che non è duplicato altrove.

In questo caso, metto in guardia dalla generalizzazione prematura . Ci sono volte in cui ci si sente come se un pezzo di codice fosse riutilizzabile. Tuttavia, senza conoscere i dettagli intimi di come il secondo caso d'uso utilizzerà tale codice, è molto facile dedicare più tempo alle funzionalità di "riusabilità" che non saranno effettivamente utili nei casi aggiuntivi o fare ipotesi che si dimostrano errate in il secondo caso.

Scrivere una "biblioteca" per un caso d'uso può trasformarsi in un esercizio molto costoso senza alcun profitto --- sono stato morso da questo diverse volte.

Esempio di costi:

  1. Tempo / energia impiegato per considerare casi "generali"
  2. Tempo impiegato per rendere la "libreria" distribuibile al tuo "client" (il tuo codice)
  3. La pressione futura a fare uso della "libreria" anche se non corrisponde completamente al caso d'uso successivo

La mia regola generale è: non creare codice in una libreria a meno che non abbia almeno 2 posti separati in cui è necessario il codice.


2
Ho visto quasi esattamente le stesse ragioni usate da alcuni sviluppatori come il motivo per cui il loro codice è tutto in un singolo file sorgente di linea> 20k. Se combinato con nomi bizzarri e commenti scadenti, si ottiene presto un codice che è più veloce da riscrivere che da mantenere.
Steve Barnes,

Ottimo punto: non sto certamente discutendo contro la scrittura di codice mantenibile e leggibile. File separati, metodi / classi ben definiti e struttura del pacchetto sono tutti componenti importanti della manutenibilità. Il mio punto è solo che i costi di scrittura + distribuzione di una biblioteca sono elevati per sostenere quando esiste un solo caso d'uso per la "biblioteca".
Sam,

1
Al contrario, non sto sostenendo che devi necessariamente impacchettare e distribuire una libreria in ogni caso, solo che scrivere e strutturare come se un giorno il tuo codice potesse diventare una libreria di solito vale un piccolo sforzo e spesso paga dividendi anche se il codice non diventa mai distribuito come una biblioteca.
Steve Barnes,

1

perché una libreria interna dovrebbe essere sviluppata solo per essere collegata a un'applicazione interna quando ho accesso all'intestazione e ai file di implementazione e posso semplicemente includerli nel mio albero dei sorgenti e compilarli tutti insieme?

Perché se "li includi semplicemente nel mio albero dei sorgenti", stai duplicando il codice .

Il problema è che non trarrai alcun vantaggio da eventuali miglioramenti (inclusi bugfix critici) apportati dal progetto da cui hai copiato il codice, né trarranno vantaggio da alcun miglioramento apportato.

Potresti pensare di poter risolvere questo problema semplicemente copiando regolarmente la versione più recente del codice nel tuo albero dei sorgenti, magari anche automatizzato usando un sottomodulo in git o qualcosa di simile. Ma poi avrai costantemente la tua pausa di costruzione a causa di modifiche API incompatibili. D'altra parte, una libreria ha un'API pubblica "ufficiale" che i suoi sviluppatori sanno che non può essere cambiata senza coodinamica con i clienti.

Infine, potrebbero esserci ragioni tecniche: mantenere parte del codice come libreria potrebbe essere necessario in modo che possa essere caricato facoltativamente o anche caricato e scaricato su richiesta, e quindi ridurre l'utilizzo della memoria quando non è necessaria la funzionalità?


1
Quindi, a quanto ho capito, il motivo principale per trasformare un pezzo di codice in una libreria è quando verrà utilizzato in diversi progetti (anche se sono tutti sviluppati internamente) in modo che quel codice non possa essere duplicato, aggiornato, mantenuto separatamente? E se hai intenzione di sviluppare un singolo progetto, non è necessario trasformare qualcosa in una libreria (a meno che tu non intenda utilizzarlo in altri progetti in un secondo momento).
Andrew Murtagh,

@AndrewMurtagh: Sì, è esattamente come l'ho messo io. Sebbene ci possano essere anche ragioni tecniche; Non ho familiarità con lo sviluppo di C / C ++ - forse mantenere parte del codice come libreria è necessaria in modo che possa essere caricato facoltativamente o anche caricato e scaricato su richiesta, e quindi ridurre l'utilizzo della memoria quando non è necessaria la funzionalità?
Michael Borgwardt,

Credo che ciò possa essere possibile attraverso librerie condivise. Grazie per il chiarimento, segnerò la tua risposta come accettata.
Andrew Murtagh,

Quasi tutti i VCS dell'ultimo decennio supportano riferimenti o sottomoduli esterni. Ciò ha rimosso il codice duplicato e il problema di correzione degli errori. Potrebbe includere ulteriori informazioni sul perché queste non sono una soluzione praticabile se si ritiene ancora che siano problemi validi.
Sirisian,

Pensa anche alla manutenzione. 1) La libreria può essere mantenuta in modo indipendente e in parallelo. 2) Il codice è facile da sostituire. 3) Le piccole basi di codice sono più facili da gestire per i piccoli team e più facili da comprendere per tutti. 4) se il time-to-market è fondamentale, preferirai avere build più veloci. Il codice in libs è il codice che non si compila più volte nella pipeline (IMO). 5) È un codice riutilizzabile affidabile ...
Ce l'

1

Vorrei approfondire i costi che la vostra soluzione ha a lungo termine.

Chiaramente, l'aggiunta di una libreria a un progetto ha un certo sovraccarico, soprattutto se è il primo: i flussi di lavoro devono essere cambiati, a volte anche l'infrastruttura e alcuni membri del team potrebbero non apprezzarlo (all'inizio). Così i vantaggi della soluzione sono evidenti, in quanto impone al netto dei costi ora .

Tuttavia, man mano che il tuo progetto cresce, aumenteranno anche i costi della "pseudo-biblioteca". Supponiamo di avere una "pseudo-libreria" Ache viene utilizzata da un'applicazione e da un tester di unità. Ogni volta che aggiungi un cpp a A, devi aggiungerlo a entrambi i progetti, altrimenti non si collegheranno.

E se la tua "pseudo-biblioteca" viene utilizzata da un'altra "pseudo-biblioteca" B? Devi aggiungere il tuo nuovo cpp in un sacco di progetti in più. E se Bpassare a utilizzare un'altra libreria? Dovrai eliminare i cpps da Atutti i progetti in base solo a B.

Tutto questo sarebbe gratuito se si utilizzasse una vera libreria. Quindi la domanda è: quanti cpp sono necessari per giustificare il passaggio a una vera libreria?

Ma aspetta, c'è ancora più garanzia: a uno sviluppatore non piace questo stupido lavoro di caccia di tutti i progetti che richiedono il nuovo cpp down e aggiungerà il suo codice / classi da qualche parte in file già esistenti, il che non è una buona cosa in la lunga corsa.

Quindi usare la "pseudo-biblioteca" può essere un primo passo per spezzare un progetto monolitico, ma non dovresti aspettare troppo a lungo per renderlo una vera biblioteca per poterne sfruttare i vantaggi.


0

Ma perché una libreria interna dovrebbe essere sviluppata solo per essere collegata a un'applicazione interna quando ho accesso all'intestazione e ai file di implementazione e posso semplicemente includerli nel mio albero dei sorgenti e compilarli tutti insieme?

Se la libreria è sempre e solo utilizzato da un'applicazione, allora probabilmente non è necessario come una libreria separata.

Se la libreria viene utilizzato da 3.500 applicazioni, allora è assolutamente farlo serve come una libreria separata.

Che cosa succede se nella libreria è presente un bug e devi risolverlo? O qualche modifica statutaria o regolamentare arriva Ciò significa che hai di cambiare il modo in cui le opere della biblioteca?

Se si trova in una libreria separata, è possibile (potenzialmente) correggere la libreria, riprovarla e ridistribuirla e ogni applicazione beneficia della correzione.

Se è solo nel codice sorgente "locale" per ogni applicazione, allora devi cambiare, ricostruire, riprovare e ridistribuire ogni singola applicazione . È un esercizio molto più grande (cioè più costoso).

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.