Esercizio con classi

di il
8 risposte

Esercizio con classi

Ciao a tutti, mi presento, mi chiamo Angelo e sono di Milano.
Da qualche tempo ho deciso di riprendere in mano Java dato che lo avevo studiato a scuola ma non l'ho mai approfondito.
Quindi ho deciso di ripassarlo e successivamente migliorare la mia conoscenza in merito.

Dopo un po' di ripasso ed esercizietti vari, come "allenamento" ho deciso di implementare un programmino che servisse a gestire in maniera molto base un conto corrente. Vi riporto il codice sotto:
Ho creato prima questa classe main

package ContoCorrente;
import java.io.*;
public class CC {

	//main
	public static void main(String[] args) {
		InputStreamReader reader = new InputStreamReader(System.in);
		BufferedReader input = new BufferedReader(reader);
		int scelta, continua;
		double prelievo = 0, tmp_saldo = 0;
		String ultimiMov[];
		boolean riprova = true;
		//creo conto con saldo iniziale
		CC_oper conto = new CC_oper(1000.50);
		System.out.println("Benvenuto!\nIl tuo saldo iniziale è: "+conto.getSaldo()+" €");
		while(true) {
			scelta = 0;
			continua = -1;
			System.out.println("Quale operazione si vuole eseguire: \n1 - Visualizza saldo\n2 - Visualizza ultimi 5 movimenti\n3 - Prelievo\n4 - Versamento");
			while (scelta <1 || scelta >4) {
				try {
					scelta = Integer.parseInt(input.readLine());
				}catch(Exception e) {
					System.out.println("Errore: \n"+e);
				}
			}
			switch(scelta) {
				case 1:
					//visualizza saldo
					System.out.println("Il tuo saldo attuale è "+conto.getSaldo());
					break;
				case 2:
					//visualizza gli ultimi 5 movimenti
					System.out.println("Ultimi movimenti fatti:");
					ultimiMov=conto.getMovim();
					for (int i =0; i<ultimiMov.length; i++) {
						if(ultimiMov[i]!="") {
							System.out.println(ultimiMov[i]);
						}else {
							break;
						}
					}
					break;
				case 3:
					//prelievo
					while (riprova) {
						System.out.print("Quanto desideri prelevare? ");
						try {
							prelievo = Double.parseDouble(input.readLine());
						}catch(Exception e) {
							System.out.println("Errore: \n"+e);
						}
						tmp_saldo = conto.getSaldo();
						if(tmp_saldo < prelievo) {
							System.out.println("Non è possibile prelevare più denaro di quello disponibile.");
							riprova = true;
						}else {
							riprova = false;
						}
					}
					conto.setSaldo(tmp_saldo-prelievo);
					conto.setMovim("Prelievo di "+prelievo);
					break;
				case 4:
					//versamento
					System.out.print("Quanto desideri versare? ");
					try {
						prelievo = Double.parseDouble(input.readLine());
					}catch(Exception e) {
						System.out.println("Errore: \n"+e);
					}
					conto.setSaldo(conto.getSaldo()+prelievo);
					conto.setMovim("Versamento di "+prelievo);
					break;
			}
			while (continua <0 || continua >1) {
				System.out.println("Desideri effettuare altre operazioni? \n0 - No\n1 - Sì");
				try {
					continua = Integer.parseInt(input.readLine());
				}
				catch (Exception e){
					System.out.println("Errore "+e);
				}
			}
			if(continua == 0) {
				System.exit(0);
			}
		}
	}
}
e poi quest'altra che dovrebbe rappresentare effettivamente il mio oggetto conto corrente.

package ContoCorrente;

public class CC_oper {
	//variabili di classe
	private double saldo;
	private String movimenti[]=new String [10];
	int numMov = 0;
		
	//costruttore
	public CC_oper(double s) {
		saldo = s;
		//init a vuoto dei movimenti
		for (int l =0; l<movimenti.length; l++) {
			movimenti[l]="";
		}
	}
		
	/****************************************
				metodi di classe
	 ***************************************/
	public double getSaldo() {
		return saldo;
	}

	public void setSaldo(double nuovoSaldo) {
		saldo = nuovoSaldo;
	}

	public String[] getMovim() {
		return movimenti;
	}

	public void setMovim(String oper){
		boolean insertOk = false;
		for (int i = 0; i<movimenti.length; i++) {
			if(movimenti[i]!="") {
				//non faccio niente
				insertOk = false;
			}else {
				movimenti[i]=oper;
				insertOk = true;
				numMov ++;
				break;
			}
		}
		if(insertOk) {
			//non faccio niente
		}else {
			//non ho inserito, quindi sovrascrivo il movimento più "vecchio"
			movimenti[numMov%10]=oper;
		}
		if(numMov==10) {
			numMov = 0;
		}
	}
}
Il programma funziona, o almeno fa quello che deve, ma volevo dei suggerimenti nel caso in cui ci fosse qualcosa da migliorare (sicuramente).
Ogni suggerimento è ben accetto purchè costruttivo

8 Risposte

  • Re: Esercizio con classi

    Come puoi ben immaginare, ci sono un bel po' di pasticci, ma ci puo' stare per essere un primo tentativo.

    0) STUDIA i concetti fondamentali della programmazione ad oggetti. Saper usare un linguaggio di programmazione NON VUOL DIRE SAPER PROGRAMMARE, cosi' come conoscere dei termini in inglese NON VUOL DIRE saper scrivere in inglese.

    1) non sono metodi di classe ma di istanza. I metodi di classe sono quelli associati alla classe e che ritornano lo stesso risultato per TUTTE le istanze.

    2) separa l'input dall'output e dalla manipolazione degli oggetti.

    3) usa un UNICO ciclo nel main dove richiedere l'operazione ed eseguirla

    4) la gestione dei try/catch e' sbagliata. E' tutta una questione filosofica, quindi non c'e' un unico modo per usarli e non si puo' spiegare una filosofia a suon di post. Diciamo che puoi usare un try/catch per operazione E BASTA.

    5) NON VOLER FARE tutto in un colpo solo: costruisci il programma un pezzetto alla volta e quando quel pezzetto funziona, passa al successivo. Se ti rendi conto che c'e' un modo migliore per fare le cose, butta via tutto e riparti. NON ESISTE il concetto di ""buona la prima"".

    6) un buon programma e' quello che fa tutto con il numero minimo di linee di codice. E il numero minimo di linee di codice NON LO SI OTTIENE scrivendo il codice, MA RAGIONANDO CON LA TESTA.

    Per esperienza insegna che si possono radoppiare le funzionalita' dimezzandone il codice.
    Il limite e' riuscire a fare tutto senza niente


    Usa 4 oggetti:
    - Banca: lista di conto correnti e lista di correntisti
    - Conto Corrente: correntista, saldo e lista di movimenti
    - Movimento: importo, tipo di movimento e data in cui e' avvenuto
    - Correntista: nome cognome e lista di conto correnti

    Studiati le 'collezioni' : il vettore e' la piu' semplice ma anche la piu' stupida (nel senso che e' semplice lei, non la tua scela ) struttura dati che puo' essere usata come collezione

    Usa un file di testo in formato JSON per leggere e scrivere i dati. Non inventarti il codice per leggere e scrivere sul file: java ha gia' la libreria pronta.

    Il main del programma, quando parte, deve chiedere chi sei, per la scelta del correntista, quindi la lista di operazioni
    - saldo
    - saldo e lista operazioni
    - prelievo e saldo
    - deposito e saldo
    - uscita

    Devi tracciare tutte (ma proprio tutte, anche quelle che non cambiano il saldo) le operazioni e non cancellarle mai. Devi poter ricostrire il saldo corrente dal saldo iniziale e rifacendo tutte le opetazioni.

    La banca sara' un Singletone: hai un'unica banca. Quando istanzi l'oggetto banca, questa deve automaticamente leggere dal file il suo stato. Avrai un'operazione 'chiusuraBanca' che devi chiamare prima dell'uscita del programma per salvare lo stato della banca su file. Al momento parti con un solo correntista, tu, cablato nel file. Poi prevederai la possibilita' di aggiungere altri correntisti, altre banche, il trasferimento di un correntista da una banca all'altra, o solo un po' di soldi, oppure tutto quello che ti vierra' in mente.

    E' piu' arzigogolato del tuo codice, MA bisogna avere obbiettivi piu' ambiziosi per migliorare.

    La PRIMA cosa da imparare nella programmazione ad oggetti e' quello di avere chiaro gli oggetti coinvolti e le loro interazioni, che cosa deve saper fare ogni oggetto, e come deve interagire con gli altri.

    Questa parte e' indipendente da Java, ma funziona con qualunque linguaggio di programmazione, anche uno inventato al momento. Solo dopo c'e' il linguaggio. Quindi, PRIMA< con carta e matita, ti fai il diagramma degli oggetti e ti fai un'idea di come devono funzionare, SOLO DOPO ti metti a scrivere codice. Il codice E' SEMPRE ALLA FINE!!!!!!

    Ad esempio, studiati i design pattern.

    Faccio un esempio:
    - il correntista fa un prelievo; NON E' l'oggetto correntista che accede direttamente al conto corrente e al saldo, ma accede all' oggetto conto corrente della banca a cui chiede i soldi. L 'oggetto conto corrente decrementa l' importo dal saldo e ritorna i soldi al correntista.

    Ad esempio, supponi che l'operazione di prelievo venga tassata: e' l'oggetto conto corrente che toglie i soldi della tassa all'importo richiesto e ritorna al correntista un importo inferiore.

    Poi ci saranno infiniti altri dettagli, scelte progettuali da fare. Non esiste un'unica soluzione. Parti con la piu' semplice.

    Per capire se e' stata fatta la scelta giusta, a questo livello e' ragionevolmente (per modo di dire) semplice: se stai scrivendo troppo codice e il codice e' troppo incasinato, hai sbagliato.

    In un metodo: 10 righe di codice sono tante, 20 sono troppe.

    E' ovvio che non e' assoluto, ma e' un punto di partenza per ripensare a quello che stai scrivendo quando inizi a fare strani giri con il codice per implementare qualcosa che nella tua testa doveva essere semplice.
  • Re: Esercizio con classi

    Se funziona, è solo una questione estetica, quindi vedi tu.

    L'unico appunto è che nei conti corrente si usa il BigDecimal, non il double, altrimenti il rischio di fare cappellate e perdere centesimi è alto
  • Re: Esercizio con classi

    @Weierstrass, errato: si deve usare il "Currency"

    https://docs.oracle.com/javase/8/docs/api/java/util/Currency.html

    NON E' una questione di decimali: i decimali DEVONO ESSERE QUELLI (4 per l'euro, poi arrontodati a 2) e si devono usare le regole di arrotondamento definite dalla legge.

    Si, lo so, il 99.99999% dei programmatori usa il BigDecimal (o peggio, il double). Questo dimostra solo che il 99.99999% sapra' anche programmare, ma non sa nulla di leggi finanziarie.
  • Re: Esercizio con classi

    AngeloI ha scritto:


    Dopo un po' di ripasso ed esercizietti vari, come "allenamento" ho deciso di implementare un programmino che servisse a gestire in maniera molto base un conto corrente.
    Ti sono già state dette delle cose ma ne aggiungo/ribadisco alcune io.

    1) Applica di più la programmazione "ad oggetti". Significa che devi rappresentare meglio le entità con apposite classi, incapsulando bene dati e comportamenti.

    2) Studia le "collezioni". Gli array per certe cose vanno bene fino ad un certo punto (a meno di voler fare logiche più o meno similari a quelle nelle collezioni).

    3) Il buon migliorabile ti ha detto di usare file JSON. . Sì certo è una possibilità ma nella Java Standard Edition non c'è già nel framework una API per JSON (se migliorabile intendeva la Java API for JSON Processing, JSR-353 o 374, va tirata dentro nel progetto una libreria di implementazione di questa API). Ma a quel punto sarebbe anche meglio usare la Gson o la Jackson (altre librerie più sofisticate per JSON).
    Meglio magari se usi dei file di testo con una struttura che "inventi" tu. Cosa che comunque è sicuramente "formativa" per te.

    4) La logica: metto tutti i movimenti inizialmente a "", poi testo per !="" ha poco senso. Quando crei un array così new String[10] i suoi elementi hanno GIÀ un valore di default: null. Che nel tuo caso è sicuramente più che appropriato.

    Posso sicuramente aggiungere altro appena riesco a vedere meglio il tuo codice.
  • Re: Esercizio con classi

    migliorabile ha scritto:


    errato: si deve usare il "Currency"

    https://docs.oracle.com/javase/8/docs/api/java/util/Currency.html
    Currency rappresenta solo la valuta in sé (codice iso, simbolo, n. decimali, ecc...). Non un valore in una valuta.

    Generalmente (per fare bene) si può usare BigDecimal e Currency per rappresentare il valore.
  • Re: Esercizio con classi

    migliorabile ha scritto:


    @Weierstrass, errato: si deve usare il "Currency"

    https://docs.oracle.com/javase/8/docs/api/java/util/Currency.html

    NON E' una questione di decimali: i decimali DEVONO ESSERE QUELLI (4 per l'euro, poi arrontodati a 2) e si devono usare le regole di arrotondamento definite dalla legge.

    Si, lo so, il 99.99999% dei programmatori usa il BigDecimal (o peggio, il double). Questo dimostra solo che il 99.99999% sapra' anche programmare, ma non sa nulla di leggi finanziarie.
    Ma mi spieghi che senso hanno queste risposte? Che fai con Currency da sola? A cosa la abbini, a un int? Un BigInteger? un BigDecimal?
    Ha chiesto interventi costruttivi perché sta imparando e costruttivamente gli ho indicato di stare attento agli arrotondamenti dei double, non confondergli le idee con roba riservata a chi lavora in banca...
  • Re: Esercizio con classi

    Giusto, "Currency" era una libreria Java 7 o 8 che implementava il concetto di "soldi/valuta". Pensavo l'avessero integrata come con java.util.concurrency . Ne avevo implementata una per conto mio che si chiammava proprio "Currency".

    I vecchi riferimenti sono questi

    http://jscience.org
    http://jscience.org/api/org/jscience/economics/money/package-summary.html#package_description


    Ora c'e' questo:

    https://jcp.org/en/jsr/detail?id=35
    https://github.com/JodaOrg/joda-mone
    https://javamoney.github.io
  • Re: Esercizio con classi

    Beh, non resta che mettermi sotto ed applicare nel miglior modo possibile i (molti) consigli che mi avete mandato.
    Grazie a tutti per i suggerimenti. Quando avrò fatto una versione successiva di questo esercizio, lo riposterò per chiedervi ulteriori pareri
Devi accedere o registrarti per scrivere nel forum
8 risposte