Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
La riorganizzazione del codice secondo le linee suggerite da marco_ e TheDarkJuster si sta dimostrando più intricata del previsto, per l'autodidatta che sono. "Isolare" parti di un programma non mi è così semplice come pensavo a prima vista. Scopro ogni momento d'aver bisogno di tanta, tanta pratica e di montagne di ripensamento del mio modo di intendere la realizzazione d'un programma anche semplice come il "Codificatore". Ma non demordo!
ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
Probabilmente il metodo migliore per iniziare è leggere qualche articolo scritto bene e/o qualche buon source, cercare di reinventare la ruota è faticoso(anche se non è un cattivo esercizio).
<AldoBaldo> di poche parole, eh?
Se fossi rimasto altri 5 minuti ti avrei risposto. In genere di sera trovi più gente(non molta).
Fino a qualche mese fa era ostico anche per me utilizzare le classi in modo logico, pensare a come utilizzarle era una faticaccia ma devo dire che dopo essermi costretto a non scrivere codice fuori da una classe, main escluso mi sono abitutato abbastanza in fretta, soprattutto al modo di vedere logicamente gli oggetti. L'unico consiglio che posso darti è pensa al tuo algoritmo come qualcosa di astratto: molto astratto, ma teoricamente implementabile ovunque. E guarda la STL del C++, perchè ti sprona un sacco a usare codice c++ organizzato in modo logico. O almeno, per me è così
Non esistono regole fisse per la progettazione di un diagramma a classi, è un esercizio per lo piu di design. Se per un problema algoritmico ci sono 20 soluzioni, per lo stesso problema visto dal punto di design delle classi magari ce ne sono 200. Ci sono però delle linee guida che si possono seguire. Nel tuo caso hai un programma che codifica e decodifica un file quindi un punto comune è questo, un file, quindi per la classe avrai un puntatore ad a questo file, magari passato per costruttore; avrai anche un puntatore al file dizionario; stesso ragionamento. Avrai dei metodi pubblici che permettono la codifica e la decodifica del file, dei metodi che permettono di cambiare il file source, ugualmente delle funzioni che permettano il cambio del dizionario.
Dovresti applicare un interpretazione a strati
Applicazione con interfaccia utente
----------------------------------
Classe di codifica e decodifica
----------------------------------
File sorgente | file dizionario
Devi solo pensare un interfaccia facilmente fruibile dallo strato applicativo, la stratificazione ti costringe a mantenere le specifiche di interfaccia mentre aggiorni il contenuto della classe.
Cerca di capire cosa avrà bisogno l'applicazione per poter funzionare senza dover modificare in alcun modo la classe.
Certo che avere un po di esperienza in un linguaggio puramente OOP ti aiuterebbe non poco.
Grazie dei consigli, dei quali cerco di tenere sempre conto (in caso contrario perché dovrei star qui a stressarvi?).
Al momento credo d'essere a buon punto nell'implementare una classe cdf (CoDiFicatore) che viene creata "nulla", ovvero senza contenere dati di sorta, e successivamente foraggiata con una stringa che rappresenta la chiave e con il percorso d'un file ricavato tramite la classica finestra di navigazione dalla parte del programma che si occupa dell'interfaccia.
La classe...
1. ...crea un duplicato della stringa della chiave e la immagazzina in una delle sue proprietà private.
2. ...apre e legge il file del quale riceve il percorso, usando la libreria standard, caricandone il testo da codificare/decodificare.
3. ...riconosce e memorizza l'operazione da compiere (codifica o decodifica) in base all'estensione del file.
4. ... effettua la verifica della compatibilità tra i dati da elaborare e la chiave per elaborarli.
5. ... codifica/decodifica i dati salvandoli autonomamente in un file del quale compone il percorso a partire da quello del file "sorgente".
Fornisce inoltre alcuni metodi "accessori" di lettura per permettere alla sezione di interfaccia di conoscere lo stato delle proprietà e adeguare l'attivazione dei pulsanti, le stringhe di segnalazione per l'utente, la lista dei caratteri mancanti, ecc.
Nelle intenzioni dovrebbe avere ben pochi metodi pubblici, occupandosi "interiormente" degli aspetti più macchinosi dei procedimenti attivati dai comandi (a me sembra che una classe dovrebbe comportarsi così, ma ogni tanto le mie certezze vacillano).
Non credo che implementerò costruttori di copia e overload di operatori, perché non intendo creare situazioni che li richiedano. FORSE sottoporrò a overload le funzioni creatrici, per fare in modo che accettino all'atto della creazione i dati che ora devono essere forniti successivamente. Non dovrebbe essere complicato, perché nei fatti dovrebbe essere sufficiente richiamare i metodi che già sto predisponendo.
Eliminando i prototipi dei metodi privati, al momento la classe appare così:
Codice sorgente - presumibilmente C++
#ifndef CDF_H
#define CDF_H
// un po' di costanti
constchar kEstensioneFileCodificato[]="cdf";
constchar kEstensioneFileInChiaro[]="txt";
enum{ kNoDati, kDaCodificare, kDaDecodificare };
class CDF {
public:
CDF();
virtual ~CDF();
void imposta_chiave(constchar*sChiave, unsignedlong l = 0xFFFFFFFF )
throw(constchar*);
void imposta_dati(constchar*percDati, unsignedlong l = 0xFFFFFFFF )
EDIT: non è che mi sto avviando verso la creazione d'una classe "blob"? Farei forse meglio a lasciare i dati a un livello ESTERNO alla classe e a passarli a questa come parametri per un processamento immediato e un altrettanto immediato abbandono? Ma, facendo così, dove sarebbe il vantaggio dell'avere una classe anziché un semplice set di funzioni?
Ultima modifica effettuata da AldoBaldo il 02/02/2015 alle 18:30
ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
usare std::string anzichè char* dovrebbe portarti a eliminare lChiave e lDati. le stringhe della STL sono inoltre oggetti con metodi che potrebbero tornarti utili..... Io te lo dico, non si sa mai........ Nel C++11 non serve specificare il tipo delle eccezioni lanciate dai metodi, quindi niente
Codice sorgente
void elabora( void )
throw (const char*);
e così via...... InizializzaNullo sarà un metodo che chiamerai solo dal costruttore? Se si, fai un pensierino sul rimuoverlo e traslocare il suo contenuto nel costruttore. Io personalmente ti sconsiglio di gestire i file direttamente in quella classe, in quanto dovrebbe poter cifrare/decifrare un flusso di byte in memoria, non necessariamente memorizzati in un file, ma per esempio da una chat o simile.
Codice sorgente - presumibilmente C++
unsignedchar carMancanti[256];// la lista dei caratteri mancanti nella chiave
unsignedint nCarMancanti;// la quantita dei caratteri mancanti
un bel std::vector<uint8_t> carMancanti sostituirebbe egreggiamente quel codice. Quando ti serve nCarMancanti basta fare this->carMancanti.size(); e per salvare un nuovo carattere this->carMancanti.push_back(...);
Passi da gigante rispetto alla prima versione, segui i consigli di Juster.
Normalmente i metodi e le proprietà pubbliche si scrivono con le iniziali maiuscole "CamelCase", e le variabili private con la prima lettera minuscola e le parole successive con la prima lettera maiuscola, i _ si adoperano nelle definizioni. Puoi scegliere di seguire queste piccole regole di ordine, ma non sei obbligato, molti coder non usano delle notazioni ordinate, ma questo non rende i loro algoritmi meno concorrenziali. Non mi azzardo assolutamente a consigliarti di usare nomi inglesi, hai gia chiarito la tua posizione XD
Juster ha sottolineato un punto importante, vuoi limitare la tua classe alla sola codifica di file o di uno stream generico?
Lasciare che sia la classe a decidere se codificare o decodificare non mi sembra un ottima idea, potrebbe precluderti delle implementazioni future, io lascerei le funzioni codifica e decodifica come pubbliche.