Вы находитесь на странице: 1из 25

Construccin de un Programa MVC

Este ejemplo muestra la construccin de un programa MVC para Android usando tcnicas de Ingeniera de
Software.

1. Planteamiento del Problema


Realizar un programa que recibe el nombre de 2 personas y devuelve un saludo que incluya a las dos.

2. Diagrama de Casos de Uso

3. Caso de Uso Saludo


El usuario introduce el nombre de 2 personas y devuelve una saludo dirigido a los dos.

3.1. Flujo Bsico


1. El usuario ingresa a la aplicacin.
2. El usuario introduce el valor para los dos nombres y hace clic en el botn Saludar.
3. El sistema muestra el saludo Saludos a nombre 1 y a nombre 2, donde nombre 1 y nombre 2 son los
valores introducidos en el punto anterior.

3.2 Flujos alternos


1. Si el usuario hace clic en Saludar y nombre 1 est en blanco, se presenta el mensaje de error Falta
el nombre 1..
2. Si el usuario hace clic en Saludar, nombre 1 est capturado y nombre 2 est en blanco, se presenta
el mensaje de error Falta el nombre 2..

4. Anlisis de Robustez
Se identifican las capas que lleva el programa, as como los datos que intercambian, sin preocuparnos de la
forma de implementacin. Las capas que en este caso identificamos son:

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
Objetos boundary (lmite). Son los objetos con que se comunican los actores. Pueden ser ventanas,
pantallas, cuadros de dilogo, mens, etc.
Objetos controller (controlador). Realizan las operaciones del negocio. Es decir, hacen la parte
importante de la aplicacin.
Las reglas que sigue este modelo son simples:
Los actores solo pueden comunicarse con objetos boundary.
Los objetos boundary solo pueden comunicarse con actores y controller.
Los objetos controller solo pueden comunicarse con objetos boundary.

4.1. Diagrama de Secuencia

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
4.2. Diagrama de Clases

5. Diseo
Para implementar el anlisis de robustez, hay varias opciones: MVC y MVP.

5.1. Modelo MVC


Model (modelo). Los datos del dominio de la aplicacin.
View (vista). Se modela en base a los objetos boundary del anlisis de robustez. Tiene asociado un
modelo. Los cambios del modelo se notifican automticamente a la vista para que los muestre. Los
cambios en la interfaz grfica se reflejan directamente en el modelo.
Controller (controlador). Se modela de los objetos controller del anlisis de robustez. Realiza las
operaciones del dominio de la aplicacin, que son solicitadas por la vista. Tambin puede realizar
cambios al modelo.

5.2. Modelo MVP con Vista Pasiva


En Android, las vistas normalmente se modelan en un archivo XML, conocido como layout, y son pasivas.
Es decir que no llevan instrucciones en su interior; solamente la distribucin de componentes grficos. Para
este caso, hay una variacin del patrn MVC que resulta ms adecuada: MVP con vista pasiva.
Model (Modelo). Los datos del dominio de la aplicacin.
View. Es pasiva. No tiene ninguna informacin sobre la estructura del modelo.
Presenter (presentador). Reemplaza al controlador. Interacta directamente con la vista y el modelo.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
Escucha los eventos de la vista. Realiza las operaciones del dominio de la aplicacin.

5.3. Consideraciones
1. Los nombres de las vistas en Android no pueden llevar maysculas, por lo cual, el nombre de la vista
se cambia a view_saludo.
2. La clase controladora es ahora un presentador.
3. Las app de Android necesitan una Activity para controlar el ciclo de vida y mostrar la vista. Esta clase
tambin juega el papel de presentador. Su nombre es ActivitySaludo.
4. Android recomienda que los mensajes deben tomarse de un archivo. Esto facilita el mantenimiento
del programa e internacionalizarlo.

5.4. Diseo de pruebas


Hay que disear como se prueba la aplicacin. En algunos casos esta seccin se incluye en los contratos para
sealar los criterios de aceptacin de la aplicacin. Se indican los

Id de Prueba Nombre1 Nombre 2 Salida Errores


P1 Falta el nombre 1.
P2 Pedro Falta el nombre 2.
P3 Ana Falta el nombre 1.
P4 Pedro Ana Saludos a Pedro y a Ana.
P5 Cuca Pepe Saludos a Cuca y a Pepe.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
5.5. Diagrama de Secuencia

5.6. Diagrama de Clases

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
6. Deployment
Todas las aplicaciones android estn formadas por los archivos classes.dex, AndroidManifest.xml,
resources.arsc y la capeta res.

Los archivos Java se compilan y con ellos se forma el archivo classes.dex.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
La carpeta res contiene distintos tipos de archivos. Un ejemplo son los conos del lanzador de la aplicacin,
que se llaman ic_launcher.png y se colocan en una carpeta diferente para ser usados segn la resolucin del
mvil que los usa. Hay algunos archivos xml que coordinan distintos aspectos de la aplicacin.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
7. Implementacin
Crea un nuevo proyecto de Android Studio siguiendo las instrucciones de D201android. Solo toma en cuenta
las siguientes consideraciones.
El Application name es D202mvc.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
En Activity Name introduce ActivitySaludo y en Layout Name teclea view_saludo.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
Para crear las clases que faltan, haz clic derecho en el package, que en este caso es net.ramptors.d202mvc y
selecciona el men contextual New > Java Class.

Aparece el cuadro de dilogo Create New Class. En el campo Name se introduce el nombre de la nueva
clase, que en este caso es Nombres.

Tambin hay que crear la clase Nombres.


El contenido de las clases debe coincidir con los diagramas de secuencia y clases para el diseo.

8. Creacin de Test para Clases Independientes de Android


Del diseo, el modelo y el controlador no dependen de la plataforma Android. Se pueden probar de una
forma sencilla.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
Selecciona la pestaa Build Variants que se localiza en el margen inferior derecho de la ventana.

Cambia el valor de Test Artifact a Unit Tests.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
En la vista Project abre la carpeta app/src/test/java. Aparece el paquete de la aplicacin, que en este caso es
net.ramptors.d202mvc. Crea una clase que se llame NombresTest. La cual sirve para probar el
funcionamiento de la clase Nombres. Nota que la clase de prueba se llama igual que la original, pero termina
con Test.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
La clase creada aparece.

Cuando hayas introducido el cdigo de las clases Nombres y NombresTest, que aparece ms adelante,
puedes ejecutar la prueba, haciendo clic derecho en la clase NombresTest.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
Aparece el panel de ejecucin. Si todo funciona bien, aparece una barra totalmente en verde. Si hay alguna
falla, Android Studio indica el nombre de la clase, mtodo y nmero de lnea donde ocurri el fallo, y una
descripcin del problema.

9. Creacin de Test para la Aplicacin Android


Para probar una activity, hay que cambiar el Test Artifact de la pestaa Build Variant. Su nuevo valor es
Android Instrumentation Test.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
Crea la clase de prueba ActivitySaludoTest dentro del paquete que aparece al abrir la carpeta
app/src/androidTest/java.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
Para ejecutar el test, primero hay que lanzar un emulador o BlueStacks y esperar a que el emulador levante.
Haz clic derecho y ejecuta la prueba.

Selecciona el dispositivo para ejecutar la prueba.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
Android Studio se prepara para ejecutar la prueba.

Aparece el panel de ejecucin de test.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
El telfono ejecuta las pruebas.

Los resultados aparecen en el panel de pruebas.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
10. Cdigo.

AndroidManifest.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <manifest
3 package="net.ramptors.d202mvc"
4 xmlns:android="http://schemas.android.com/apk/res/android">
5 <application
6 android:allowBackup="true"
7 android:icon="@mipmap/ic_launcher"
8 android:label="@string/app_name"
9 android:supportsRtl="true"
10 android:theme="@style/AppTheme">
11 <activity android:name=".ActivitySaludo">
12 <intent-filter>
13 <action android:name="android.intent.action.MAIN"/>
14 <category android:name="android.intent.category.LAUNCHER"/>
15 </intent-filter>
16 </activity>
17 </application>
18 </manifest>

styles.xml
1 <resources>
2 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
3 <item name="colorPrimary">@color/colorPrimary</item>
4 <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
5 <item name="colorAccent">@color/colorAccent</item>

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
6 </style>
7 </resources>

colors.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3 <color name="colorPrimary">#3F51B5</color>
4 <color name="colorPrimaryDark">#303F9F</color>
5 <color name="colorAccent">#FF4081</color>
6 </resources>

strings.xml
1 <resources>
2 <string name="app_name">D202mvc</string>
3 <string name="nombre1">Nombre 1</string>
4 <string name="nombre2">Nombre 2</string>
5 <string name="saludar">Saludar</string>
6 <string name="hint_saludo">Aqu aparece el saludo para Nombre 1 y Nombre 2.</string>
7 <string name="formato_del_saludo">Saludos a %1$s y a %2$s.</string>
8 <string name="falta_el_nombre_1">Falta el nombre 1.</string>
9 <string name="falta_el_nombre_2">Falta el nombre 2.</string>
10 <string name="edit_text_no_encontrado">EditText no encontrado en el archivo xml.</string>
11 </resources>

ActivitySaludo.java
1 package net.ramptors.d202mvc;
2
3 import android.os.Bundle;
4 import android.support.annotation.IdRes;
5 import android.support.annotation.NonNull;
6 import android.support.annotation.StringRes;
7 import android.support.v7.app.AppCompatActivity;
8 import android.view.View;
9 import android.widget.Button;
10 import android.widget.EditText;
11 import android.widget.TextView;
12
13 public class ActivitySaludo extends AppCompatActivity {
14 private static final String VIEW_NO_ENCONTRADA =
15 "View no encontrada en el archivo xml.";
16 @Override protected void onCreate(Bundle savedInstanceState) {
17 super.onCreate(savedInstanceState);
18 setContentView(R.layout.view_saludo);
19 final Button btnSaludar = getBtnSaludar();
20 btnSaludar.setOnClickListener(new View.OnClickListener() {
21 @Override public void onClick(View v) {
22 clicEnSaludar();
23 }
24 });
25 }
26 @NonNull Button getBtnSaludar() {
27 return (Button) busca(R.id.btnSaludar);
28 }

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
29 @NonNull TextView getLblSalida() {
30 return (TextView) busca(R.id.lblSalida);
31 }
32 @NonNull View busca(@IdRes int idView) {
33 final View view = findViewById(idView);
34 if (view == null) {
35 throw new NullPointerException(VIEW_NO_ENCONTRADA);
36 } else {
37 return view;
38 }
39 }
40 public void clicEnSaludar() {
41 try {
42 final String nombre1 = recuperaTexto(R.id.txtNombre1);
43 final String nombre2 = recuperaTexto(R.id.txtNombre2);
44 final Nombres modelo = new Nombres(nombre1, nombre2);
45 final String saludo = saluda(modelo);
46 muestraRespuesta(saludo);
47 } catch (ExceptionFaltaNombre exceptionFaltaNombre) {
48 muestraRespuesta(exceptionFaltaNombre.getLocalizedMessage());
49 }
50 }
51 @NonNull private String saluda(@NonNull Nombres modelo)
52 throws ExceptionFaltaNombre {
53 valida(modelo.getNombre1(), R.string.falta_el_nombre_1);
54 valida(modelo.getNombre2(), R.string.falta_el_nombre_2);
55 return construyeSaludo(modelo);
56 }
57 @NonNull private String recuperaTexto(@IdRes int idEditText) {
58 final EditText editText = (EditText) busca(idEditText);
59 return editText.getText().toString();
60 }
61 private void valida(@NonNull String nombre, @StringRes int idMensajeDeError)
62 throws ExceptionFaltaNombre {
63 if (nombre.isEmpty()) {
64 throw new ExceptionFaltaNombre(getString(idMensajeDeError));
65 }
66 }
67 @NonNull private String construyeSaludo(@NonNull Nombres modelo) {
68 return getString(R.string.formato_del_saludo, modelo.getNombre1(),
69 modelo.getNombre2());
70 }
71 private void muestraRespuesta(@NonNull String respuesta) {
72 final TextView lblSalida = getLblSalida();
73 lblSalida.setText(respuesta);
74 }
75 }

Nombres.java
1 package net.ramptors.d202mvc;
2
3 public class Nombres {
4 private final String nombre1;
5 private final String nombre2;
6 public Nombres(String nombre1, String nombre2) {
7 this.nombre1 = nombre1;
8 this.nombre2 = nombre2;

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
9 }
10 public String getNombre1() {
11 return nombre1;
12 }
13 public String getNombre2() {
14 return nombre2;
15 }
16 }

ExceptionFaltaNombre.java
1 package net.ramptors.d202mvc;
2
3 import android.support.annotation.NonNull;
4
5 public class ExceptionFaltaNombre extends Exception {
6 public ExceptionFaltaNombre(@NonNull String detailMessage) {
7 super(detailMessage);
8 }
9 }

view_saludo.xml

1 <?xml version="1.0" encoding="utf-8"?>


2 <!-- ViewGroup que muestra sus componentes un en seguida del otro. Como tiene el
3 atributo android:orientation="vertical", los despliega de arriba hacia abajo.
4 -->
5 <LinearLayout
6 xmlns:android="http://schemas.android.com/apk/res/android"
7 xmlns:tools="http://schemas.android.com/tools"
8 android:layout_width="match_parent"
9 android:layout_height="match_parent"
10 android:orientation="vertical"
11 android:paddingBottom="@dimen/activity_vertical_margin"
12 android:paddingLeft="@dimen/activity_horizontal_margin"
13 android:paddingRight="@dimen/activity_horizontal_margin"
14 android:paddingTop="@dimen/activity_vertical_margin"
15 tools:context="net.ramptors.d202mvc.ActivitySaludo">
16 <!-- Cuadro para editar texto. El atributo android:hint="@string/nombre1"
17 define un sello de agua que se muestra cuando no hay datos capturados y
18 le indica al usuario que valor debe introducir. -->
19 <EditText
20 android:id="@+id/txtNombre1"

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
21 android:layout_width="match_parent"
22 android:layout_height="wrap_content"
23 android:hint="@string/nombre1"/>
24 <EditText
25 android:id="@+id/txtNombre2"
26 android:layout_width="match_parent"
27 android:layout_height="wrap_content"
28 android:hint="@string/nombre2"/>
29 <Button
30 android:id="@+id/btnSaludar"
31 android:layout_width="match_parent"
32 android:layout_height="wrap_content"
33 android:text="@string/saludar"/>
34 <TextView
35 android:id="@+id/lblSalida"
36 android:layout_width="wrap_content"
37 android:layout_height="wrap_content"
38 android:hint="@string/hint_saludo"/>
39 </LinearLayout>

dimens.xml (values)
1 <resources>
2 <dimen name="activity_horizontal_margin">16dp</dimen>
3 <dimen name="activity_vertical_margin">16dp</dimen>
4 </resources>

dimens.xml (values-w820dp)
1 <resources>
2 <dimen name="activity_horizontal_margin">64dp</dimen>
3 </resources>

NombresTest.java
1 package net.ramptors.d202mvc;
2
3 import org.junit.Test;
4
5 import static org.junit.Assert.assertEquals;
6
7 /** Clase que sirve para probar la clase Test. */
8 public class NombresTest {
9 /**
10 * Mtodo que implementa una prueba. Debe llevar la anotacin org.junit.Test
11 * y ser public. Puede lanzar excepciones.
12 */
13 @Test public void testNombres() {
14 final Nombres nombres = new Nombres("Pp", "Qk");
15 // Revisa que el objeto devuelva los valores recibidos en el constructor.
16 assertEquals("Pp", nombres.getNombre1());
17 assertEquals("Qk", nombres.getNombre2());
18 }
19 }

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
ActivitySaludoTest.java
1 package net.ramptors.d202mvc;
2
3 import android.support.annotation.IdRes;
4 import android.test.ActivityInstrumentationTestCase2;
5 import android.test.TouchUtils;
6 import android.widget.EditText;
7 import android.widget.TextView;
8
9 public class ActivitySaludoTest
10 extends ActivityInstrumentationTestCase2<ActivitySaludo> {
11 private static final String FALTA_EL_NOMBRE_1 = "Falta el nombre 1.";
12 private static final String FALTA_EL_NOMBRE_2 = "Falta el nombre 2.";
13 public ActivitySaludoTest() {
14 super(ActivitySaludo.class);
15 }
16 @Override protected void setUp() throws Exception {
17 super.setUp();
18 getActivity();
19 }
20 public void testP1() {
21 TouchUtils.clickView(this, getActivity().getBtnSaludar());
22 assertEquals(FALTA_EL_NOMBRE_1, getTextoSalida());
23 }
24 public void testP2() {
25 asignaTexto(R.id.txtNombre1, "Pedro");
26 TouchUtils.clickView(this, getActivity().getBtnSaludar());
27 assertEquals(FALTA_EL_NOMBRE_2, getTextoSalida());
28 }
29 public void testP3() {
30 asignaTexto(R.id.txtNombre2, "Ana");
31 TouchUtils.clickView(this, getActivity().getBtnSaludar());
32 assertEquals(FALTA_EL_NOMBRE_1, getTextoSalida());
33 }
34 public void testP4() throws Exception {
35 asignaTexto(R.id.txtNombre1, "Pedro");
36 asignaTexto(R.id.txtNombre2, "Ana");
37 TouchUtils.clickView(this, getActivity().getBtnSaludar());
38 assertEquals("Saludos a Pedro y a Ana.", getTextoSalida());
39 }
40 public void testP5() throws Exception {
41 asignaTexto(R.id.txtNombre2, "Pepe");
42 asignaTexto(R.id.txtNombre1, "Cuca");
43 TouchUtils.clickView(this, getActivity().getBtnSaludar());
44 assertEquals("Saludos a Cuca y a Pepe.", getTextoSalida());
45 }
46 private void asignaTexto(@IdRes int idEditText, String s) {
47 final EditText editText = (EditText) getActivity().busca(idEditText);
48 getInstrumentation().runOnMainSync(new Runnable() {
49 @Override
50 public void run() {
51 editText.requestFocus();
52 }
53 });
54 getInstrumentation().waitForIdleSync();
55 getInstrumentation().sendStringSync(s);
56 getInstrumentation().waitForIdleSync();
57 }

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.
58 private String getTextoSalida() {
59 final TextView lblSalida = getActivity().getLblSalida();
60 return lblSalida.getText().toString();
61 }
62 }

11. Bibliografa
http://www.codeproject.com/Articles/8058/Applying-Robustness-Analysis-on-the-Model-View-Con
Applying Robustness Analysis on the ModelViewController (MVC) Architecture in ASP.NET
Framework, using UML.
http://www.codeproject.com/Articles/42830/Model-View-Controller-Model-View-Presenter-and-Mod
Model View Controller, Model View Presenter, and Model View ViewModel Design Patterns.
http://martinfowler.com/eaaDev/PassiveScreen.html Passive View.
https://www.imaginanet.com/blog/patron-mvp.html Patrn MVP
http://www.uml-diagrams.org/
http://bouml.fr/doc/
http://d.android.com

Android es propiedad de Google, al igual que Android Studio. Este ltimo est basado en IntelliJIDEA, que es propiedad de
JetBrains.

Esta obra est licenciada bajo la Licencia Creative Commons Atribucin 4.0 Internacional. Para ver una copia de esta
licencia, visita http://creativecommons.org/licenses/by/4.0/.

Вам также может понравиться