Distribuzione del codice Java nei pacchetti utilizzando un approccio di clustering

5

La teoria è che le classi che si conoscono e si utilizzano reciprocamente devono trovarsi nello stesso pacchetto (usando la visibilità pacchetto per le funzioni che non sono utilizzate dal resto dell'applicazione), formando così una concisa , interfaccia comprensibile. [Classi ben note (accessibili da quasi ovunque, come i logger) dovrebbero andare al loro pacchetto, chiamandolo utils .]

Assumi una base di codice di diverse centinaia di file Java, distribuiti piuttosto liberamente su circa sei dozzine di pacchetti, la maggior parte dei metodi ha dichiarato public (a parte alcuni private ), e relazioni piuttosto oscure tra le classi. (Nessun punto di ingresso chiaro, poiché i metodi vengono chiamati da un'infrastruttura JSF, se questo è importante. Potrebbero esserci alcuni metodi main() , ma di solito sono non usati .)

Qualcuno ha mai pensato di applicare un approccio di clustering per raggruppare un insieme così ampio di classi Java in pacchetti? Mi chiedo se e come ciò sia possibile, sia per delineare la forza delle relazioni tra le classi come aiuto per la pulizia manuale, sia per riorganizzare automaticamente il codice in qualche modo.

La misura della distanza potrebbe implicare il numero di funzioni necessarie per essere dichiarate public e il numero di istruzioni pacchetto import (cioè quelle che terminano con .* ) necessarie per la compilazione del codice. Dal momento che la risposta algoritmicamente "migliore" a quella domanda sarebbe quella di avere tutte le classi in un unico pacchetto (non richiede alcun metodo pubblico o importa più, che non è quello che voglio), mi sembra che un approccio di clustering gerarchico sarebbe il migliore (lasciando la granularità finale dei pacchetti come una decisione per gli umani), ma forse ci sono approcci migliori di cui non sono a conoscenza.

Ho cercato di trovare informazioni su quell'argomento, ma la ricerca di "Java" e "clustering" mi ha portato solo su pagine che spiegavano come implementare il clustering con Java, che non è quello che sto cercando . (Naturalmente, un approccio potrebbe essere implementato anche in Java, dal momento che potrebbe essere realizzato usando l'introspezione, ma non è importante per la mia domanda.)

    
posta Paramaeleon 13.02.2017 - 10:45
fonte

4 risposte

4

Did someone ever think about applying a clustering approach to group such a large set of Java classes into packages?

Sì, è stato un tema scottante nella ricerca di software (re) engineering (e più specificamente nella ristrutturazione del software) qualche anno fa, con algoritmi di taglio della rete di flusso (sia per il punto di vista strutturale che comportamentale) e alcuni altri approcci.

Alcuni riferimenti, in realtà ci sono molti articoli di ricerca su questo argomento:

Sono state considerate anche altre nozioni di distanza / somiglianza. Ad esempio, i moduli (ad es. Le classi) che sono spesso modificati negli stessi commit possono essere considerati "vicini" l'uno all'altro poiché tendono a coevolvere nel tempo. Pertanto, la determinazione dei cluster di questi moduli "simili" aiuta a prevenire i bisogni dimenticati di coevoluzione (hai cambiato classe, e hai dimenticato di cambiare quella classe correlata) e di evidenziare le relazioni implicite (e forse indesiderate) tra i moduli.

    
risposta data 14.02.2017 - 10:48
fonte
3

In realtà ho pensato a questo argomento esatto. L'idea che ho preso è stata:

  1. Rappresenta la base di codice del progetto come un grafico.
  2. Ogni classe diventa un vertice nel grafico.
  3. Ogni metodo dichiarato con Parametri diventa un vantaggio diretto. Quando la Classe A ha un metodo che richiede un parametro di input di tipo Classe B, viene aggiunto al grafico un bordo diretto dalla Classe A alla Classe B. Ad esempio, il metodo (dichiarato all'interno di ClassA) public void doWorkWith(ClassB b, ClassC c) comporterebbe l'aggiunta di 2 bordi diretti al grafico.
  4. Ho considerato i tipi e le classi di ritorno del metodo utilizzati nell'implementazione ma non esposti a livello di API. Ho dimenticato come intendevo gestire questi
  5. Utilizza la riflessione Java per creare il grafico a livello di codice.
  6. Esegui qualche tipo di rilevamento di cluster e / o community sul grafico risultante

Ho anche trovato poche informazioni su questo argomento quando sono andato in giro online. Detto questo, il libro Sviluppo software agile di Robert Martin tratta questo argomento.

Non l'ho implementato perché: (1) è un sacco di lavoro e (2) scommetterei soldi seri che qualsiasi progetto che deve essere analizzato in questo modo risulterebbe in un grafico orribilmente intrecciato che è difficile "separare" pulito". Di conseguenza, ho focalizzato i miei sforzi sul refactoring del progetto per utilizzare più Dependency Injection.

Modificato per aggiungere: una cosa semplice e veloce da fare è semplicemente contare il numero di istruzioni di importazione. Classi che parlano in senso ampio che iniziano con una dichiarazione di zillion import sono i principali obiettivi per gli sforzi di miglioramento Purtroppo, quelle sono probabilmente le classi più pericolose da toccare.

    
risposta data 13.02.2017 - 16:50
fonte
1

Non sono d'accordo con la tua ipotesi di base, che è meglio separare le classi in pacchetti per minimizzare le dipendenze tra i pacchetti. Seguendo questa euristica estremizzazione, finiamo con tutte le classi nello stesso pacchetto, che è chiaramente un incubo di manutenzione. Ma anche senza usare un argomento così riduttivo e assurdo, mi sembra che il fattore più importante nel decidere dove dovrebbe essere una classe è che si inserisce logicamente in un pacchetto tale che i programmatori del team saranno in grado di indovinare dove dovrebbe essere.

Ridurre al minimo le dipendenze è una buona cosa, ma dovremmo probabilmente usare tecniche come facciate o inversione di dipendenza come metodo principale per raggiungere questo obiettivo, piuttosto che spostare il codice in modo che client e server siano insieme.

    
risposta data 13.02.2017 - 13:47
fonte
0

Proporrò questa risposta, anche se è molto più un puntatore a un'eccellente discussione e strumento per visualizzare queste relazioni, fornendo un punto di partenza per il refactoring e l'esposizione degli effetti del refactoring.

Edmund Kirwan è ossessionato da questo argomento e il suo sito è pieno di interessanti rivelazioni sulla struttura del codice. Il suo strumento di analisi, Spoiklin Soice, è disponibile sul suo sito.

Sito di Edmund

L'articolo

    
risposta data 17.02.2017 - 17:52
fonte

Leggi altre domande sui tag