Regole di programmazione
Post date: Feb 16, 2015 9:44:39 PM
Legenda
___ = regole relative al cambio di stato degli oggetti
Interferenza
Se da "getAziende" di una classe "persona", non torno una copia, espongo "azienda" in maniera pericolosa.
Programmazione interfacce
Non è la regola che fa cambiare il componente, ma è il componente che deve cambiare secondo la regola (dal suo interno)
Forms con gestione dati, aperte alla possibilità che qualcuno da fuori le apra in un certo stato o filtro sui dati (classe per gestire stati d'apertura)
Forms che mandano segnali e ricevono segnali da fuori
Maggior separazione fa interfaccia, logica businness e database (meglio fare 3 progetti distinti, in modo che la logica businness e il database siano inglobabili in altri progetti) MVC??
Controllo a chiusura form che se i dati sono variati chiedere a utente
Pattern Undo reso da implementare subito (vedere anche pattern Command)
Il programma deve essere intelligente. (Vedi concetto del peso in NameTouch)
Troppe funzionalità possono fare casino. Meglio poche ma mirate.
Non mescolare mai logica e presentazione
Principi OOP
Non usare gli enum per definire tipi di oggetto, categorie (vedi Open closed principle) meglio per codici d'errore, stati ecc..
Le property non devono essere usate per interrogare un oggetto e prendere una decisione poi in base allo stato ritornato.
L'oggetto chiamante conosce già lo stato, perché lui stesso lo ha impostato!
Se l'oggetto chiamate imposta uno stato, e successivamente, lo stato interno dell' oggetto chiamato varia (e io lo so perché ho progettato la classe), meglio esporre un metodo che internamente interroga lo stato e compiere l'azione; se invece so che non varierà non serve.
Mai utilizzare un proprietà di un oggetto complesso, come magazzino di valori per l'oggetto corrente (Es.:
A {//In questo caso ipotizzo di sapere per certo che GIGI non varia mai VAL = 1 B.GIGI = VAL //if (A == B.GIGI) non corretto //if(A == VAL) corretto }
Secondo i principi più puri dell’Object Oriented, property e accessor method dovrebbero consentire l’accesso al campo interno solo in termini di interfaccia: in nessun caso si dovrebbe consentire l’accesso diretto al campo interno
Un oggetto dovrebbe nascondere il proprio stato interno ed esporre solo metodi che permettano ai propri utilizzatori di invocare delle azioni (Es.: Per farsi dare la size, open cv non espone i metodi del campi interno ma torna un oggetto cv::Size s = _cv_image.size(); )
Se si ha modo di sostituire l’accessor col quale si chiederebbe all’oggetto una sua proprietà con un metodo col quale dire all’oggetto di fare qualcosa, è preferibile.
Meglio programmare in termini di “conversazione tra oggetti”, piuttosto che “indagine di valori per eseguire delle operazioni”. (l'indagine può essere fatta all'interno del oggetto stesso una volta chiamato il metodo. Così sono anche sicuro di non dimenticarmi effettuare il controllo ed incorrere in errori)
È il concetto che distingue la programmazione orientata agli oggetti da quella procedurale: un programma Object Oriented è il risultato della cooperazione tra oggetti che si inviano messaggi piuttosto che dell’esecuzione di procedure che consultano valori e poi prendono decisioni.
Le proprietà note alla nascita hanno un parametro di default nel costruttore.
Le proprietà che ho definito immutabili non hanno il setter
Se non ci sono responsabilità non ci sono funzioni
Se l'attributo è noto alla nascita e immutabile allora è final
Fare i controlli per la verifica delle post-condizioni a server e ritornare all'oggetto client un eventuale eccezione, se non sono soddisfatte
Verifica pre-condizioni sul client
Le precondizioni stabiliscono le eventuali restrizioni di definizione della funzione sull’insieme dei dati in input (dato dal tipo dei parametri) il chiamante deve assicurarsi di chiamare la funzione solo se le precondizioni sono soddisfatte, infatti se una precondizione non è rispettata al momento della chiamata, la funzione può comportarsi in modo imprevedibile.
Le post-condizioni specificano l’output della funzione.
Se il chiamante ha rispettato le pre-condizioni, la funzione deve rispettare le post-condizioni, cioè restituire i valori in conformità con esse.
Se non ci sono post-condizioni (complesse), i metodi posso essere scritti inline.
Le property forniscono dati all'oggetto affiché possa compiere le operazioni. Le property non devono compiere azioni.
Pre e post condizioni vanno espresse in termini di interfaccia pubblica
Le eccezioni sono appropriate quando si ha a che fare con fallimenti di risorse. (Es.: Disco, memoria, accesso alla rete, ecc..)
Non passare mai le eccezioni fino a livello di presentazione perché sono nel sottosistema sbagliato.
Le eccezioni vanno gestire convertendo un livello più basso in uno più alto che l'avvolge.
Se possibile si devono aggiunge eventuali informazioni per rendere l'eccezione più significativa per il contesto in cui viene intercettata.
Evitare di estrarre oggetti (child) da oggetti aggregati (parent), per poi passare e far circolare gli oggetti interni. Piuttosto va passato l’oggetto aggregato che contiene gli oggetti interni.
I metodi sono utilizzati per cambiare lo stato e il comportamento di un oggetto. Le proprietà interrogano i cambiamenti ma non ne eseguono funzioni.
I metodi sono void o al massimo ritornano bool per indicare che sono stati eseguiti con successo.
Id-To-Object: Trasformare un id numerico o stringa proveniente dal layer UI in un oggetto vero e proprio, appena entra nel dominio del modello di progetto.
Evitare di interrogare proprietà di un oggetto (che non siano lo stato o la sua esistenza), per poi eseguire un metodo in base al risultato. Chiamare direttamente il metodo. Sarà l'oggetto stesso a fare in necessari controlli per la sua esecuzione.
Mai chiamare prima una classe server passandogli valori per poi interrogare il suo stato che sarà variato in base a tali valori. Meglio un unico metodo che fa tutto.
Do It Myself: Io oggetto software, faccio quelle cose che vengono normalmente fatte dall'oggetto reale che rappresento e di cui sono un astrazione. (Es.: Circle e Square disegnano se stessi)
Se più client derivati possono eseguire uno stesso lavoro è meglio che lo faccia una classe server uguale per tutti altrimenti ogni uno lo fa come vuole
Un oggetto può utilizzarne un altro per adempiere ad un preciso scopo, ma lui stesso non è l'oggetto che utilizza, quindi per questo caso, NON si usa l'ereditarietà ma la composizione
Usare il pattern "Iterator" per accedere agli oggetti contenuti in una collezione di una classe, senza esporli direttamente