3.3 Desarrollo de la propuesta
3.3.2 Metodología de desarrollo de software
3.3.2.3 Producción
El propósito en la fase de producción es implementar la funcionalidad requerida en el producto aplicando ciclo de desarrollo iterativo e incremental, se realiza la programación iterativa hasta la implementación de las funciones deseadas.
70
Los objetivos clave de esta fase son implementar la funcionalidad priorizada por el cliente al producto, en este caso el registro de dietas por parte del especialista para conocimiento de los usuarios; así también centrarse en la funcionalidad básica crucial implementándolos en el incremento inicial para permitir múltiples ciclos de mejora.
3.3.2.3.1 Codificación 3.3.2.3.1.1 Main Activity
Actividad principal donde inicia la aplicación, se inicia el llamado a la interfaz de la app y la carga del inicio de sesión de usuario.
namespace AppCeres {
[Activity(Label = "Ceres", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity
{
EditText edtUserName; EditText edtPass; Button btnLogin; TextView txvMensaje; string json = string.Empty;
WebService.WebService servicio = new WebService.WebService(); protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
71 edtUserName = FindViewById<EditText>(Resource.Id.edtUserName); edtPass = FindViewById<EditText>(Resource.Id.edtPass); btnLogin = FindViewById<Button>(Resource.Id.btnLogin); txvMensaje = FindViewById<TextView>(Resource.Id.txvMensaje); btnLogin.Click += BtnLogin_Click; }
private void BtnLogin_Click(object sender, System.EventArgs e) {
txvMensaje.Text = Herramientas.ValidarLogin(edtUserName.Text, edtPass.Text); if (txvMensaje.Text.Length != 0) return;
else {
txvMensaje.Text = "Validando usuario..."; btnLogin.Enabled = false;
servicio.ValidarUsuarioAsync(edtUserName.Text, edtPass.Text);
servicio.ValidarUsuarioCompleted += Servicio_ValidarUsuarioCompleted; }
}
private void Servicio_ValidarUsuarioCompleted(object sender, WebService.ValidarUsuarioCompletedEventArgs e) { json = e.Result.ToString(); try { if (json == "[]")
72 {
txvMensaje.Text = "El usuario y/o contraseña no existe"; edtUserName.Text = string.Empty; edtPass.Text = string.Empty; btnLogin.Enabled = true; edtUserName.RequestFocus(); } else {
txvMensaje.Text = "Abriendo sistema...";
Intent intent = new Intent(this, typeof(MenuActivity)); intent.PutExtra("usuario", json);
StartActivity(intent); this.Finish();
} }
catch (System.Exception ex) { txvMensaje.Text = ex.Message; } } } }
73
Para poder usar este código de inicio de sesión, se debe implementar la interfaz donde se ejecutará este proceso, para lo cual se necesita de archivos extensión .xaml, el mismo es un lenguaje de marcado basado en XML desarrollado por Microsoft como la variante de XML de para desarrollar interfaces. A continuación, se muestra el código usado para el diseño de la interfaz de inicio de sesión:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:XamarinCeres" x:Class="XamarinCeres.MainPage"> <ScrollView> <StackLayout Padding="10"> <Image Source="cuenta.png" /> <Label x:Name="lblUsuario" Text="Usuario" Font="18" FontAttributes="Bold" /> <Entry x:Name="txtUsuario" Placeholder="Ingrese su Usuario" Text="1804279345"/> <Label x:Name="lblPass" Text="Contraseña" Font="18" FontAttributes="Bold" /> <Entry x:Name="txtPass"
74 Placeholder="Ingrese su Contraseña" IsPassword="True" Text="123"/> <Button x:Name="btnIngresar" Text="Ingresar" Font="20" HeightRequest="80"/> <Label x:Name="lblMensaje" Font="15" HorizontalTextAlignment="Center" TextColor="Red" /> <ActivityIndicator x:Name="aiEspera" /> </StackLayout> </ScrollView> </ContentPage> 3.3.2.3.1.2 Clase Peso
Agrupa las operaciones en las que involucre cálculos con el peso del usuario. public class Peso
{
public static string excedentePeso = "Ex"; public static string clasificacionPeso = "Cl";
public static string IndiceMasaCorporal(string Altura, string Peso, string Parámetros) {
75 if ((Altura.Length > 1) && (Peso.Length > 1)) {
double alt = Convert.ToInt32(Altura), pes = Convert.ToDouble(Peso); double imc;
alt /= 100;
imc = Math.Round(pes / (alt * alt), 2); double pesoIdeal = pes - imc;
if (Parámetros == "Ex") {
if (imc <= 18.5) return "ICM: -" + imc + " kg."; else return "ICM: +" + imc + " kg.";
}
else if (Parámetros == "Cl") {
if (imc <= 18.5) return "Peso Bajo"; else if (imc <= 25) return "Normal"; else if (imc <= 27) return "Sobrepeso I"; else if (imc <= 30) return "Sobrepeso II"; else if (imc <= 35) return "Obesidad I"; else if (imc <= 40) return "Obesidad II"; else if (imc <= 50) return "Obesidad III"; else if (imc > 50) return "Obesidad IV"; else return "Error";
}
76 }
else return ""; }
}
Permite obtener el índice de masa corporal (excedente de peso) del cliente mediante la fórmula 𝐼𝐶𝑀 = 𝑝𝑒𝑠𝑜(𝑘𝑔) 𝑎𝑙𝑡𝑢𝑟𝑎⁄ 2(𝑚2). El procedimiento puede devolver dos tipos de resultado :
excedente de peso y a que categoría pertenece.
Gráfico 29 Cálculo del índice de masa corporal Fuente: Elaboración propia
Si los datos de altura y peso el resultado no se muestra, además automáticamente muestra la complexión del usuario.
3.3.2.3.1.3 Web Services
El proceso de llamar a las diferentes tablas de la base de datos y poder usar la informa c ió n almacenada en el mismo se realiza dentro del archivo WebServices.asmx. El uso de los Web Services permite la reutilización de funciones de una aplicación en distintas plataformas o lenguajes, es así que de la misma forma que se referencia a otras librerías como Dlls o componentes ActiveX, también se puede referenciar funciones que se están ejecutando en otra computadora o servidor. En este caso es de gran importancia la disponibilidad de procesos almacenados para que nuestra app pueda en cualquier momento conectarse a el servidor y llamar procedimientos o consultas.
77 namespace CeresService { [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {
[WebMethod(MessageName = "ActividadesInsert", Description = "ActividadesInsert")] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
public bool ActividadesInsert(string json) {
return Ejecuciones.SetConsulta("ActividadesInsert", json); }
[WebMethod(MessageName = "ActividadesSelectByID", Description = "ActividadesSelectByID")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string ActividadesSelectByID(string Filtro)
{
return Ejecuciones.GetConsulta("ActividadesSelectByID", Filtro); }
[WebMethod(MessageName = "ActividadesUpdate", Description = "ActividadesUpdate")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public bool ActividadesUpdate(string json)
78 {
return Ejecuciones.SetConsulta("ActividadesUpdate", json); }
[WebMethod(MessageName = "AlimentosInsert", Description = "ActividadesInsert")] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
public bool AlimentosInsert(string json) {
return Ejecuciones.SetConsulta("AlimentosInsert", json); }
[WebMethod(MessageName = "AlimentosSelectByID", Description = "AlimentosSelectByID")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string AlimentosSelectByID(string Filtro)
{
return Ejecuciones.GetConsulta("AlimentosSelectByID", Filtro); }
[WebMethod(MessageName = "AlimentosUpdate", Description = "AlimentosUpdate")] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
public bool AlimentosUpdate(string json) {
return Ejecuciones.SetConsulta("AlimentosUpdate", json); }
[WebMethod(MessageName = "DistribucionCaloricaInsert", Description = "DistribucionCaloricaInsert")]
79 public bool DistribucionCaloricaInsert(string json) {
return Ejecuciones.SetConsulta("DistribucionCaloricaInsert", json); }
[WebMethod(MessageName = "DistribucionCaloricaSelectByID", Description = "DistribucionCaloricaSelectByID")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string DistribucionCaloricaSelectByID(string Filtro)
{
return Ejecuciones.GetConsulta("DistribucionCaloricaSelectByID", Filtro); }
[WebMethod(MessageName = "DistribucionCaloricaUpdate", Description = "DistribucionCaloricaUpdate")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public bool DistribucionCaloricaUpdate(string json)
{
return Ejecuciones.SetConsulta("DistribucionCaloricaUpdate", json); }
[WebMethod(MessageName = "GastoEnergeticoSelectByID", Description = "GastoEnergeticoSelectByID")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string GastoEnergeticoSelectByID(string Filtro)
{
return Ejecuciones.GetConsulta("GastoEnergeticoSelectByID", Filtro); }
80
[WebMethod(MessageName = "GastoEnergiticoInsert", Description = "GastoEnergiticoInsert")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public bool GastoEnergiticoInsert(string json)
{
return Ejecuciones.SetConsulta("GastoEnergiticoInsert", json); }
[WebMethod(MessageName = "HistorialInsert", Description = "Seleccionar historial por ID")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public bool HistorialInsert(string json)
{
return Ejecuciones.SetConsulta("HistorialInsert", json); }
[WebMethod(MessageName = "HistorialSelectByPersona", Description = "Seleccio nar historial por ID")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string HistorialSelectByPersona(int IDPersona)
{
return Ejecuciones.GetConsulta("HistorialSelectByPersona", IDPersona.ToString()); }
[WebMethod(MessageName = "HistorialUpdate", Description = "HistorialUpdate")] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public bool HistorialUpdate(string json)
81
return Ejecuciones.SetConsulta("HistorialUpdate", json); }
[WebMethod(MessageName = "PersonaInsert", Description = "Insertar datos de una nueva Persona")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public bool PersonaInsert(string json)
{
return Ejecuciones.SetConsulta("PersonaInsert", json); }
[WebMethod(MessageName = "PersonasSelectByNombres", Description = "Lista de Personas por Nombre y Apellido")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string PersonasSelectByNombres(string Nombres)
{
return Ejecuciones.GetConsulta("PersonasSelectByNombres", Nombres); }
[WebMethod(MessageName = "PersonaUpdate", Description = "PersonaUpdate")] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public bool PersonaUpdate(string json)
{
return Ejecuciones.SetConsulta("PersonaUpdate", json); }
[WebMethod(MessageName = "RepartoBaseInsert", Description = "RepartoBaseInser t ")] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
82 {
return Ejecuciones.SetConsulta("RepartoBaseInsert", json); }
[WebMethod(MessageName = "RepartoBaseSelectByID", Description = "RepartoBaseSelectByID")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string RepartoBaseSelectByID(string Nombres)
{
return Ejecuciones.GetConsulta("RepartoBaseSelectByID", Nombres); }
[WebMethod(MessageName = "RepartoBaseUpdate", Description = "RepartoBaseUpdate")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public bool RepartoBaseUpdate(string json)
{
return Ejecuciones.SetConsulta("RepartoBaseUpdate", json); }
[WebMethod(MessageName = "RolPersonasSelect", Description = "Rol de personas")] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
public string RolPersonasSelect() {
return Ejecuciones.GetConsulta("RolPersonaSelect"); }
[WebMethod(MessageName = "TaylorSelect", Description = "Tabla Taylor por Nombre")]
83
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string TaylorSelect()
{
return Ejecuciones.GetConsulta("TaylorSelect"); }
[WebMethod(MessageName = "TipoAlimentosSelect", Description = "TipoAlimentosSelect")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string TipoAlimentosSelect()
{
return Ejecuciones.GetConsulta("TipoAlimentosSelect"); }
[WebMethod(MessageName = "TipoAlimentosSelectByNombre", Description = "Lista de TipoAlimentos por Nombre")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string TipoAlimentosSelectByNombre(string Alimento)
{
return Ejecuciones.GetConsulta("TipoAlimentosSelectByNombre", Alimento); }
[WebMethod(MessageName = "TipoPersonaSelect", Description = "Tipos de Personas para consumo de valores analiticos")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string TipoPersonaSelect()
{
84 }
[WebMethod(MessageName = "UsuarioValidate", Description = "Comprobar login de usuario y traer datos")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public string UsuarioValidate(string UserName, string password)
{
return Ejecuciones.GetConsulta("Usuario Validate", UserName, password); }
} }
Cada llamado mediante public bool, permite usar las consultas ya generadas en SQL las cuales son traídas mediante json (JavaScript Object Notation), el cual es un formato de texto ligero que será usado también para devolver los datos resultado de las diferentes consultas ejecutadas. Por ejemplo en la declaración UsuarioValidate, se llama a la consulta SQL ValidarUsuario, la misma se encuentra a continuación, al final de la misma se puede observar que se ha agregado la línea For Json Auto, la cual automáticamente guarda esta consulta en texto ligero para ser usado en otras plataformas:
SELECT IDPersona, RolPersona.IDRolPersona, RolPersona.Rol, Cedula, Nombre, Apellido,
Edad, Sexo, Altura, Peso, email, Password, Activo
FROM Personas
INNER JOIN RolPersona
85
WHERE Cedula = '{0}' AND Password = '{1}'
FOR JSON AUTO
3.3.2.3.1.4 Ejecución de consultas
Para poder ejecutar las consultas creadas en SQL y que se han llamado en el servicio web, se ha creado la clase Ejecuciones, donde se ha realizado el siguiente proceso para que funcio nes una consulta sin argumentos:
public static string GetConsulta(string query) {
try {
String queryJson = Herramientas.Consulta(query);
using (SqlConnection conn = new SqlConnection(ConfigurationManager. ConnectionStrings["Ceres21ConnectionString"].ConnectionString)) {
SqlCommand cmd = new SqlCommand(queryJson, conn); conn.Open();
StringBuilder jsonResult = new StringBuilder(); using (SqlDataReader reader = cmd.ExecuteReader()) { if (!reader.HasRows) jsonResult.Append("[]"); else { while (reader.Read())
86 jsonResult.Append(reader.GetValue(0).ToString()); } } return jsonResult.ToString(); } }
catch (Exception ex) {
return "Error:" + ex.Message; }
}
3.3.2.3.1.5 Serialización y deserializar
Como se explicó en el enunciado Web Services del presente capítulo, JSON es un formato de codificación de datos eficaz que permite intercambios rápidos de cantidades pequeñas de datos entre los exploradores de cliente y servicios web, pero el mismo debe ser modificado en el proceso para poder procesarlo correctamente y puedan ser entendidos para el usuario, así como transformar los datos ingresados a la aplicación para ser almacenados en la base de datos. A continuación, el código de deserealización y serialización de datos en formato JSON:
public static T Deserealizar<T>(string cadena, bool lista) {
Object obj = null; try
{
87 {
if (cadena.Substring(0, 1).Contains("["))
cadena = cadena.Substring(1, cadena.Length - 2); }
obj = (T)JsonConvert.DeserializeObject<T>(cadena); }
catch (Exception ex) {
string a = ex.Message; }
return (T)obj; }
public static string Serializar(object valor) {
return JsonConvert.SerializeObject(valor, Formatting.None); }