Aiuto programmazione OO

Salve sono nuovo del forum e un programmatore ‘newbie’ (si dice cosi?).
Sto tentando di scrivere un preprocessore grafico per un soft di calcolo
(tipo CAD). Ho necessità di gestire alcuni elementi del tipo

Nodi
Aste
Piastre

Ho creato le corrispondenti classi.

La classe nodo accetta come parametri
id - il numero univoco
x - coordinata x
y - coordinata y
z - coordinata z
vincolo - codice numerico

La classe asta accetta come parametri:
id - il numero univoco
ni - nodo iniziale
nf - nodo finale
tipo - codice alfanumerico
sezione - intero
materiale - intero

Ad esempio l’asta n. 15 ha come estremi il nodo 1 e il nodo 20.

Secondo voi la classe Asta deve ereditare da Nodo oppure è inutile?

Non conosco il dominio del problema, ma da quello che dici tu non vedo
relazione tra un nodo e un asta.

A naso, se un asta è composta da due nodi, asta e nodo sono oggetti del
dominio distinti.
Non essendoci relazione di “parentela” nel mondo reale, non userei
l’ereditarietà.

Simone F.

Architect

2010/1/15 Alessandro B. [email protected]

Il 15 gennaio 2010 10.59, Alessandro B. [email protected] ha
scritto:

Salve sono nuovo del forum e un programmatore ‘newbie’ (si dice cosi?).
ciao e benvenuto!
Secondo voi la classe Asta deve ereditare da Nodo oppure è inutile?
in genere, quello che più conta non sono i dati, ma il comportamento;
che accettino parametri simili non è importante, la domanda è cosa
fanno esattamente queste classi; se vedi che hanno molti metodi in
comune, puoi optare per l’ereditarietà - ma magari, se l’asta non è un
caso particolare di nodo (e mi sembra di capire che non lo è), la cosa
più giusta è che entrambi ereditino da un capostipite comune.

pietro

Simone F. wrote:

Non conosco il dominio del problema, ma da quello che dici tu non vedo
relazione tra un nodo e un asta.

A naso, se un asta � composta da due nodi, asta e nodo sono oggetti del
dominio distinti.
Non essendoci relazione di “parentela” nel mondo reale, non userei
l’ereditariet�.

OK grazie.

Pietro G. wrote:

Il 15 gennaio 2010 10.59, Alessandro B. [email protected] ha
scritto:

Salve sono nuovo del forum e un programmatore ‘newbie’ (si dice cosi?).
ciao e benvenuto!
Secondo voi la classe Asta deve ereditare da Nodo oppure � inutile?
in genere, quello che pi� conta non sono i dati, ma il comportamento;
che accettino parametri simili non � importante, la domanda � cosa
fanno esattamente queste classi; se vedi che hanno molti metodi in
comune, puoi optare per l’ereditariet� - ma magari, se l’asta non � un
caso particolare di nodo (e mi sembra di capire che non lo �), la cosa
pi� giusta � che entrambi ereditino da un capostipite comune.

pietro

Chiarissimo. grazie

Il 06 febbraio 2010 15.55, Alessandro B. [email protected]
ha scritto:

Ho creato due classi:

[…]

Nella classe Asta mi serve un metodo che restituisce i tutti i dati dei
nodi di estrmità: come faccio a “linkare” le due classi?

Ciao,

Non ho capito, cosa intendi per linkare? Non puoi fare una cosa tipo
questa?

class Asta
def dati_dei_nodi_di_estremita
[@ni.id, @ni.x, @ni.y, …, @nf.id, @nf.x, @nf.y, …]
end
end

O, meglio ancora:

class Nodo
def dati_del_nodo
{:x => @x, :y => @y, :z => @z, …}
end
end

class Asta
def dati_dei_nodi_di_estremita
[@ni.dati_del_nodo, @nf.dati_del_nodo]
end
end

Spiega meglio cosa intendi.

Ah, una supplica: i byte costano poco, usali! non chiamare le
variabili l1, l2, lb, zi, non ci si capisce niente! Se usi nomi più
lunghi, risparmi sui commenti.

pietro

Grazie Pietro per la rapidità .

Spiega meglio cosa intendi.

Creo 100 nodi, da 1 a 100.
Creo 60 aste.
Ad esempio l’asta 23 ha come nodi il numero 44 e il numero 87.

nodo44 = Nodo(0,0,0,…)
nodo87 = Nodo(100,0,0, …)

asta23 = Asta(44,87,…)

Vorrei scrivere qualcosa del tipo:

puts “Il nodo iniziale dell’asta 23 ha coordinate”
puts asta23.nodo_iniziale.x
puts asta23.nodo_iniziale.y
puts asta23.nodo_iniziale.z

Ah, una supplica: i byte costano poco, usali! non chiamare le
variabili l1, l2, lb, zi, non ci si capisce niente! Se usi nomi pi�
lunghi, risparmi sui commenti.

Si vero, ma:

  1. quando avrò a che fare con delle formule un conto è scrivere

q = (l1^2 + l2^2)*sqrt(…)

un’altro è scrivere

carico_per_metro_lineare_asta = (lunghezza_1^2 +
lunghezza_2^2)*sqrt(…

:slight_smile:

  1. I commenti li uso perchè voglio utilizzare rdoc, … :slight_smile:

Pietro G. wrote:

Il 15 gennaio 2010 10.59, Alessandro B. [email protected] ha
scritto:

Salve sono nuovo del forum e un programmatore ‘newbie’ (si dice cosi?).
ciao e benvenuto!
Secondo voi la classe Asta deve ereditare da Nodo oppure � inutile?
in genere, quello che pi� conta non sono i dati, ma il comportamento;
che accettino parametri simili non � importante, la domanda � cosa
fanno esattamente queste classi; se vedi che hanno molti metodi in
comune, puoi optare per l’ereditariet� - ma magari, se l’asta non � un
caso particolare di nodo (e mi sembra di capire che non lo �), la cosa
pi� giusta � che entrambi ereditino da un capostipite comune.

pietro

Ancora dubbi…

Ho creato due classi:

La classe Nodo crea un oggetto nodo.

Ogni istanza della classe e’ identificata da un numero univoco (id)

La classe necessita di 5 parametri + 1 opzionale: id, x, y, z,

vincolo, [costante elastica]
class Nodo

Numero identificativo del nodo

attr_accessor :id

Coordinata x

attr_accessor :x

Coordinata y

attr_accessor :y

Coordinata z

attr_accessor :z

Codice di vincolo. E’ costituito da tre strighe

che si riferiscono alle tre componenti di movimento del nodo

(nell’ordine: traslazione lungo x, lungo y e rotazione attorno z).

0 = movimento consentito 48

1 = movimento impedito 49

C = movimento limitato da un vincolo cedevole 67

attr_accessor :sx
attr_accessor :sy
attr_accessor :rz

costante elastica del vincolo alla traslazione lungo x

attr_accessor :csx

costante elastica del vincolo alla traslazione lungo y

attr_accessor :csy

costante elastica del vincolo alla traslazione lungo z

attr_accessor :csz

costante elastica del vincolo alla rotazione attorno x

attr_accessor :crx

costante elastica del vincolo alla rotazione attorno y

attr_accessor :cry

costante elastica del vincolo alla rotazione attorno z

attr_accessor :crz

numero totale di nodi creati

@@numero_nodi = 0

Inizializzazione della classe

def
initialize(id,x,y,z,sx,sy,sz,rx,ry,rz,csx=0,csy=0,csz=0,crx=0,cry=0,crz=0)
@id = id
@x = x
@y = y
@z = z
@sx = sx
@sy = sy
@sz = sz
@rx = rx
@ry = ry
@rz = rz

# Per i gradi di libertà per i quali si è usato C come codice di
# vincolo, bisogna fornire anche la costante elastica di vincoli
# cedevoli (kN/m per vincoli allo spostamento kNm per vincoli alla 

rotazione)

@csx = csx
@csy = csy
@csz = csz
@crx = crx
@cry = cry
@crz = crz

@@numero_nodi +=1

end

Il metodo to_s stampa una tabella con i dati caratteristici

del nodo.

def to_s
puts “\n”
puts “NODO n. #{@id}”
puts “=”*30
puts “x= #{@x} [#{$umlungh}]”
puts “y= #{@y} [#{$umlungh}]”
puts “z= #{@z} [#{$umlungh}]”
puts “sx= #{@sx}”
puts “sy= #{@sy}”
puts “sz= #{@sz}”
puts “rx= #{@rx}”
puts “ry= #{@ry}”
puts “rz= #{@rz}”
if not nodo.csx==0
puts “csx= #{@csx} [#{$umcedevol}]”
end
if not nodo.csy==0
puts “csy= #{@csy} [#{$umcedevol}]”
end
if not nodo.csz==0
puts “csz= #{@csz} [#{$umcedevol}]”
end
if not nodo.crx==0
puts “crx= #{@crx} [#{$umcedevolrot}]”
end
if not nodo.cry==0
puts “cry= #{@cry} [#{$umcedevolrot}]”
end
if not nodo.crz==0
puts “crz= #{@crz} [#{$umcedevolrot}]”
end
end
end

La classe Asta crea una asta tra due nodi.

I parametri accettati sono:

id = numero identificativo asta [intero]

ni = nodo iniziale [intero]

nf = nodo finale [intero]

nmat = indice del materiale dell’asta [intero]

nsez = indice della sezione dell’asta [intero]

tipo = codice indentificativo del tipo di asta:

T = trave alla DeSaint Venant

TR = trave alla De saint Venant con tratti rigidi

W = trave di fonazione alla Winkler

WR = trave di fondazione alla Winkler con tratti rigidi

*opz = lista di 2 o 4 valori numerici che possono essere:

se tipo = TR oppure WR:

l1 = lunghezza tratto rigido al nodo ni

l2 = lunghezza tratto rigido al nodo nf

se tipo = W oppure WR:

lb = larghezza sottobase [cm]

kw = costante sottofondo [N/cm3]

class Asta
attr_accessor :id, :ni, :nf, :nmat, :nsez, :tipo, :l1, :l2, :lb, :kw
@@numero_aste = 0
def initialize(id,ni,nf,nmat,nsez,tipo,*opz)
@id=id
@ni=ni
@nf=nf
@nmat=nmat
@nsez=nsez
@tipo=tipo
if @tipo == “TR”
@l1=opz[0]
@l2=opz[1]
elsif @tipo == “W”
@lb=opz[0]
@kw=opz[1]
elsif @tipo == “WR”
@l1=opz[0]
@l2=opz[1]
@lb=opz[2]
@kw=opz[3]
end
@@numero_aste +=1
end

Il metodo to_s/em> stampa una tabella con i dati caratteristici

dell’asta.

def to_s
puts “\n”
#puts “=”*40
puts “ASTA n. #{@id}”
puts “=”*50
puts “nodo i= #{@ni}”
puts “nodo f= #{@nf}”
puts “materiale n° #{@nmat}”
puts “sezione n° #{@nsez}”
puts “tipo= #{@tipo}”
if @tipo == ‘TR’ or @tipo == “WR”
puts “lunghezza tratto rigido al nodo #{@ni} #{@l1}
[#{$umlungh}]”
puts “lunghezza tratto rigido al nodo #{@nf} #{@l2}
[#{$umlungh}]”
end
if @tipo == “W” or @tipo == “WR”
puts “Larghezza sottobase lb= #{@lb} [#{$umlungh}]”
puts “Costante di sottoforndo kw= #{@kw} [#{$umdens}]”
end
end

Il metodo lungh calcolca la lunghezza dell’asta.

def lungh
xi = @ni.xi
yi = @ni.yi
zi = @ni.zi
l = Math.sqrt((xf-xi)^2+(yf-yi)^2+(zf-zi)^2)
return l
end
end

Nella classe Asta mi serve un metodo che restituisce i tutti i dati dei
nodi di estrmità : come faccio a “linkare” le due classi?

Grazie Andrea.

  • wrappare le componenti x,y,z di posizione e costanti elastiche.
    Qualcosa di questo tipo:

class Vector

def initialize(x,y,z)
@x, @y, @z = x, y,z
end

end

puoi ereditare da Vector nel caso (probabile) in cui ci sia della logica
associata alla posizione/costante elastica.

Cosa vuol dire “wrappare”?

  • quel @@numero_nodi mi piace pochino :slight_smile: perch� lo usi? Non vedo niente
    nella classe Nodo stessa che ne faccia uso. Se la necessit� del counter
    � dovuta a qualche altra classe � il caso che sia la classe che ne ha
    bisogno ad assumersi la
    responsabilit�.

OK

  • nel costruttore della classe asta: tipo e opzioni nascondono in realt�
    classi, non passare stringhe in giro e comparare ma crea una classe per

ogni tipo. Qui la logica di dominio non la conosco ma un’ idea potrebbe
essere qualcosa del genere:

class Trave
#logica per le travi
end

class DeSaint < Trave
#logica per le travi desaint
end

class Winkler < Trave
#logica per le travi winkler
end

e via cos�. Se la logica per le travi rigide � comune per tutte le travi
puoi anche creare un modulo (esempio)

module TraveRigida
#logica per le travi rigide
end

ed includerlo dove serve:

class WinklerRigida < Trave
include TraveRigida

end

Mi sembra decisamente più razionale :slight_smile:

  • non passare in giro l’ID per identificare i nodi: se non ti serve per
    altre esigenze (tipo persistenza in DB) eliminalo, e passa in giro
    direttamente le istanze.

Dato che dovrò gestire centinaia di nodi e di aste (ma non di sezioni e
materiali) pensavo ad un DB. Non so, cosa consigli?

  • stessa cosa per nmat e nsez: fai delle classi e passa in giro le
    istanze, tipo:

class Materiale
#logica comune a tutti i materiali
end

class MaterialeFoo < Materiale
#logica
end

in questo caso dipende per� da quanti materiali hai e da quanto varia la
logica fra uno e l’altro: se sono tanti e tutti uguali allora usa solo
una classe materiale, se ne hai logiche diverse per materiali diversi
fai classi diverse. Stesso discorso per le sezioni

Scusa la (ennesima) domanda da ‘negozio degli orrori’:::
Come faccio a passare una istanza al posto dell’id?

  • il costruttore di asta diventerebbe

def TraveCippaLippa < Trave

#usa nomi significativi per le variabili… li paghi te i
caratteri? :slight_smile:
def initialize(nodo_iniziale, nodo_finale, materiale, sezione)

@nodo_iniziale = nodo_iniziale
@nodo_finale   = nodo_finale
@materiale     = materiale
@sezione       = sezione
# niente @@numero_aste += 1, stesso discorso che per i nodi

end

Già detto a Pietro.

Grazie davvero per gli utilissimi consigli.

On Sat, 2010-02-06 at 19:59 +0100, Alessandro B. wrote:

end

puoi ereditare da Vector nel caso (probabile) in cui ci sia della logica
associata alla posizione/costante elastica.

Cosa vuol dire “wrappare”?

Giusta osservazione :slight_smile: avrei dovuto spiegarmi nel dettaglio.
Nel tuo caso hai come parametri nel costruttore, fra gli altri, x y e z.
Insieme rappresentano la posizione del nodo. Se, invece di passarli come
valori numerici che, in linea teorica, potrebbero anche essere
interpretati come non collegati l’uno all’ altro costruisci una classe
(la suddetta Vettore) che li contiene è come se tu dicessi “ok, questi
valori x y e z non sono semplici valori numerici ma, insieme,
costituiscono una entità vettore che rappresenta un punto nello spazio”.
Nel caso ti servisse, ad esempio, di avere il vettore in un sistema di
coordinate polari potresti aggiungere un metodo nella classe vettore che
si occupa della conversione.

classi, non passare stringhe in giro e comparare ma crea una classe per

  • non passare in giro l’ID per identificare i nodi: se non ti serve per
    altre esigenze (tipo persistenza in DB) eliminalo, e passa in giro
    direttamente le istanze.

Dato che dovrò gestire centinaia di nodi e di aste (ma non di sezioni e
materiali) pensavo ad un DB. Non so, cosa consigli?

Salvare in DB ha senso ma non creare cose che non ti servono prima del
tempo. Se e quando deciderai di persistere il tuo grafo di oggetti in un
database allora potrai pensare ad aggiungere id e cose del genere.

end

in questo caso dipende per� da quanti materiali hai e da quanto varia la
logica fra uno e l’altro: se sono tanti e tutti uguali allora usa solo
una classe materiale, se ne hai logiche diverse per materiali diversi
fai classi diverse. Stesso discorso per le sezioni

Scusa la (ennesima) domanda da ‘negozio degli orrori’:::
Come faccio a passare una istanza al posto dell’id?

esempio:

start = Nodo.new
end = Nodo.new
materiale = Materiale.new
sezione = Sezione.new
trave = Trave.new(start, end, materiale, sezione)

puoi passare come parametro un oggetto esattamente nello stesso modo in
cui passi in giro un fixnum o una stringa. In ruby tutto (o quasi :)) è
un oggetto, dal punto di vista delle “variabili” non fa differenza se si
tratta di un numero (istanza della classe Fixnum) o dell’ istanza di una
classe da te creata.

@nodo_finale   = nodo_finale


Andrea D.

Ciao Alessandro,

alcune note sparse:

  • wrappare le componenti x,y,z di posizione e costanti elastiche.
    Qualcosa di questo tipo:

class Vector

def initialize(x,y,z)
@x, @y, @z = x, y,z
end

end

puoi ereditare da Vector nel caso (probabile) in cui ci sia della logica
associata alla posizione/costante elastica.

  • quel @@numero_nodi mi piace pochino :slight_smile: perchè lo usi? Non vedo niente
    nella classe Nodo stessa che ne faccia uso. Se la necessità del counter
    è dovuta a qualche altra classe è il caso che sia la classe che ne ha
    bisogno ad assumersi la
    responsabilità.
  • nel costruttore della classe asta: tipo e opzioni nascondono in realtà
    classi, non passare stringhe in giro e comparare ma crea una classe per
    ogni tipo. Qui la logica di dominio non la conosco ma un’ idea potrebbe
    essere qualcosa del genere:

class Trave
#logica per le travi
end

class DeSaint < Trave
#logica per le travi desaint
end

class Winkler < Trave
#logica per le travi winkler
end

e via così. Se la logica per le travi rigide è comune per tutte le travi
puoi anche creare un modulo (esempio)

module TraveRigida
#logica per le travi rigide
end

ed includerlo dove serve:

class WinklerRigida < Trave
include TraveRigida

end

  • non passare in giro l’ID per identificare i nodi: se non ti serve per
    altre esigenze (tipo persistenza in DB) eliminalo, e passa in giro
    direttamente le istanze.

  • stessa cosa per nmat e nsez: fai delle classi e passa in giro le
    istanze, tipo:

class Materiale
#logica comune a tutti i materiali
end

class MaterialeFoo < Materiale
#logica
end

in questo caso dipende però da quanti materiali hai e da quanto varia la
logica fra uno e l’altro: se sono tanti e tutti uguali allora usa solo
una classe materiale, se ne hai logiche diverse per materiali diversi
fai classi diverse. Stesso discorso per le sezioni

  • il costruttore di asta diventerebbe

def TraveCippaLippa < Trave

#usa nomi significativi per le variabili… li paghi te i
caratteri? :slight_smile:
def initialize(nodo_iniziale, nodo_finale, materiale, sezione)

@nodo_iniziale = nodo_iniziale
@nodo_finale   = nodo_finale
@materiale     = materiale
@sezione       = sezione
# niente @@numero_aste += 1, stesso discorso che per i nodi

end

HTH!


Andrea D.

Il 06 febbraio 2010 19.50, Alessandro B. [email protected]
ha scritto:

un’altro è scrivere

carico_per_metro_lineare_asta = (lunghezza_1^2 +
lunghezza_2^2)*sqrt(…

:slight_smile:

  1. I commenti li uso perchè voglio utilizzare rdoc, … :slight_smile:

Immagino che i calcoli vorrai concentrarli in (relativamente) pochi
metodi; lì (e solo lì) puoi eventualmente usare variabili:

def primo_calcolo_astruso
l = una_lunghezza_con_un_nome_comprensibile
q = una_quantita_di_cui_non_so_nulla
c = non_voglio_nemmeno_saperlo

(l * q + c) ** 3 - …
end

Non ti sto suggerendo di eliminare tutti i commenti, solo quelli
dannosi.

Considera che, se tutto va bene, quasi nessuna delle righe di codice
che scrivi sopravviverà : man mano che aggiungi, togli, riorganizzi,
riscriverai tutto più e più volte.

Mantenere attuali i commenti raddoppierà il lavoro; se una volta ti
dimenticherai di aggiornare un commento, il codice diventerà un
labirinto.

Se i commenti servono a spiegare cosa fa il codice, vuol dire che il
codice non è chiaro.

I commenti dovrebbero spiegare perché il codice fa quello che fa; ad
esempio, nel caso del tuo progetto, i commenti sono indispensabili, ma
dovrebbero riguardare in massima parte i concetti trattati dal codice,
cioè Asta, Nodo, traslazione, rotazione etc.

pietro