Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
[OT DEV] Sviluppare applicazioni GUI-independent
View unanswered posts
View posts from last 24 hours
View posts from last 7 days

 
Reply to topic    Gentoo Forums Forum Index Forum italiano (Italian) Forum di discussione italiano
View previous topic :: View next topic  
Author Message
assente
Guru
Guru


Joined: 12 Apr 2004
Posts: 570
Location: Torino, italia, New Europe

PostPosted: Mon Oct 10, 2005 1:25 pm    Post subject: [OT DEV] Sviluppare applicazioni GUI-independent Reply with quote

Ho fatto questo script in ruby di prova che a seconda dell'argomento si avvia con la GUI o con la console.
La struttura è banale classe principale List e poi le interfacceGtkList e ConsoleList che lo estendono e si occupano dell'interfaccia I/O, adesso mi viene ho 2 dubbi,

1. secondo voi il controllo della validità dei dati deve essere fatta anche a livello interfaccia?
(Per esempio chi deve segnalare se un'entry è null? l'interfaccia o l'oggetto centrale? Se si fa a livello GUI non si rischia di inconsistenza rispetto le altre GUI che ci possono essere?)

2. nel caso il dato non sia valido è meglio che l'oggetto principale lanci un'eccezione o che implementi un metodo d'errore a livello superiore?
(Se si usano le eccezioni non si rischia di implementare i messaggi di errore nelle interfacce - e quindi duplicali? - )

Chiedete pure se non mi sono spiegato bene o se avete implementazioni più efficaci da proporre.

Code:

 #!/usr/bin/ruby
=begin
 == esempio.rb ==
 Una semplice implementazione di oggetti indipendenti dall'interfaccia grafica/console
 oOo. http://assente.altervista.org .oOo
=end

# Oggetto principale GUI-indipendent
class List
    def initialize()
        @a=[]
    end
    def add(value)
        # vari controlli sull'input
        if value==""
            error("Valore nullo")
        elsif value=~/[a-zA-Z]/
            error("Le lettere non sono ammesse")
        elsif value=~/[0-9]/
            @a << value
            notify("'#{value}' inserito")
        end
    end
    # yield viene sostituito con quello che passiamo a livello superiore,
    # puts oppure @display.text+=, fantastico, no?
    def show_all
        @a.each { |value| yield value}
    end
end

class ConsoleList < List
    def initialize
        super
        puts "Console mode"
        while true
            puts "1: Aggiungi 2: Visualizza 3: Esci"
            # toglie \n dall'input da terminale
            choice=gets.strip
            case (choice)
                when "1" then add
                when "2" then show_all
                when "3" then exit
            else
                error("Scelta non valida")               
            end       
        end
    end
    def add
        puts "Inserisci: "
        # manda al metodo List#add vedi su
        super(gets.strip)
    end
    # Richiamato da List
    def error(text)
        puts "!! #{text} !!"
    end
    def notify(text)
        puts ">> #{text}"   
    end
    def show_all
        super{|v| puts "|#{v}|"}
    end
end

class GtkList < List
    require 'gtk2'
    def initialize
        super
        puts "GUI mode"
       
        Gtk.init   
       
        #Inizializzo i widget
        @window=Gtk::Window.new
        @container=Gtk::VBox.new
        @entry=Gtk::Entry.new
        @display=Gtk::Label.new
        @button=Gtk::Button.new("Inserisci")
       
        #Assegno gli eventi
        @button.signal_connect("clicked"){add}
        @entry.signal_connect("activate"){add}
        @window.signal_connect("destroy"){exit}
       
        #impacchetto
        @container.add(@display).add(@entry).add(@display).add(@display).add(@button)
        @window.add(@container)
       
        @window.show_all
       
        Gtk.main
    end
    def add
        puts "Inserisci: "
        super(@entry.text)
        @entry.text=""
    end
    def error(text)
        # Con più spazio estendetevi Gtk::Alert :-)
        Gtk::Window.new.add(Gtk::Label.new("#{text}")).show_all
    end
    def notify(text)
        # Non necessario
        #Gtk::Window.new.add(Gtk::Label.new("#{text}")).show_all
        show_all
    end
    def show_all
        @display.text=""
        super{|v| @display.text+=v+" "}
    end
end

# Inizia qui
case(ARGV[0])
    when nil:     ConsoleList.new
    when "--gtk": GtkList.new
end

_________________
Blog
E8400, 4850, P5q
Back to top
View user's profile Send private message
federico
Advocate
Advocate


Joined: 18 Feb 2003
Posts: 3272
Location: Italy, Milano

PostPosted: Mon Oct 10, 2005 3:37 pm    Post subject: Reply with quote

Il controllo della consistenza dei dati la farei a livello di programma e non di interfaccia, esattamente per il motivo che hai citato tu.
Per gli errori, farei sollevare un eccezione, che l'interfaccia grafica puo' poi gestire nel modo che piu' le aggrada
_________________
Sideralis www.sideralis.org
Pic http://blackman.amicofigo.com/gallery
Arduino http://www.arduino.cc
Chi aveva potuto aveva spaccato
2000 pezzi buttati là
Molti saluti,qualche domanda
Semplice come musica punk
Back to top
View user's profile Send private message
assente
Guru
Guru


Joined: 12 Apr 2004
Posts: 570
Location: Torino, italia, New Europe

PostPosted: Mon Oct 10, 2005 8:03 pm    Post subject: Reply with quote

ok grazie per la delucidazione, anche se mi piaceva l'idea di implementare error("x non valido") a livello di programma, pensandoci bene c'è anche un'altro contro: con l'eccezione non viene eseguito il codice sottostante ed è giusto che sia così
_________________
Blog
E8400, 4850, P5q
Back to top
View user's profile Send private message
federico
Advocate
Advocate


Joined: 18 Feb 2003
Posts: 3272
Location: Italy, Milano

PostPosted: Mon Oct 10, 2005 9:44 pm    Post subject: Reply with quote

Potresti fornire anche qualche specifica per la gestione delle eccezioni, per esempio se tu facessi un substrato software per la gestione di mp3 e due persone decidessero di fare un'interfaccia, magari all'evento mp3 non trovato tu sollevi un eccezione, e la prima gui che ne so, decide di scaricare l'mp3 non trovato, e la seconda decide di proporti canzoni dello stesso autore, bhop... ahhah che esempio pessimo :)
_________________
Sideralis www.sideralis.org
Pic http://blackman.amicofigo.com/gallery
Arduino http://www.arduino.cc
Chi aveva potuto aveva spaccato
2000 pezzi buttati là
Molti saluti,qualche domanda
Semplice come musica punk
Back to top
View user's profile Send private message
assente
Guru
Guru


Joined: 12 Apr 2004
Posts: 570
Location: Torino, italia, New Europe

PostPosted: Mon Oct 10, 2005 10:37 pm    Post subject: Reply with quote

sì.. però mi piaceva anche l'idea di avere tutte le stringhe da tradurre in un solo posto.. e quindi lanciare l'eccezione con la stringa d'errore insieme.

lancia EccezioneStandard.new("Mp3 non trovato")

lancia Mp3NotFound.new

Nel primo caso ho la comodità di stabilire la stringa d'errore dal programma, nel secondo la devo poi definire nella GUI; il primo mi sembra meno ridondante, ma il secondo è più flessibile, metti che una gui voglia fare citare widget specifici.

Comunque sia, se l'errore comporta anche delle modifiche nella GUI bisognerebbe comunque specificare eccezione->azione e distinguerle dall'errore delle stringhe sarebbe troppo grezzo, no?

Quindi i livelli sono: Interfaccia con stringhe d'errore che intercetta le eccezioni e programma che lancia eccezioni
_________________
Blog
E8400, 4850, P5q
Back to top
View user's profile Send private message
riquito
Tux's lil' helper
Tux's lil' helper


Joined: 17 Jul 2002
Posts: 93

PostPosted: Tue Oct 11, 2005 9:27 am    Post subject: Reply with quote

assente wrote:

Quindi i livelli sono: Interfaccia con stringhe d'errore che intercetta le eccezioni e programma che lancia eccezioni


Non esattamente. Direi piuttosto
"programma che lancia eccezioni" e "interfaccia che intercetta le eccezioni e mostra le relative stringhe di errore"

la parte di computazione indipendente dalla gui deve generare eccezioni in caso di errore, contenenti informazioni utili.
La gui deve leggere dall'eccezione la stringa che indica il problema riscontrato, ed eventualmente mostrare all'utente la stringa incapsulata nell'eccezione (via shell o via libreria grafica a seconda del tipo di GUI).


Ciao,
Riccardo
_________________
Sideralis Programs
http://www.sideralis.org
Back to top
View user's profile Send private message
assente
Guru
Guru


Joined: 12 Apr 2004
Posts: 570
Location: Torino, italia, New Europe

PostPosted: Tue Oct 11, 2005 3:11 pm    Post subject: Reply with quote

quindi con la stringa d'errore impacchettata nell'eccezione tipo:

Code:

class Controller
   def initialize(word)
      if ["ciao", "tizio", "caio"].include?(word)
         raise ArgumentError, "'#{word}' non ammesso"
      else
         raise "'#{word}' valido"
      end
   end
end

class GuiController < Controller
   def initialize(value)
      begin
      super(value)      
      rescue ArgumentError => e
         puts "!!! "+e
      rescue  => e
         puts ">>> "+e
      end
   end
end

GuiController.new("pinco")
GuiController.new("ciao")
GuiController.new("pallino")


Ma a sto punto sarebbe anche il caso di lanciare un'eccezione se tutto èandato a buon fine? ..e poi decidere a livello gui se è il caso di mostralo?
_________________
Blog
E8400, 4850, P5q
Back to top
View user's profile Send private message
riquito
Tux's lil' helper
Tux's lil' helper


Joined: 17 Jul 2002
Posts: 93

PostPosted: Tue Oct 11, 2005 5:56 pm    Post subject: Reply with quote

assente wrote:
quindi con la stringa d'errore impacchettata nell'eccezione tipo:

Code:

class Controller
   def initialize(word)
      if ["ciao", "tizio", "caio"].include?(word)
         raise ArgumentError, "'#{word}' non ammesso"
      else
         raise "'#{word}' valido"
      end
   end
end

class GuiController < Controller
   def initialize(value)
      begin
      super(value)      
      rescue ArgumentError => e
         puts "!!! "+e
      rescue  => e
         puts ">>> "+e
      end
   end
end

GuiController.new("pinco")
GuiController.new("ciao")
GuiController.new("pallino")


Ma a sto punto sarebbe anche il caso di lanciare un'eccezione se tutto èandato a buon fine? ..e poi decidere a livello gui se è il caso di mostralo?


Non conosco ruby, ma python, e mi sembra di capire che in Controllore tu generi una eccezione con raise anche se il dato e' corretto, giusto? questo e' un uso improprio delle eccezioni: come dice il nome, devono indicare qualcosa di anomalo, e solo quello.

in python farei una cosa del genere, seguendo il tuo codice

Code:

class Controller(object):
    def __init__(self,word):
        if  word in ["ciao", "tizio", "caio"]:
            raise ArgumentError, word+" non ammesso"


class GuiController(Controller):
    def __init__(self,value):
        try:
            super(GuiController,self).__init__(value)
            print ">>>",e
        except ArgumentError,e:
            print e


forse l'esempio snatura le tue intenzioni, ma il controllo della validità di un argomento e' piu' lavoro di una funzione che di una classe, e soprattutto tu, in qualunque caso, "fai creshare" l'inizializzazione della classe Controller: non dovrebbe mai accadere.

Spero di esserti stato utile.

Ciao,
Riccardo
_________________
Sideralis Programs
http://www.sideralis.org
Back to top
View user's profile Send private message
assente
Guru
Guru


Joined: 12 Apr 2004
Posts: 570
Location: Torino, italia, New Europe

PostPosted: Tue Oct 11, 2005 7:25 pm    Post subject: Reply with quote

Python e Ruby non sono molto diversi, sì genero un'eccezione anche se il valore è valido, sono quasi sicuro che non si fa così, però in alcuni casi potrebbe essere utile segnalare/notificare che: "il valore x è stato aggiunto correttamente", come lo faresti senza eccezione? Lo supporresti dalla GUI? visto che non si è fermato prima allora tutto è andato bene?!

Certo lanciare eccezioni da init non va bene, ma era solo per far vedere che partivano dall'oggetto interno.

Per il resto mi sembra tutto molto simile, tranne per il fatto che io ho esteso Controller con GuiController e tu invece lo passi come argomento.
_________________
Blog
E8400, 4850, P5q
Back to top
View user's profile Send private message
riquito
Tux's lil' helper
Tux's lil' helper


Joined: 17 Jul 2002
Posts: 93

PostPosted: Wed Oct 12, 2005 9:36 am    Post subject: Reply with quote

assente wrote:

- in alcuni casi potrebbe essere utile segnalare/notificare che: "il valore x è stato aggiunto correttamente"

non mi vengono in mente casi utili, tranne quando devi _attendere_ che il dato sia stato processato e inserito e ti aspetti un segnale che ti informi (caso di thread o programmazione concorrente)


assente wrote:

- come lo faresti senza eccezione? Lo supporresti dalla GUI? visto che non si è fermato prima allora tutto è andato bene?!


Non lo suppongo dalla GUI perche' e' la chiamata tramite super che va a buon fine, e si, visto che non si e' fermato andra' tutto bene. Questo e' l'approccio con le eccezioni. Se non ti piace, puoi usare uno stile procedurale, e farti ritonare valori utili da una funzione (0,1 - vero,falso o altro), che ti indica esplicitamente se la chiamata e' andata a buon fine oppure no.

assente wrote:

Certo lanciare eccezioni da init non va bene, ma era solo per far vedere che partivano dall'oggetto interno.

ok

assente wrote:

Per il resto mi sembra tutto molto simile, tranne per il fatto che io ho esteso Controller con GuiController e tu invece lo passi come argomento.

Erano poche righe di codice, che ti aspettavi? :)

Ciao,
Riccardo
_________________
Sideralis Programs
http://www.sideralis.org
Back to top
View user's profile Send private message
gutter
Bodhisattva
Bodhisattva


Joined: 13 Mar 2004
Posts: 7162
Location: Aarau, Aargau, Switzerland

PostPosted: Sat Oct 29, 2005 10:17 pm    Post subject: Reply with quote

Moved from Italian to Off Topic.
_________________
Registered as User #281564 and Machines #163761
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Forum italiano (Italian) Forum di discussione italiano All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum