1 de JUNIO de 2005 Es un factor externo de calidad del software

Anuncio
INGENIERÍA DEL SOFTWARE. 4º ING. INFORMÁTICA (UPV/EHU)
1 de JUNIO de 2005
NOMBRE:
GRUPO:
1) (0,25 ptos.) (Tiempo: 5 minutos) ¿Qué es robustez del software?
Es un factor externo de calidad del software, que indica la capacidad del
software para re accionar apropiadamente ante condiciones anormales,
esto es, ante condiciones no contempladas en la especificación.
2) (0,25 ptos.) (Tiempo estimado: 5 minutos) ¿Qué son los servicios Web?
Un servicio Web es lógica del negocio accesible mediante protocolos
estándar en Internet: habitualmente HTTP para el transporte, SOAP
(basado en XML) para la invocación, WSDL para la definición del servicio.
3) (1 pto.) (Tiempo estimado: 20 minutos) Dado el caso de uso PEDIR BILLETE, y el
siguiente caso de prueba
Entrada: nombre “Kepa Sola”
Condiciones de entrada: Existen 25 billetes libres y 5 ocupados en la tabla
BILLETES(NUMERO,NOMBRE,ESTADO)
Salida: dar número de billete x (x>0), quedando 24 billetes libres, 6 ocupados y el billete
con el número x está ocupado en la BD.
Escribir un componente de prueba para poder probar al menos el caso de prueba anterior,
teniendo en cuenta que disponemos de las siguientes clases. NOTA: Si se usa alguna otra
clase auxiliar, describirla usando UML.
PedirBillete
-logNeg : GestorBilletes
«interface»
GestorBilletes
+getBillete(in nombre : string) : int
«subsystem»
java.rmi
ServidorGestorBilletesBD
+getBillete(in nombre : string) : int
«subsystem»
java.sql
SOLUCIÓN:
public class ComponentePruebaEntrSistema {
GestorBilletes ln;
OperacionesParaPruebas lp = new OperacionesParaPruebas();
public static void main(String[] args) {
try{
ln = java.rmi.Naming.lookup("rmi://MAQ:PUERTO/gestorBilletes");
lp.inicializarBilletes(25,5); // 25 libres, 5 ocupados
int i = ln.getBillete("Kepa Sola"); // Llamar a lógica negocio
int quedanLibres = lp.getNumLibres();
int quedanOcupados = lp.getNumOcupados();
boolean esCorrecto = lp.existeBillete(i,"Kepa Sola","OCUPADO");
if ((i>0)&&(quedanLibres==24)&&
(quedanOcupados==6)&&(esCorrecto))
System.out.println("CP1 correcto");
else System.out.println("CP1 incorrecto");
} catch (Exception e) {e.printStackTrace();}
}
donde se usa la clase:
4)
(3
ptos.)
(Tiempo
estimado:
60
minutos)
La
siguiente
clase
(ConsultarAutobuses.java) implementa el caso de uso CONSULTAR HORARIOS
AUTOBUSES, que permite escoger una ciudad de salida, otra de llegada y consultar los
horarios de autobuses entre ellas.
Los puntos de salida, llegada y horarios se obtienen de las siguientes tablas:
Se pide :
1) (1,5 ptos.) Proponer una solución que utilice una arquitectura física en 3 niveles.
Se deben mostrar las clases necesarias en notación UML, junto con la signatura de
los métodos de las mismas. No hay que implementar completamente la solución,
pero sí mostrar el uso de Java RMI, Java JDBC e interfaces Java. Esto se puede
representar por medio de dependencias “usa”, generalizaciones e implementación
de interfaces en UML. También se puede implementar algún método de alguna clase
si eso ayuda a explicar mejor la solución.
Suponiendo que la solución propuesta está completamente implementada, hay que
analizar ahora qué habría que cambiar para satisfacer una serie de nuevos
requisitos. Para cada nuevo requisito hay que indicar claramente si se cree que
afecta al nivel de presentación, lógica del negocio o nivel de datos, explicar los
cambios que habría que hacer en el diseño y/o implementación e indicar si la
solución era extensible ante cada cambio.
2) (0,5 ptos.) Se desea cambiar de SGBD: MySQL en vez de Access.
3) (0,5 ptos.) Queremos que al escoger una ciudad de salida en la lista desplegable
correspondiente, sólo aparezcan en la otra aquellas ciudades a las que llega un
autobús desde dicha ciudad. Lo mismo cuando se escoja una ciudad de llegada.
4) (0,5 ptos.) Se desea que aparezcan todas las ciudades y pueblos en los que para el
autobús y desde los que se puede coger el autobús.
El código es el siguiente:
package autobuses;
import ...
public class ConsultarAutobuses extends JFrame
{ private JPanel jPanel1 = new JPanel();
private BorderLayout borderLayout1 = new BorderLayout();
private JLabel jLabel1 = new JLabel();
private DefaultComboBoxModel model1 = new DefaultComboBoxModel();
private JComboBox jComboBox1 = new JComboBox(model1);
private JLabel jLabel2 = new JLabel();
private DefaultComboBoxModel model2 = new DefaultComboBoxModel();
private JComboBox jComboBox2 = new JComboBox(model2);
private JButton jButton1 = new JButton();
private DefaultListModel model3 = new DefaultListModel();
private JList jList1 = new JList(model3);
private Statement st;
private ResultSet rs;
private static Connection conexion;
public ConsultarAutobuses()
{ try
{ jbInit(); } catch(Exception e)
{ e.printStackTrace();} }
private void jbInit() throws Exception
{ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
conexion = DriverManager.getConnection("jdbc:odbc:bdautobus");
st = conexion.createStatement();
this.getContentPane().setLayout(borderLayout1);
this.setSize(new Dimension(400, 300));
this.setTitle("Consultar Horarios Autobuses");
jLabel1.setText("Salida:");
jLabel2.setText("Llegada:");
jButton1.setText("Consultar Horarios");
jButton1.addActionListener(new ActionListener()
{ public void actionPerformed(ActionEvent e)
{jButton1_actionPerformed(e); }});
jPanel1.add(jLabel1, null);
jPanel1.add(jComboBox1, null);
jPanel1.add(jLabel2, null);
jPanel1.add(jComboBox2, null);
rellenarModel(model1,obtenerElementos("SELECT SALIDA FROM AUTOBUS"));
rellenarModel(model2,obtenerElementos("SELECT LLEGADA FROM AUTOBUS"));
this.getContentPane().add(jPanel1, BorderLayout.NORTH);
this.getContentPane().add(jButton1, BorderLayout.SOUTH);
this.getContentPane().add(jList1, BorderLayout.CENTER);
}
public void rellenarModel(DefaultComboBoxModel d,Vector elems)
{ d.removeAllElements();
for (int i=0;i<elems.size();i++) { d.addElement(elems.elementAt(i)); } }
public void rellenarModel(DefaultListModel d,Vector elems)
{ d.removeAllElements();
for (int i=0;i<elems.size();i++) { d.addElement(elems.elementAt(i)); } }
public Vector obtenerElementos(String sql)
{ Vector v = new Vector();
try{ rs = st.executeQuery(sql);
while (rs.next()) {v.addElement(rs.getString(1)); } }
catch(Exception e) {System.out.println("Error: "+e.toString());}
return v; }
private void jButton1_actionPerformed(ActionEvent e)
{ rellenarModel(model3,
obtenerElementos("SELECT horario "+
"FROM horarios INNER JOIN Autobus ON horarios.codigo=Autobus.codigo "+
"WHERE SALIDA='"+jComboBox1.getSelectedItem()+
"' AND LLEGADA='"+jComboBox2.getSelectedItem()+"'"));
}}
SOLUCIÓN 1):
NOTA: en la solución no se esperaba tanto detalles como los que se dan aquí. Eso sí, los
nombres de las clases e interfaces y los métodos de la interfaz con la lógica del negocio sí. En
particular, los nombres de los atributos de las clases no son necesarios.
SOLUCIÓN 2):
En la lógica del negocio hay que cargar un driver de MySQL (por ejemplo el
org.gjt.mm.mysql.Driver) y la base de datos de autobuses.
Esto se puede hacer, por ejemplo, en el constructor de ServidorGestorAutobuses
Class.forName("org.gjt.mm.mysql.Driver");
conexion=DriverManager.getConnection("jdbc:mysql://localhost/BDAutobuses");
Hay que cambiar el nivel de datos: instalar el SGBD MySQL y crear la BD
BDAutobuses.
El nivel de presentación no se ve afectado.
Podría ser que la lógica del negocio no tuviera que cambiarse si el driver del
SGBD y el string de conexión se hubieran leído de un fichero de configuración. En
este caso, sí podríamos haber considerado la solución como muy extensible, ya
que un cambio que en principio afecta sólo al nivel de datos (cambio en el SGBD
y la BD), se ha realizado sólo modificando dicho nivel de datos (y además
instalando los drivers de MySQL en los servidores de aplicaciones)
SOLUCIÓN 3):
En la lógica del negocio hay que añadir algún método:
getLlegadas(salida: String): Vector
getSalidas(llegada:String): Vector
que se implementarían devolviendo los resultados a estas preguntas,
respectivamente:
SELECT LLEGADA FROM AUTOBUS WHERE SALIDA = %salida%
SELECT SALIDA FROM AUTOBUS WHERE LLEGADA = %llegada%
El nivel de presentación debe cambiarse para que al escoger una ciudad en una
lista desplegable (JComboBox) se rellene la otra lista desplegable:
rellenarModel(modX,logNeg.getLlegadas(jCombX.getSelectedItem().toString())
El nivel de datos no se ve afectado.
En principio, se puede considerar que la solución era extensible ya que un
cambio que afecta al nivel de presentación (qué debe aparecer en una lista
desplegable de la interfaz gráfica) afecta al nivel de presentación, y al nivel de
lógica del negocio porque esa operación no estaba considerada (en cierta manera
es un nuevo requisito).
SOLUCIÓN 4):
En este caso no se indica claramente qué es lo que debe aparecer en la interfaz
gráfica (en la presentación) por lo que la siguiente solución sería válida:
Añadir una tupla en la tabla AUTOBUS por cada posible trayecto, y tantas por
cada horario. Por ejemplo: <x,Lasarte,Andoain> y <x,8.40> y <x,9.40>
Esta solución no implica un cambio en la aplicación. Sólo hay que añadir las
tuplas correspondientes en la base de datos.
Nota: En realidad, seguramente no será una solución correcta porque hemos
puesto un código de autobús por cada trayecto, y, claro está, no sale un nuevo
autobús desde cada parada a todas las siguientes.
Si se quisiera que en la interfaz gráfica aparecieran todas las paradas junto con
sus horarios, entonces se necesitarían cambios en todos los niveles: en la BD
habría que añadir datos sobre las paradas y sus horarios. En la lógica del negocio
habría que añadir métodos para obtener esos datos. Y en la presentación habría
que decidir en qué parte de la interfaz gráfica se muestra dicha información y
hacerlo.
5) (2 ptos.) (Tiempo estimado: 40 minutos)
Se desea realizar una aplicación informática para gestionar las competiciones de
natación. Una competición está compuesta por Nadadores y Pruebas, donde un
nadador que compite en una prueba obtiene un resultado. El resultado además del
tiempo obtenido (min, seg, cent) tiene dos asociaciones que refe rencian al nadador
que lo ha realizado, y la prueba obtenida. En el diagrama UML se reflejan todas las
clases y asociaciones que existen en el modelo.
Utilizando los algoritmos y predicados JGL, se pide implementar los siguientes
métodos en la clase Competicion:
1- Visualizar ordenados por tiempo, los nadadores que han participado en una
prueba pru.
void nadadoresPrueba(String pru)
2- Visualizar los nadadores que hayan competido en más de n pruebas.
void nadadoresMasDeNPruebas(int n)
3- Visualizar los nadadores que han realizado un tiempo inferior a m minutos, s
segundos y c centésimas en la prueba pru
void nadadoresTiempoMenor(String pru, int m, int s, int c)
Solución 1)
void nadadoresPrueba(String pru){
Prueba p=(Prueba)pruebas.get(pru);
BinaryPredicate bp=new BinaryComposePredicate(new LessNumber(),
new ObtenCentesimas(),new ObtenCentesimas());
Sorting.sort(p.resultados,bp);
Applying.forEach(p.resultados,new PrintResultadoNadador());
}
Solución 2)
void nadadoresMasDeNPruebas(int n){
UnaryPredicate up=new BindSecondPredicate(new GreaterNumber(),
new Integer(n));
UnaryPredicate up2=new UnaryComposePredicate(up,new ObtenerPruebas());
Container c=Filtering.select(nadadores,up2);
Applying.forEach(c,new PrintNadador());
}
Solución 3)
void nadadoresTiempoMenor(String pru, int m, int s, int c){
double t=m*6000+s*100+c;
Prueba p=(Prueba)pruebas.get(pru);
UnaryPredicate up=new BindSecondPredicate(new LessNumber(),new Double(t));
UnaryPredicate up2=new UnaryComposePredicate(up,new ObtenCentesimas());
Container cont=Filtering.select(p.resultados,up2);
Applying.forEach(cont,new PrintResultadoNadador());
}
Funciones auxiliares
public class ObtenCentesimas implements UnaryFunction {
public Object execute(Object o) {
Resultado res=(Resultado)o;
return new Double(res.min*6000+res.seg*100+res.cent);
}
}
public class PrintResultadoNadador implements UnaryFunction {
public Object execute(Object o) {
Resultado res=(Resultado)o;
System.out.println(res.nad.nombre+" "+res.nad.club+"
:"+res.min+"'"+res.seg+"''"+res.cent);
return null;
}
}
public class PrintNadador implements UnaryFunction {
public Object execute(Object o) {
Pair p=(Pair)o;
Nadador nad=(Nadador)p.second;
System.out.println(nad.nombre+" "+nad.club);
return null;
}
}
public class Obtene rPruebas implements UnaryFunction {
public Object execute(Object o) {
Pair p=(Pair)o;
Nadador nad=(Nadador)p.second;
return(new Integer(nad.resultados.size()));
}
}
6) (2 ptos.) (Tiempo estimado: 30 minutos)
Se desea realizar una aplicación para la evaluación de expresiones aritméticas.
Una expresión aritmética es:
a) Un número, o bien
b) Un operador binario que opera sobre dos expresiones aritméticas.
El único requisito del sistema es:
1- Los operadores para los que se defi ne el sistema son inicialmente la Suma,
Resta, Producto y División, pero no se descarta que en el futuro se pueda
extender a otras operaciones como Exponencial o Logaritmo. Realiza la
aplicación teniendo en cuenta este requisito.
Se pide:
1. Realizar un modelo que permita recoger expresiones aritméticas
2. Implementa las clases del modelo
3. Realiza un programa que devuelva el resultado de 4+5 * 6-2 (Es decir, 36).
SOLUCIÓN:
public class Compuesta implements Expresion
{
Operador op;
Expresion exp1, exp2;
public Compuesta(Operador o, Expresion e1, Expresion e2)
{
op=o;
exp1=e1;
exp2=e2;
}
public float getValor() {
return op.evalua(exp1.getValor(),exp2.getValor());
}
}
public interface Operador
{
public float evalua(float x, float y);
}
public class Suma implements Operador
{
public float evalua(float p1, float p2){
return p1+p2;
}
}
Programa principal:
public static void main(String[] args)
{
Expresion n4=new Numero(4);
Expresion n5=new Numero(5);
Expresion n6=new Numero(6);
Expresion n2=new Numero(2);
Expresion s1=new Compuesta(new Suma(),n4,n5);
Expresion s2=new Compuesta(new Resta(),n6,n2);
Expresion s3=new Compuesta(new Producto(),s1,s2);
System.out.println(s3.getValor());
}
7) (1 .5 ptos.) (Tiempo estimado: 20 minutos)
Queremos realizar un componente que nos sirva como Monedero Virtual a la hora
de realizar compras en Internet. El monedero cuando se crea se inicializa con una
cantidad q, y las operaciones que están disponibles son:
1- void añadirCantidad(int q). Se incrementa el monedero con una cantidad q.
2- boolean realizarCompra(String articulo, int precio). Devuelve cierto si hay
saldo suficiente, falso en caso contrario.
3- Container articulosComprados(). Devuelve en un contenedor los artículos
que se han comprado así como su precio de compra.
Se pide:
1. Realizar un componente que implemente este Monedero Virtual.
NOTA: Las interfaces
javax.ejb.EJBHomeObject
extienden
de
las
clases:
javax.ejb.EJBObject
SOLUCIÓN:
Interface EJB
public interface MonederoEJB extends EJBObject
{
void añadirCantidad(int q) throws RemoteException;
boolean realizarCompra(String articulo, int precio) throws RemoteException;
Contain er articulosComprador() throws RemoteException;
}
Interface Home
public interface MonederoEJBHome extends EJBHome
{
MonederoEJB create(int q) throws RemoteException, CreateException;
}
Componente
public class MonederoEJBBean implements SessionBean
{
SList articulos=new SList();
int cantidad;
private SessionContext context;
public void ejbCreate(int q)
{
cantidad=q;
}
public void añadirCantidad(int q)
y
{
cantidad=cantidad+q;
}
public boolean realizarCompra(String articulo, int precio)
{
if (cantidad>precio) {
articulos.add(new Articulo(articulo, precio));
cantidad=cantidad-precio;
return true;
}
else
return false;
}
public Container articulosComprador()
{
return articulos;
}
}
Descargar