Anuncios

Bienvenidos sean a este post, hoy repasaremos y veremos nuevos temas sobre diseño.

Anuncios

En este post, hablamos sobrre el diseño y planeo del testing. Y en ese mecionamos que en esa seccion listamos a las entidades generales, tales como los usuarios, productos, galpones etc. Lo siguiente que hicimos fue descomponer cada entidad en componentes mas pequeños. Tambien mencionamos que consideremos a cada entidad como una clase. Hacerlo de esta manera, nos dara mas sentido en el termino de descomposicion. Tomemos como ejemplo la clase para el Usuario:

class Usuario
{
public:
  // constructores y operadores de asignacion omitidos para brevedad
  void set_nombre(const std::string& nombre);
  std::string get_nombre() const;
  void set_email(const std::string&);
  std::string get_email() const;
  // tambien omitimos la mayoria de metodos getter y setter

private:
  std::string nombre_;
  std::string email_;
  Domicilio domicilio_;
  int age;
};
Anuncios
Anuncios

Esta es una clase basica donde los datos del usuario estaran en la parte privada y podremos manejarlos mediante setter y getter en la parte publica. Pero en el post que mencionamos al inicio tambien discutimos el tema del domicilio. Para ello, creamos un struct para poder manipularla correctamente. Si bien, Domicilio no lo podemos considerar como una entidad pero si tendra una estrecha relacion con Usuario. Y este sera parte de Usuario, pero no podra tener su propio objeto sino existe uno de Usuario. Sin embargo, aqui entra en accion una buena practica como es el codigo reutilizable. Porque este mismo struct lo podemos usar tambien para el objeto de Galpon. Por eso, no debemos considerarlo como una composicion sino como un agregado.

Anuncios

Ahora podemos pasar al siguiente tema como son los datos ded pago. Tomemos como premisa lo realizado para el domicilio. Asi que deberiamos tener un struct donde almacenaremos una serie de datos basicos, veamos un ejemplo:

struct OpcionPagos
{
  std::string numero;
  std::string nombre_tarjeta;
  std::chrono::year_month fecha_expiracion;
  int cvv;
};
Anuncios
Anuncios

Como dijimos solo tendra datos basicos del metodo de pago como es una tarjeta de credito. En este caso, tendremos el numero de la tarjeta, el nombre del dueño de la tarjeta, la fecha de expiracion y el codigo de verificacion. Los usuarios de este tipo de plataformas de e-commerce notaran estos datos como habituales cada vez que se usan. En este ejemplo, usamos una particularidad como es year_month que fue introducido en C++20 y este permite almacenar solamente el mes y el año, lo cual nos viene perfecto. Para el resto, son datos que se utilizan todo el tiempo.

Anuncios

Con esto podemos pasar a actualizar nuestra clase Usuario para agregar las opciones de Pago:

class Usuario
{
public:
  // codigo omitido para brevedad
  void agregar_opcion_pago(const OpcionPagos& op) {
    opciones_pago_.push_back(op);
  }

  std::vector get_opciones_pago() const {
    return opciones_pago_;
  }
private:
  // codigo omitido para brevedad
  std::vector<OpcionPagos> opciones_pago_;
};
Anuncios

En la parte privada agregamos la propiedad encargada de manejar las opciones de pago pero usaremos un vector porque el usuario puede tener mas de una forma de pago. En la parte publica tendremos un metodo para agregar opciones de pago y otro para recuperarlas. Sin embargo, este codigo lo podemos mejorar de la siguiente manera:

class Usuario
{
public:
  // codigo omitido para brevedad
  void agregar_opcion_pago(const OpcionPagos& op, bool es_primario) {
    opciones_pago_.push_back(std::make_tuple(op, es_primario));
  }

  std::vector<std::tuple<OpcionPagos, boolean> > get_opciones_pago() const {
    return opciones_pago_;
  }
private:
  // codigo omitido para brevedad
  std::vector<std::tuple<OpcionPagos, boolean> > opciones_pago_;
};
Anuncios

En este caso simplemente modificamos al vector encargado de recibir los datos de pago para que ahora tenga un tuple que maneja dos tipos de datos. El primero es el que usaremos para almacenar los datos pero ahora tendremos un valor booleano para establecer cual de todos los objetos ingresados sera el primario. Esta modificacionn afecta a los dos metodos para agregar el metodo de pago y la recuperacion de los datos. En el primer caso, ahora debemos pasar un nuevo dato y en ambos casos se modifico el tipo de dato. El resto seguira siendo lo mismo. Tomemos este codigo y hagamos una modificacion estetica:

class Usuario
{
public:
  // codigo omitido para brevedad
  using ListaOpcionesPago = std::vector<std::tuple<OpcionPagos, boolean> >;
  
  void agregar_opcion_pago(const OpcionPagos& op, bool es_primario) {
    opciones_pago_.push_back(std::make_tuple(op, es_primario));
  }

  ListaOpcionesPago get_opciones_pago() const {
    return opciones_pago_;
  }
private:
  // codigo omitido para brevedad
  ListaOpcionesPago opciones_pago_;
};
Anuncios

Simplemente implementamos un alias con using para reemplazar todo la linea del vector en la parte publica. Y despues lo usamos en todas las propiedades y metodos donde se pasaba el vector. Funcionalmente es lo mismo pero quedo un poco mas simple y explicito a la vista. Vamos a suponer que tenemos nuestros metodos bien implementados, en el siguiente codigo veremos como utilizar la posibilidad de poder obtener el metodo de pago primario:

Usuario juan = get_usuario_actual();
auto opciones_pago = john.get_opciones_pago();
for (const auto& opcion : opciones_pago) {
  auto [op, es_primario] = option;
  if (es_primario) {
    // usamos el metodo primario...
  }
}
Anuncios
Anuncios

Primero creamos un objeto para el usuario con todos sus datos y para ello usaremos una funcion, supongamos que esta implementada y lista para ser usada, lo siguiente sera un objeto para obtener las opciones de pago del usuario. Para ello usamos al metodo get_opciones_pago, con todas las opciones obtenidas usaremos un bucle mejorado para pasar por todos ellos y de cada objeto obtendremos todos los datos y si es el primario. Cada dato que se obtiene pasara por un condicional que al momento que encuentre un true procedera a realizar la accion necesaria. Si bien, esto que comentamos es completamente funcional no es una buena practica porque estaremos pasando por todo el vector cada vez que lo necesitemos.

Anuncios

Para soluucionarlo, debemos nuevamente descomponerlo y para ello modificaremos el codigo de la siguiente manera:

class Usuario
{
public:
  // codigo omitido para brevedad
  using ListaOpcionesPago = std::vector<OpcionPagos>;

  OpcionPagos get_opcion_pago_primario() const {
    return opcion_pago_primaria_;
  }

  ListaOpcionesPago get_opciones_pago() const {
    return opciones_pago_;
  }

  void agregar_opcion_pago(const OpcionPagos& op, bool es_primario) {
    if (es_primario) {
      agregar_opcion_pago(opcion_pago_primaria_, false);
      opcion_pago_primaria_ = op;
      return;
    }
    opciones_pago_.push_back(op);
  }

private:
  // codigo omitido para brevedad
  OpcionPagos opcion_pago_primaria_;
  ListaOpcionesPago opciones_pago_;
};
Anuncios

Como dijimos vamos a descomponerlo, para ello separamos la parte de primaria. Ahora sera una propiedad independiente y por eso tendra una opcion para recuperarla pero para agregarla tambien cambiara. Sigue recibiendo dos valores para agregar la opcion de pago pero ahora trabajara de manera diferente. Porque ahora verificara si es_primario es verdadero y en caso de ser asi, toma la opcion de pago actual y la pasa a no primarias. Luego pasamos al objeto informado con los datos de pago como el nuevo primario y salimos. En caso de no haber sido asi,, agregamos el objeto recibido a las opciones de pago.

Anuncios

Esta es una forma mas equilibrada tanto de agregar una opcion de pago, y establecer como primaria. Asi como tambien, obtendremos unicamente el metodo de pago primario. Pero esto esta lejos de ser lo mas optimo, porque esto no contempla para el caso de cuando no tengamos valores duplicados en nuestro vector. Pero esos son temas que podemos ir solucionando mas adelante.

Anuncios

En resumen, hoy hemos visto un poco mas profundamente como es el proceso de diseño, repasamos algunos temas, asi como tambien hemos visto nuevas conductas para nuestro proyecto. Espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios
pp258

Donación

Es para mantenimento del sitio, gracias!

$1.50