Eclipse -- I -- Historia y Toma de Contacto

Puede encontrar la versión original de este artículo en Inglés en:

http://www.onjava.com/

Un poco de Historia

Si ha seguido de cerca la programación en Java o el tema de Open Source, habrá oído hablar de Eclipse. Eclipse es un IDE (Integrated Development Environment) open source y extensible. El proyecto se lanzó originalmente en Noviembre de 2001, cuando IBM donó 40 millones de dolares del código fuente de Websphere Studio Workbench y formó el Eclipse Consortium para controlar el desarrollo continuado de la herramienta.

El objetivo de Eclipse era "desarrollar una plataforma industrial robusta, con todas las características y de calidad industrial para el desarrollo de herramientas altamente integradas". Al final, el Eclipse Consortium se había enfocado en tres proyectos principales:

  1. The Eclipse Project es responsable de desarrollar el workbench (banco de trabajo) del IDE Eclipse (la "plataforma" que contiene las herramientas Eclipse), el JDT (Java Development Tools), y el PDE (Plug-In Development Environment) utilizado para ampliar la plataforma.
  2. The Eclipse Tools Project se enfoca en la creación de herramientas para la plataforma Eclipse. Entre los subproyectos actuales se incluyen un IDE Cobol, un IDE C/C++, y una herramienta de modelado EMF.
  3. The Eclipse Technology Project se enfoca en investigaciones tecnológicas, incubación y educación utilizando la plataforma Eclipse.

La plataforma Eclipse, cuando se combina con el JDT, ofrece muchas de las características que cabría esperar de un IDE de calidad comercial: editor con síntaxis coloreada, compilación incremental, un depurador que tiene en cuenta los threads a nivel fuente, un nevegador de clases, un controlador de ficheros/proyectos, e interfaces para control estándar de código fuente, como CVS y ClearCase.

Eclipse también incluye varias características únicas, como la refactorización de código, la actualización/instalación automática de código (mediante Update Manager), una lista de tareas, soporte para unidades de test con JUnit, e integración con la herramienta de construcción de Jakarta: Ant.

A pesar del gran número de características estándar, Eclipse se diferencia de los IDEs tradicionales en varias cosas fundamentales. Quizás lo más interesante de Eclipse es que es completamente neutral a la plataforma - y al lenguaje. Además de la mezcla ecléctica de lenguajes soportados por el Eclipse Consortium (Java, C/C++, Cobol), también hay otros proyectos para añadir a Eclipse el soporte de lenguajes tan diversos como Python, Eiffel, PHP, Ruby, y C#.

Con respecto a las plataformas, el Eclipse Consortium proporciona instalaciones binarias para Windows, Linux, Solaris, HP-UX, AIX, QNX, y Mac OS X. La mayoría de cosas interesantes que posee Eclipse se centran en la arquitectura de plug-ins y el API proporcionado por el Plug-in Development Environment para ampliarlo. Añadir soporte para un nuevo tipo de editor, una vista, o un lenguaje de programación, es remarcadamente fácil, con el API y los bloques de construcción que proporciona Eclipse.

Con cientos de proyectos de desarrollo de plug-ins en progreso, los gigantes de la industria como IBM, HP, y Rational, proporcionan recursos, y diseños de peso pesado como Erich Gamma helping para guiarnos en el proceso.

Instalación

Se estará preguntando donde obtener una copia de Eclipse para su plataforma y qué tiene que hacer para instalarla. Lo primero que necesita hacer es asegurarse de que tiene disponible un Java runtime (JRE) apropiado. Aunque Eclipse puede compilar código para las versiones 1.3 y 1.4 del JDK, las versiones actuales están diseñadas para una versión 1.3. Si no está seguro de donde encontrar la JVM apropiada para su plataforma, puede encontrar más información en: eclipse.org.

Una vez que tenga la JVM, está listo para obtener Eclipse. Visite la página de descargas de Eclipse y coja la última versión liberada para su plataforma. Todas las versiones se entregan como ficheros .zip. Descomprima el archivo en un directorio apropiado y luego lea todos los ficheros que estén presentes en el directorio readme.

Lo crea o no, ya se ha terminado la instalación. Si ha instalado apropiadamente la JVM y ha desempaquetado correctamente el archivo de Eclipse, debería poder ejecutarlo ahora mismo.

Todas las distribuciones binarias proporcionan una aplicación lanzadora en el directorio principal de Eclipse. El nombre de esa aplicación varía entre plataformas: eclipse.exe en Windows, eclipse en Solaris, etc. La primera vez que se ejecute Eclipse, completará algunas pocas tareas que quedan de la instalación (es decir, la creación del directorio workspace para almacenar los ficheros de proyecto) antes de que aparezca el entorno.

El Interface

Después de lanzar Eclipse por primera vez, debería ver una ventana como ésta:

Como puede ver, el IDE Eclipse tiene una barra de menú bastante estándar:

y una barra de herramientas:

También hay una ventana del editor con pestañas, que inicialmente muestra la página de Bienvenida:

Una Aplicación de Ejemplo

El Navegador de Ficheros, la Lista de Tareas y la ventana de Code Outline está presentes pero vacías. Para poder continuar con la exploración de Eclipse, vamos a crear un programa de una sencilla calculadora basada en Swing:

  1. Seleccion File->New->Project... para empezar a crear su primer proyecto Java. En el wizard que aparece, seleccione Java y de la lista de posibles tipos de proyecto seleccione Java Project, luego pulse el botón Next

  2. Como nombre de proyecto, ponga Calculator, luego pulse de nuevo el botón Next.

  3. El paso final del wizard permite indicar dónde residirán el código fuente y los ficheros class, especificar cualquier sub-proyecto que se pudiera necesitar para el proyecto actual, y proporcionar cualquier librería necesaria para su construcción. Seleccione el botón de radio Use source folder contained in the project, luego pulse el botón Create New Folder.... Introduzca src como nombre de la nueva carpeta. Pulse Yes cuando Eclipse le pregunte si quiere actualizar la carpeta de salida del proyecto como Calculator/bin.

  4. Pulse el botón Finish para hacer que Eclipse cree el nuevo proyecto.

Una vez creado el proyecto, y tras aceptar la ventana que indica que este es un proyecto Java, puede abrir la 'Perspectiva Java' para visualizarlo, podría observar que la distribución de las ventanas ha cambiado: la vista Outline se ha movido al lado derecho de la pantalla, el Navigator ha sido reemplazado por el Package Explorer, etc.

Una Perspectiva, en el lenguaje de Eclipse, es una distribución de ventanas que contiene cualquier número de editores y vistas diferentes. Eclipse viene con varias perspectivas por defecto (Resource, Java, Debug, etc.) que se pueden personalizar, o se pueden crear perspectivas completamente nuevas. Las perspectivas se manejan utilizando ítems del menú Window o desde la barra de herramientas de perspectivas situadas en la parte superior derecha de la ventana de Eclipse.

El siguiente paso en la creación de un proyecto Java es crear los directorios que contendrán el código fuente. Cambie a la perspectiva Resource utilizando Window->Open Perspective->Resource. En la vista Navigator, expanda el árbol de carpetas hasta que vea el nodo src. Seleccione este nodo, luego elija el menú File->New->Folder. En el diálogo que aparece, asegurese de que está seleccionado el directorio src, luego introduzca com en el campo Folder Name.

Crear muchas carpetas utilizando el diálogo New Folder puede ser un poco aburrido. Afortunadamente, Eclipse es tan bueno que permite hacer el trabajo utilizando su interface favorito al sistema de ficheros, ventana de comandos, Windows Explorer, etc. Utilice uno de estos métodos para crear dos carpetas llamadas devious y calculator bajo la carpeta com. Una vez que haya hecho esto, seleccione cualquier carpeta en el Navigator y luego seleccione en el menú File->Refresh. Eclipse examinará el sistema de ficheros y actualizará el proyecto adecuadamente. En este punto, el proyecto debería parecerse a esto:

Una forma mejor para crear las carpetas de los paquetes Java es utilizar los menús contextuales que aparecen al pulsar el botón derecho. Por ejemplo, se podría haber creado la ruta de directorios com/devious/calculator en un sólo paso si desde la perspectiva Java se hubiéra pulsado el botón derecho sobre la carpeta src:

Luego en la nueva ventana se pone el nombre completo del paquete incluyendo los puntos separadores (es decir com.devious.calculator):

Añadir Código

Ahora que ya está creada la estructura de directorios, se puede empezar a añadir código al proyecto. Se dividirá el programa Calculator en tres ficheros diferentes:

  • CalcPanel.java que maneja casi todo el interface de usuario de nuestra calculadora.
  • Calculator.java que maneja la configuración y el lanzamiento del GUI.
  • Y CalModel.java, que implementa los "mecanismos" reales de la calculadora: responde a eventos, realiza los cálculos numéricos, actualiza el display, etc.

Empezaremos por la primera clase para diseñar todo el interface de usuario. La clase CalcPanel.java debe extender la clase JPanel e implementar los interfaces Observer y ActionListener:

  1. En el Explorador de Paquetes pulse con el botón derecho sobre com.devious.calculator y selecccione New > Class:

  2. Aparecerá la siguiente ventana. Escriba CalcPanel como nombre de la clase:

  3. Pulse sobre el botón Browse al lado de Superclass para cambiar la superclase, recuerde que CalcPanel debe extender JPanel. En la ventana que aparecerá introduzca JP en el cuadro de texto superior y aparecerá una lista de clases que empiezan con esas letras, seleccione JPanel y pulse OK:

  4. Ahora haga lo mismo pulsando sobre el botón Add junto a Interfaces para añadir los interfaces Observer y ActionListener:

  5. Seleccione el resto de los botones de radio según la siguiente imagen y pulse Finish, después de uno segundos Eclipse mostrará este aspecto, donde se puede ver la clase recién creada en el editor Java:

  6. Ahora sólo falta teclear el código de la clase. Puede hacerlo utilizando este listado, o bajarse el código fuente de CalcPanel.java:
    
    package com.devious.calculator;
    
    import javax.swing.*;
    import javax.swing.event.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.lang.*;
    import java.util.*;
    
    /**
     * The primary user-interface for our simple calculator application.
     * The UI consists of a JLabel "display" and a panel of JButtons
     * which allow the user to enter numbers and perform basic arithmetic
     * operations.
     * 
     * @author [email protected]
     */
    public class CalcPanel
    	extends JPanel
    	implements ActionListener, Observer
    {
    	/**
    	 * The CalcModel associated with this particular instance of
    	 * the calculator GUI.
    	 */
        private CalcModel model;
        
        /**
         * The JLabel which serves as the "display" for this calculator.
         */
        private JLabel display = new JLabel("0");
    
        /**
         * Constructor for CalcPanel.
         * 
         * @param model    the CalcModel to be used by this calculator
         */
        public CalcPanel(CalcModel model)
        {
            super();
            this.model = model;
            model.addObserver(this);
        }
        
        /**
         * Creates a button for the calculator's button panel
         * and intializes the appropriate event handlers
         * 
         * @param label     the text label for the new button.
         */
        protected JButton addButton(String label)
        {
            JButton b = new JButton(label);
            b.addActionListener(this);
            return b;
        }
        
        /**
         * Creates the panel which contains the calculator's buttons
         */
        protected JPanel createButtonPanel()
        {
            JPanel panel = new JPanel();
            panel.setLayout(new GridLayout(0, 4));   
            
            panel.add(addButton("1"));
            panel.add(addButton("2"));
            panel.add(addButton("3"));
            panel.add(addButton("+"));
            
            panel.add(addButton("4"));
            panel.add(addButton("5"));
            panel.add(addButton("6"));
            panel.add(addButton("-"));
            
            panel.add(addButton("7"));
            panel.add(addButton("8"));
            panel.add(addButton("9"));
            panel.add(addButton("*"));
            
            panel.add(addButton("C"));
            panel.add(addButton("0"));
            panel.add(addButton("="));
            panel.add(addButton("/"));
            
            return panel;
        }
        
        /**
         * Used to initialize the controls contained inside the CalcPanel
         */
        public void init()
        {
            this.setLayout(new BorderLayout());
           
            display.setVerticalTextPosition(JLabel.CENTER);
            display.setHorizontalTextPosition(JLabel.RIGHT);
            display.setVerticalAlignment(JLabel.TOP);
            display.setHorizontalAlignment(JLabel.TRAILING);
            display.setBorder(BorderFactory.createLineBorder(Color.black));
            
            this.add(display, BorderLayout.NORTH);
            this.add(createButtonPanel(), BorderLayout.CENTER);
        }
        
        /**
         * Event-handler used to repond to mouse clicks on the calculator's
         * buttons
         * 
         * @param evt       the event being processed
         */
        public void actionPerformed(ActionEvent evt)
        {
            System.out.println(evt.paramString());
            try {
                switch (evt.getActionCommand().charAt(0)) {
                case '+':
                    model.setOperation(CalcModel.OP_ADD);
                    break;
           
                case '-':
                    model.setOperation(CalcModel.OP_SUB);
                    break;
                    
                case '*':
                    model.setOperation(CalcModel.OP_MUL);
                    break;
                    
                case '/':
                    model.setOperation(CalcModel.OP_DIV);
                    break;
                    
                case '=':
                    model.calculate();
                    break;
                    
                case 'C':
                    model.clear();
                    break;
                    
                default:
                    model.addDigit(evt.getActionCommand());
                    break;
                }
            } catch (NumberFormatException ex) {}
        }
        
        /**
         * Update the calculator's display JLabel when the model
         * indicates that the display has changed
         * 
         * @param o       the Observable object which has changed
         * @param arg     argument passed to the notifyObservers
         *                 method
         */
        public void update(Observable o, Object arg)
        {
            display.setText(model.getValue());
        }
        
    }
    
    

Ahora le toca hacer lo mismo para las otras dos clases:

  • CalModel.java extiende la clase Observable y no implementa ningún interface. Tiene el siguiente código (también puede descargarla desde aquí: CalcModel.java):
    
    package com.devious.calculator;
    
    import java.util.Observable;
    
    /**
     * The CalcModel class serves as the "mechanics" behind our
     * calculator. It handles "presses" of the calculators "buttons",
     * performs calculators, and keeps the "display" up-to-date.
     * The CalcModel extends Observable and will notify subscribers
     * whenever the calculators display should change.
     * 
     * @author [email protected]
     */
    public class CalcModel extends Observable
    {
    	/**
    	 * No operation in progress
    	 */
        public static final int OP_NONE = 0;
        
        /**
         * Addition operation
         */
        public static final int OP_ADD  = 1;
        
        /**
         * Subtration operation
         */
        public static final int OP_SUB  = 2;
        
        /**
         * Multiplication operation
         */
        public static final int OP_MUL  = 3;
        
        /**
         * Dividion operation
         */
        public static final int OP_DIV  = 4;
        
        
        //-------------------------------------------------------------
    
    	/**
    	 * The pendingOp represents the operation that the user
    	 * is currently entering. Should be one of the OP_* constants
    	 */    
        private int pendingOp = 0;
        
        /**
         * The value previously entered by the user. Effectively, this
         * is the number the user entered before pressing one of the
         * operation (+,-,*,/) keys
         */
        private int previousValue = 0;
        
        /**
         * The number the user is currently in the process of entering
         */
        private int currentValue = 0;
        
       //-------------------------------------------------------------
       
       	/**
       	 * Returns a string representing the number the calculator
       	 * should currently display.
       	 * 
       	 * @return the String the calculator should display
       	 */
        public String getValue()
        {
            return Integer.toString(currentValue);
        }
        
        /**
         * Use this method to indicate when one of the calculator's numeric
         * "keys" has been pressed.
         * 
         * @param s     a String representing the key wich was
         *               pressed (e.g. "0");
         */
        public void addDigit(String s)
        {
            char c = s.charAt(0);
            String val = getValue() + c;
            setDisplay(Integer.parseInt(val));
        }
        
        /**
         * Use this method to indicate when one of the calculator's numeric
         * "keys" has been pressed.
         * 
         * @param c     a char representing the key wich was
         *               pressed (e.g. '0');
         */
        public void addDigit(char c)
        {
        	String val = getValue() + c;
        	setDisplay(Integer.parseInt(val));
        }
        
        /**
         * Use this method to indicate when one of the calculator's
         * operational keys have been pressed. If there is a pending
         * operation, the calculation will be performed and the
         * calculator's display will be updated.
         * 
         * @param op     one of the OP_* constants indicating which
         *                operation key was pressed
         */
        public void setOperation(int op)
        {
            // handle case where user enters multiple operations
            // without intervening '=' (e.g 1 + 1 + 1)
            if (pendingOp != OP_NONE)
                calculate();
                
            previousValue = currentValue;
            this.pendingOp = op;
            currentValue = 0;
        }
        
        /**
         * Changes the calculator's display and notifies any observers
         * of the change.
         * 
         * @param value    the new value to be displayed by the calculator
         */
        public void setDisplay(int value)
        {
            currentValue = value;
            
            setChanged();
            notifyObservers();
        }
        
        /**
         * This method can be used to "clear" the calculator. Any pending
         * operations and numeric entries are discarded. The calculator's
         * display is updated appropriately.
         */
        public void clear()
        {
            this.pendingOp = OP_NONE;
            previousValue = 0;
            setDisplay(0);   
        }
        
        /** 
         * This method is used to process a pending calculation (e.g.
         * because the equals key was pressed.
         */
        public void calculate()
        {
            switch (pendingOp)
            {
            case OP_ADD:
                setDisplay(previousValue + currentValue);
                break;
            case OP_SUB:
                setDisplay(previousValue - currentValue);
                break;
            case OP_MUL:
                setDisplay(previousValue * currentValue);
                break;
            case OP_DIV:
                setDisplay(previousValue / currentValue);
                break;
            }  
            pendingOp = OP_NONE;
            previousValue = 0;
        }
    }
    
    
  • Y la clase Calculator.java que no extiende ninguna clase ni implementa ningún interface pero si necesita un método main(). Aquí tiene su código fuente, (también puede descargarla desde aquí: Calculator.java):
    
    package com.devious.calculator;
    
    import javax.swing.*;
    import javax.swing.event.*;
    import java.awt.event.KeyEvent;
    
    /**
     * The "driver" program for our simple Swing-based calculator.
     * 
     * @author [email protected]
     */
    public class Calculator
    {
    
        public static void main(String[] args)
        {
            try {
                UIManager.setLookAndFeel(
                    UIManager.getCrossPlatformLookAndFeelClassName());
            } catch (Exception e) {}
            
            JFrame calcFrame = new JFrame("Calculator");
            
            CalcModel model = new CalcModel();        
            CalcPanel calcPanel = new CalcPanel(model);
            calcPanel.init();
                     
            calcFrame.setContentPane(calcPanel);
            calcFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            calcFrame.pack();
            calcFrame.setVisible(true);
        }
    }
    
    

Este debería ser el aspecto del explorador de paquetes después de implementar todas las clases:

La mejor forma de explorar el código es cambiar entre las perspectivas Java y Java Browsing:

Ejecutar el Código y Depurar

Hasta ahora se ha visto como descargar e instalar Eclipse, como crear un proyecto Java, como añadirle carpetas (y paquetes), y como crear clases y añadirle código. Ahora es el momento de ver la aplicación en funcionamiento. Para completar los pasos necesarios para ejecutar la aplicación es necesario utilizar la perspectiva Java.

Pulse sobre la flecha que hay a la derecha del icono del hombre corriendo y seleccione Run As > 2 Java Aplication:

Eclipse compilará automáticamente todas las clases del proyecto y nos mostrará la aplicación en ejecución:

Si juega un poco con la calculadora, verá que funciona bastante bien, pero parece tener un problema. No hace la resta! Es hora de lanzar el depurador y encontrar el problema.

Como ya se ha ejecutado la aplicación con anterioridad, debajo del botón con la araña (debug) aparecerá un lanzador para depurar la aplicación. Si no es así, siempre se puede seleccionar Debug As > 2 Java Aplication:

Si Eclipse no cambia automáticamente a la perspectiva Debug puede hacerlo manualmente desde Window > Open Perspective > Other... y seleccionando Debug:

Como el problema parece centrarse en la función de la resta, seleccione breakpoints en la clase del manejador de eventos para las teclas menos e igual. Primero, debe ir a la pestaña de edición de la clase CalcPanel. (Si no tiene abierta una pestaña para la clase CalcPanel, tendrá que volver a la perspectiva Java, abrir el fichero y luego volver a la perspectiva Debug).

Utilice la vista Outline para seleccionar el método actionPerformed. Baje algunas líneas hasta que vea la sentencia case para la tecla menos (línea 126). Si hace doble click en el margen izquierdo de esta línea, verá que Eclipse marca en ella un breakpoint. Baje un poco más y seleccione otro breakpoint en la llamada a model.calculate() en el manejador de la tecla igual (línea 138):

Ahora, cambie a la ventana de la calculadora (la aplicación que se está depurando) y pulse alguno de los botones. Algo como 2 4 6 - debería bastar para dispararlo. Una vez que el depurador alcanza el breakpoint, puede utilizar los botones de la barra de herramienta de la vista Debug para entrar, pasar o salir de los métodos:

Si selecciona el botón Step Into para entrar en el método setOperation, verá que éste sólo graba el código de la operación en el campo pendingOp. Pulse el botón Resume de la barra de herramientas de Debug para continuar la ejecución del programa.

Nota:
Un error muy común a los nuevos usuarios de Eclipse es pulsar los botones Debug o Run de la barra de herramientas principal en lugar del botón Resume. Esto lanzará otra copia de la aplicación en vez de continuar con la actual.

Ahora, pulse algunos botones más (por ejemplo, "1", "2", "3") y luego la tecla igual. Una vez dentro del método calculate, el problema es obvio: alguien copió el código de la sentencia case OP_ADD pero no editó la operación para que realizara la resta y no la suma. Problema resuelto!

Corrección de Bugs

Si ocurre que está ejecutando la aplicación sobre una JVM 1.4, tiene que realizar un paso final para depurar el ejemplo. En vez de salir de la aplicación, cambiar el código, recompilar y arrancar una nueva sesión de depurado, se puede corregir el problema al vuelo!

Con el depurador ejecutándose, corrija la línea problemática de:

setDisplay(previousValue + currentValue);

a

setDisplay(previousValue - currentValue);

Grabe el fichero, y presione el botón Resume para hacer que la aplicación se ejecute de nuevo. Utilice el botón C de la calculadora y ejecute de nuevo la misma secuencia de operaciones. Esta vez, funciona!

Lo que acabamos de probar es el soporte que da Eclipse a una nueva característica del JDK 1.4 llamada "HotSwap". La Java Platform Debugger Architecture (JPDA) ahora tiene la habilidad de sustituir código modificado en un aplicación ejecutándose (en caliente). Esto es particularmente útil cuando arrancar una aplicación, o llegar al punto donde falla lleva mucho tiempo.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR