Programación orientada a aspectos



Introducción

La programación orientada a aspectos es una técnica de programación surgida a fines de los años de 1990 y con importante crecimiento en los últimos años, busca facilitar la modularización de aquellas incumbencias transversales que resultan de difícil modularización con las técnicas tradicionales de programación.

Desde sus inicios los lenguajes de programación han evolucionado proveyendo cada vez mejores técnicas de modularización. Sin duda la programación orientada a objetos (POO) ha sido una de las técnicas de modularización más potentes, pero a pesar de ello siguen existiendo ciertas incumbencias (concerns) que ni la POO ni las técnicas precedentes de programación han logrado modularizar de manera efectiva. La dificultad de modularizar estas incumbencias se debe a que las técnicas tradicionales de programación proveen la posibilidad de descomponer el problema de acuerdo a una única dimensión (la dominante), permitiendo un efectiva modularización de las incumbencias de dicha dimensión a costa de sacrificar una buena modularización de las incumbencias de las demás dimensiones. Este problema ha sido denominado "la tiranía de la descomposición dominante" [Tarr99] y como consecuencia del mismo las incumbencias de las dimensiones no dominantes adquieren una naturaleza transversal que les otorga el nombre de incumbencias transversales CCC (Cross Cutting Concerns).

Como consecuencia directa de estos CCC aparecen dos fenómenos no deseados. El primero de ellos es denominado código disperso(code scattering) y se da cuando existen invocaciones a un método esparcidas por toda la aplicación.

El segundo de estos fenómenos es el llamado código mezclado (code tangling) y se da cuando una clase tiene código que nada tiene que ver con su esencia, lo cual disminuye su cohesión y viola uno de los principios básicos del diseño de objetos: el principio de única responsabilidad.

Entre las consecuencias de estos dos fenómenos se cuentan acoplamiento, dificultad de mantenimiento, menor claridad del código y todas las demás consecuencias de una pobre modularización.

Reseña Histórica

El científico de la Computación Edsger Dijkstra introdujo el término "separación de incumbencias" por la década de los 1970. Significa que la resolución de un problema involucra varios aspectos o incumbencias, los cuales deben ser identificadas y analizadas en forma independiente.El término "programación orientada a aspectos" surgió de un trabajo de Gregor Kiczalez y su equipo en el centro de investigación de Xerox, en Palo Alto, hacia fines de los 90' [Kiczales97].

La definición actual de aspecto dice: "Un aspecto es una unidad modular que se disemina por la estructura de otras unidades funcionales. Los aspectos existen tanto en la etapa de diseño como en la implementación. Un aspecto de programa o de código es una unidad modular del programa que aparece en otras unidades modulares del programa".

La principal ventaja de este método es que permite tratar la funcionabilidad por un lado y los aspectos por otro, de forma separada. Luego ambos se combinan con un tipo de programa llamado "weaver" para dar un resultado el sistema final.

La programación orientada a aspectos se ha planteado como un nuevo paradigma de programación, el cual consiste en separar los conceptos que entrecruzan varias clases y se extienden a lo largo de éstas, pero que no pertenecen a esas clases en sí mismas.

La pregunta ¿Qué es un aspecto?, para definirla daremos ejemplos. La verificación de permisos es un aspecto, el registro de bitácora es un aspecto, el manejo de errores es un aspecto,

LaProgramación Orientada a Aspectoso POA (Aspect Oriented Programming) es un paradigma de programación relativamente reciente cuya intención es permitir una adecuada modularización de las aplicaciones y posibilitar una mejor separación de responsabilidades (Obligación o correspondencia de hacer algo).

Gracias a la POA se pueden encapsular los diferentes conceptos que componen una aplicación en entidades bien definidas, eliminando las dependencias entre cada uno de los módulos. De esta forma se consigue razonar mejor sobre los conceptos, se elimina la dispersión del código y las implementaciones resultan más comprensibles, adaptables y reusables. Varias tecnologías con nombres diferentes se encaminan a la consecución de los mismos objetivos y así, el término POA es usado para referirse a varias tecnologías relacionadas como los métodos adaptativos, los filtros de composición, laprogramación orientada a sujetoso laseparación multidimensional de competencias.

El principal objetivo de la POA es la separación de las funcionalidades dentro del sistema:

Desarrollo de software orientado a aspectos

El desarrollo de software orientado a aspectos constituye un área de investigación centrada en lograr una efectiva modularización de incumbencias. Dentro de esta área existen varios enfoques.

Entre estos enfoques se encuentran Adaptative programming, Composition Filters, Multidimensional Seperation of Concerns, Subject-Oriented Programming y Aspect-Oriented Programming, entre otros. Cada uno de estos enfoques ofrece distintos mecanismos para la separación y composición de incumbencias.

La POA es una tecnología que se basa principalmente en la POO para la implementación de los componentes base, esto no quiere decir bajo ningún caso que no pueda utilizarse con otros estilos de programación, dado que la POA también soporta programación estructurada o funcional. Es por esta razón que la programación orientada a aspectos no puede ser vista como una extensión de la POO.

El principal objetivo de AOP es lograr una efectiva modularización de los CCC de manera transparente (oblivious) y soportando distintas formas de cuantificación. Desde el punto de vista de AOP, una aplicación consiste en un conjunto de incumbencias dominantes fácilmente modularizables (componentes base), más un conjunto de incumbencias transversales de difícil modularización (aspectos). La mezcla de los componentes base y los aspectos da como resultado la aplicación final.Dicha mezcla se realiza por medio de un proceso denominado entretejido (weaving). La asimetría entre los componentes base y los aspectos pone de manifiesto en enfoque asimétrico de AOP en lo que a separación de incumbencias respecta.

Conceptualmente existen dos paradigmas para la separación de las incumbencias, uno es el paradigma simétrico y otro es el paradigma asimétrico [Harrison02].

El paradigma simétrico plantea que, para lograr una efectiva separación de incumbencias, es necesario romper con la tiranía de la descomposición dominante. Para ello todas las incumbencias son modeladas como componentes de primera clase, todos con la misma estructura y donde ninguno es más básico que otro. Podría decirse que el estandarte de este paradigma es el enfoque planteado por la técnica denominada Multidimensional Separation of Concerns.

El paradigma asimétrico por su parte hace una diferenciación entre las incumbencias dominantes (también llamadas centrales o funcionales) las cuales modela mediante componentes base que luego son compuestos con las incumbencias no dominantes (también llamadas aspectos, no centrales o secundarias). Como se vio en el ejemplo de la sección anterior, las incumbencias no centrales en un paradigma asimétrico que tienen generalmente una naturaleza transversal.

Conceptos involucrados en la POA

Un aspecto es una unidad modular que se disemina por la estructura de otras unidades funcionales. En palabras simples un aspecto puede ser definido como: "la encapsulación y modularización de un asunto transversal".

Monografias.com

Interacción entre aspectos y funcionalidad básica.

Las características más relevantes de los aspectos para ser considerados como tales son:

La estructura de una implementación basada en aspectos es análoga a la estructura de una implementación basada en los LPG.Una implementación basada en LPG consiste en:

Monografias.com

Nótese que la función que realizaba el compilador se encuentra incluida en las funciones del tejedor.

Elementos del Paradigma de la POA

Un aspecto es una abstracción que permite modularizar una incumbencia transversal. Los puntos en la ejecución de los componentes base donde es posible el entretejido de aspectos son denominados joinpoints. Algunos ejemplos de joinpoints son: una llamada a un método, la creación de una instancia, el manejo de una excepción, la ejecución de un ciclo, el retorno de un método, la asignación de un valor a una variable, la modificación de un atributo, entre otros. El modelo de jointpoints de una herramienta AOP, define los tipos de cuantificaciones que dicha herramienta soporta y por consiguiente la potencia de la herramienta.

Ilustración 1: Código de Ejemplo con Varios Joinpoints

Monografias.com

En el fragmento de código de la Ilustración 1 existen los siguientes joinpoints.

Monografias.com

A un conjunto definido de joinpoints se lo llama pointcut. A diferencia de los jointpoints, los pointcuts, son definidos por el programador. Algunos pointcuts simples podrían ser todas las ejecuciones del constructor de una determinada clase, todas las llamadas al método Pow de la clase Math que reciba como parámetro un 5 o es lanzado de una excepción de la clase RuntimeException. Todas las herramientas AOP brindan un conjunto de designadores de pointcuts que en conjunto con el uso de expresiones regulares permiten la definición de los pointcuts. La siguiente tabla muestra algunos designadores de pointcuts de aspectj.

Monografias.com

El código del aspecto que se ejecuta asociado a un determinado pointcut es denominado advice. Conceptualmente los advices contienen el comportamiento del aspecto. Los advices puede ser básicamente de 3 tipos.

Monografias.com

Elementos que forman los componentes base o funcionalidad básica versus elementos que forman los aspectos.

Otro elemento de AOP, muchas veces pasado por alto, es la declaración de intertipos (también llamada introducción o mixin) que permite extender la estructura de un componente base mediante el agregado de miembros (métodos y atributos) e interfases.

La declaración de un intertipo forma parte de un aspecto y es dicho aspecto el que define cuáles serán los componentes base que se extenderán con el intertipo. Hay que destacar que las extensiones realizadas por un intertipo no son visibles para los componentes base, ni tampoco para el propio componente que ha sido extendido.

Por ejemplo, para entender esta situación: supongamos que para poder persistir objetos en una base de datos es necesario que todo objeto implemente la interfase ObjetoPersistente, la cual define un método para obtener el identificador del objeto a utilizarse como clave primaria en la base de datos.

Utilizando AOP podría definirse un aspecto que con una declaración de intertipo se encargue de las siguientes cuestiones.

Ahora, dado un objeto que al que se le ha agregado el mencionado aspecto para implementar la interfaz ObjetoPersistente, si algún objeto quisiera tratarlo como un ObjetoPersistente, debería previamente castearlo a dicho tipo, ya que lo agregado por las declaraciones de intertipos no es directamente visible para los componentes base.

Un aspecto es una entidad que modulariza una incumbencia transversal mediante la definición de un conjunto de pointcuts, advices y declaraciones de intertipo.

Dependiendo de la herramienta utilizada, puede que la definición de un aspecto se haga enteramente en un archivo fuente, tal como ocurre con una clase en java, o bien que los advices e introducciones de definan en un archivo fuente y los poincuts en un archivo de configuración de la aplicación final.

Básicamente y muy a grandes rasgos podemos decir que existen dos tipos de herramientas AOP, diferenciadas principalmente por el modelo de entretejido, el cual puede ser estático o dinámico.

Las herramientas AOP de entretejido estático son los compiladores, pre compiladores y post compiladores. Estas herramientas toman como entrada los aspectos y los componentes base en forma de código fuente o binario y generan como salida código binario con los aspectos y los componentes base ya entretejidos. En general los componentes base se escriben en algún lenguaje orientado a objetos, mientras que los aspectos se escriben en nuevos lenguajes con soporte de aspectos que generalmente son una extensión al lenguaje orientado a objetos de los componentes base. Este es el caso de AspectJ[1]aspectj], Aspect.NET [aspectnet] y AspectC++ [aspectc++], entre otros.

Las herramientas AOP de entretejido dinámico son generalmente frameworks desarrollados en un lenguaje orientados a objetos y están basados en proxies dinámicos.

La definición del aspecto consta de dos partes. Por un lado, se define el advice, extendiendo una clase base provista por el framework de aspectos. Por otro lado, se realiza la definición de los pointcuts, la cual suele hacerse por medio de metadata, que muchas veces reside en archivos XML. Por lo general si un aspecto consta de más de un advice, es necesario crear una clase por cada advice.

Estos frameworks proveen una clase que funciona como una fábrica de objetos y que es el punto de acceso a la funcionalidad del framework (ver Ilustración 2) muestra las clases típicas de un framework AOP, hay que destacar que la clase Proxy suele ser creada en tiempo de ejecución. Esta fábrica de objetos interpreta los pointcuts definidos en la metadata y en base a eso a la hora de crear un objeto detecta si deben agregarse aspectos al objeto creado, en cuyo caso crea un proxy con el conjunto de advices que aplicarán al objeto en cuestión y devuelve una referencia al proxy en lugar de una referencia directa el objeto pedido. El diagrama de secuencia de la Ilustración 3, representa este proceso.

Ilustración 2: Clases Típicas de un Frameworks POA

Monografias.com

Ilustración 3: Creación de un Objeto Aspectizado por un Framework POA

Monografias.com

De esta forma todas las llamadas al objeto con aspectos son interceptadas por el proxy que da intervención a los advices, los cuales actúan antes y/o después de la ejecución del objeto en cuestión. Ejemplos de herramientas de este tipo son: SpringFramework [spring], JbossAOP [jbossaop], Loom.NET [loom] y Naspect [naspect].

Ilustración 4: Secuencia de ejecución de un advice de Tipo Before

Monografias.com

Hay una serie de cuestiones que caracterizan a cada tipo de herramienta.

Si bien hasta el momento hemos hecho referencia a sólo dos tipos de entretejido -estático y dinámico- en tecnologías basadas en máquinas virtuales, existen distintas variantes de estos tipos de entretejido. En el caso de Java, el entretejido dinámico puede implementarse en tiempo de ejecución o también en tiempo de carga, para lo cual se reemplaza el cargador de clases de la máquina virtual, por un cargador de clases que realiza el trabajo adicional del entretejido. En estos casos el cargador de clases reemplaza lo que hemos denominado fábrica de objetos.

Entre las herramientas AOP existentes en la actualidad se destacan Aspectj, Jboss-AOP y SpringFramework, aunque más allá de estas tres existe una cantidad importante de herramientas casi todas ellas extensiones a lenguajes OO [aspectc++], [Loom.NET], [aspectDNG], [Naspect], [aspect#].

Sin duda, gran parte del camino de la evolución de AOP lo ha marcado AspectJ, siendo la primera herramienta estable y la de mayor difusión en la actualidad. Al mismo tiempo hay que destacar el aporte de SpringFramework, promoviendo el uso de AOP en ambientes enterprise.

Habiendo analizado las incumbencias técnicas, que en cierta forma podríamos llamar secundarias, es hora de analizar las incumbencias del negocio que, si bien son la parte distintiva y más compleja de las aplicaciones enterprise, no es común que se las modele como aspectos.

Generalmente en las incumbencias de negocio de las aplicaciones enterprise puede distinguirse:

Mediante la siguiente aplicación, se emplea la metodología de la Programación Orientada a Aspectos, a través del Diseño e Implementación de un software de escritorio, el cual es una Calculadora Científica.

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

Monografias.com

import javax.swing.JOptionPane;

import javax.swing.JTextField;

/* calculadora.java

*

* Created on Junio 20, 2017, 7:18:07 PM

*/

public class calculadora extends javax.swing.JFrame {

private String cadena="";

private String memoria="";

private double memoriaoperacion=0.00;

private double temporal=0.00;

private double tercera=0.00;

private double otro=0.00;

private String resultado="";

int pendiente=0;

/** Creates new form calculadora */

public calculadora() {

initComponents();

txtsalida.setHorizontalAlignment(JTextField.RIGHT);

}

/** This method is called from within the constructor to

* initialize the form.

* WARNING: Do NOT modify this code. The content of this method is

* always regenerated by the Form Editor.

*/

@SuppressWarnings("unchecked")

//

private void initComponents() {

txtsalida = new javax.swing.JTextField();

cmdMc = new javax.swing.JButton();

cmdMr = new javax.swing.JButton();

cmdMmas = new javax.swing.JButton();

cmdMmenos = new javax.swing.JButton();

cmdMmasmenos = new javax.swing.JButton();

cmdCe = new javax.swing.JButton();

cmdC = new javax.swing.JButton();

cmdMasmenos = new javax.swing.JButton();

cmdSqrt = new javax.swing.JButton();

cmdx2 = new javax.swing.JButton();

cmd9 = new javax.swing.JButton();

cmd8 = new javax.swing.JButton();

cmd7 = new javax.swing.JButton();

cmdEntre = new javax.swing.JButton();

cmdPorciento = new javax.swing.JButton();

cmdUnosobrex = new javax.swing.JButton();

cmd4 = new javax.swing.JButton();

cmdMas = new javax.swing.JButton();

cmd6 = new javax.swing.JButton();

cmd5 = new javax.swing.JButton();

cmd1 = new javax.swing.JButton();

cmd2 = new javax.swing.JButton();

cmdXpotenciay = new javax.swing.JButton();

cmd3 = new javax.swing.JButton();

cmdMenos = new javax.swing.JButton();

cmdCero = new javax.swing.JButton();

cmdPunto = new javax.swing.JButton();

cmdIgual = new javax.swing.JButton();

cmdBackspace = new javax.swing.JButton();

cmdMultiplicar = new javax.swing.JButton();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

setTitle("Calculadora");

setLocationByPlatform(true);

setResizable(false);

txtsalida.setBackground(new java.awt.Color(255, 255, 255));

txtsalida.setEditable(false);

txtsalida.setText("0");

txtsalida.setBorder(javax.swing.BorderFactory.createCompoundBorder());

cmdMc.setText("MC");

cmdMc.setMaximumSize(new java.awt.Dimension(61, 25));

cmdMc.setMinimumSize(new java.awt.Dimension(61, 25));

cmdMc.setPreferredSize(new java.awt.Dimension(39, 25));

cmdMc.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdMr.setText("MR");

cmdMr.setMaximumSize(new java.awt.Dimension(61, 25));

cmdMr.setMinimumSize(new java.awt.Dimension(61, 25));

cmdMr.setPreferredSize(new java.awt.Dimension(39, 25));

cmdMr.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdMmas.setText("M+");

cmdMmas.setMaximumSize(new java.awt.Dimension(61, 25));

cmdMmas.setMinimumSize(new java.awt.Dimension(61, 25));

cmdMmas.setPreferredSize(new java.awt.Dimension(39, 25));

cmdMmas.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdMmenos.setText("M-");

cmdMmenos.setMaximumSize(new java.awt.Dimension(61, 25));

cmdMmenos.setMinimumSize(new java.awt.Dimension(61, 25));

cmdMmenos.setPreferredSize(new java.awt.Dimension(39, 25));

cmdMmenos.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdMmasmenos.setText("M+/-");

cmdMmasmenos.setPreferredSize(new java.awt.Dimension(39, 25));

cmdMmasmenos.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdCe.setText("CE");

cmdCe.setMaximumSize(new java.awt.Dimension(61, 25));

cmdCe.setMinimumSize(new java.awt.Dimension(61, 25));

cmdCe.setPreferredSize(new java.awt.Dimension(39, 25));

cmdCe.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdC.setText("C");

cmdC.setMaximumSize(new java.awt.Dimension(61, 25));

cmdC.setMinimumSize(new java.awt.Dimension(61, 25));

cmdC.setPreferredSize(new java.awt.Dimension(39, 25));

cmdC.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdMasmenos.setText("+/-");

cmdMasmenos.setMaximumSize(new java.awt.Dimension(61, 25));

cmdMasmenos.setMinimumSize(new java.awt.Dimension(61, 25));

cmdMasmenos.setPreferredSize(new java.awt.Dimension(39, 25));

cmdMasmenos.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdSqrt.setText("sqrt");

cmdSqrt.setMaximumSize(new java.awt.Dimension(61, 25));

cmdSqrt.setMinimumSize(new java.awt.Dimension(61, 25));

cmdSqrt.setPreferredSize(new java.awt.Dimension(39, 25));

cmdSqrt.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdx2.setText("x^2");

cmdx2.setMaximumSize(new java.awt.Dimension(61, 25));

cmdx2.setMinimumSize(new java.awt.Dimension(61, 25));

cmdx2.setPreferredSize(new java.awt.Dimension(39, 25));

cmdx2.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmd9.setText("9");

cmd9.setMaximumSize(new java.awt.Dimension(61, 25));

cmd9.setMinimumSize(new java.awt.Dimension(61, 25));

cmd9.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmd8.setText("8");

cmd8.setMaximumSize(new java.awt.Dimension(61, 25));

cmd8.setMinimumSize(new java.awt.Dimension(61, 25));

cmd8.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmd7.setText("7");

cmd7.setMaximumSize(new java.awt.Dimension(61, 25));

cmd7.setMinimumSize(new java.awt.Dimension(61, 25));

cmd7.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdEntre.setText("/");

cmdEntre.setMaximumSize(new java.awt.Dimension(61, 25));

cmdEntre.setMinimumSize(new java.awt.Dimension(61, 25));

cmdEntre.setPreferredSize(new java.awt.Dimension(39, 25));

cmdEntre.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdPorciento.setText("%");

cmdPorciento.setMaximumSize(new java.awt.Dimension(61, 25));

cmdPorciento.setMinimumSize(new java.awt.Dimension(61, 25));

cmdPorciento.setPreferredSize(new java.awt.Dimension(39, 25));

cmdPorciento.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdUnosobrex.setText("1/x");

cmdUnosobrex.setMaximumSize(new java.awt.Dimension(61, 25));

cmdUnosobrex.setMinimumSize(new java.awt.Dimension(61, 25));

cmdUnosobrex.setPreferredSize(new java.awt.Dimension(39, 25));

cmdUnosobrex.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmd4.setText("4");

cmd4.setMaximumSize(new java.awt.Dimension(61, 25));

cmd4.setMinimumSize(new java.awt.Dimension(61, 25));

cmd4.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdMas.setText("+");

cmdMas.setMaximumSize(new java.awt.Dimension(61, 25));

cmdMas.setMinimumSize(new java.awt.Dimension(61, 25));

cmdMas.setPreferredSize(new java.awt.Dimension(39, 25));

cmdMas.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmd6.setText("6");

cmd6.setMaximumSize(new java.awt.Dimension(61, 25));

cmd6.setMinimumSize(new java.awt.Dimension(61, 25));

cmd6.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmd5.setText("5");

cmd5.setMaximumSize(new java.awt.Dimension(61, 25));

cmd5.setMinimumSize(new java.awt.Dimension(61, 25));

cmd5.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmd1.setText("1");

cmd1.setMaximumSize(new java.awt.Dimension(61, 25));

cmd1.setMinimumSize(new java.awt.Dimension(61, 25));

cmd1.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmd2.setText("2");

cmd2.setMaximumSize(new java.awt.Dimension(61, 25));

cmd2.setMinimumSize(new java.awt.Dimension(61, 25));

cmd2.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdXpotenciay.setText("x^y");

cmdXpotenciay.setMaximumSize(new java.awt.Dimension(61, 25));

cmdXpotenciay.setMinimumSize(new java.awt.Dimension(61, 25));

cmdXpotenciay.setPreferredSize(new java.awt.Dimension(39, 25));

cmdXpotenciay.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmd3.setText("3");

cmd3.setMaximumSize(new java.awt.Dimension(61, 25));

cmd3.setMinimumSize(new java.awt.Dimension(61, 25));

cmd3.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdMenos.setText("-");

cmdMenos.setMaximumSize(new java.awt.Dimension(61, 25));

cmdMenos.setMinimumSize(new java.awt.Dimension(61, 25));

cmdMenos.setPreferredSize(new java.awt.Dimension(39, 25));

cmdMenos.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdCero.setText("0");

cmdCero.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdPunto.setText(".");

cmdPunto.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdIgual.setText("=");

cmdIgual.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdBackspace.setText("Borrar");

cmdBackspace.setMargin(new java.awt.Insets(2, 1, 2, 1));

cmdBackspace.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

cmdMultiplicar.setText("*");

cmdMultiplicar.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

evento(evt);

}

});

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());

getContentPane().setLayout(layout);

layout.setHorizontalGroup(

layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(layout.createSequentialGroup()

.addGap(23, 23, 23)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addComponent(txtsalida, javax.swing.GroupLayout.DEFAULT_SIZE, 338, Short.MAX_VALUE)

.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)

.addComponent(cmd4, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)

.addComponent(cmd7, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)

.addComponent(cmdCe, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)

.addComponent(cmdMc, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE))

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(layout.createSequentialGroup()

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)

.addComponent(cmdC, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)

.addComponent(cmdMr, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE))

.addComponent(cmd8, javax.swing.GroupLayout.PREFERRED_SIZE, 61, javax.swing.GroupLayout.PREFERRED_SIZE))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)

.addComponent(cmd9, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)

.addComponent(cmdMasmenos, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)

.addComponent(cmdMmas, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)))

.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addComponent(cmd5, javax.swing.GroupLayout.PREFERRED_SIZE, 61, javax.swing.GroupLayout.PREFERRED_SIZE)

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addComponent(cmd6, javax.swing.GroupLayout.PREFERRED_SIZE, 61, javax.swing.GroupLayout.PREFERRED_SIZE)))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addComponent(cmdMas, javax.swing.GroupLayout.DEFAULT_SIZE, 66, Short.MAX_VALUE)

.addComponent(cmdEntre, javax.swing.GroupLayout.DEFAULT_SIZE, 66, Short.MAX_VALUE)

.addComponent(cmdMmenos, javax.swing.GroupLayout.DEFAULT_SIZE, 66, Short.MAX_VALUE)

.addComponent(cmdSqrt, 0, 66, Short.MAX_VALUE))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)

.addComponent(cmdUnosobrex, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)

.addComponent(cmdPorciento, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)

.addComponent(cmdx2, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)

.addComponent(cmdMmasmenos, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)))

.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)

.addComponent(cmdCero, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE)

.addComponent(cmd1, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)

.addComponent(cmdPunto, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)

.addComponent(cmd2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)

.addComponent(cmdIgual, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)

.addComponent(cmd3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 61, Short.MAX_VALUE))

.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)

.addComponent(cmdMenos, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)

.addComponent(cmdMultiplicar, javax.swing.GroupLayout.DEFAULT_SIZE, 66, Short.MAX_VALUE))