Plataforma Eclipse
Reglas de compromiso de API
Versión 0.15 - Última revisión 12:00 May 30, 2001
Estas son las reglas de compromiso para los clientes del API de la plataforma Eclipse (y otros componentes).
Qué significa ser API
La plataforma Eclipse define elementos API para su utilización por sus clientes, denominados plug-ins de escritura de ISV. Estos plug-ins pueden a su vez definir elementos API para sus clientes, y así sucesivamente. Los elementos API son la expresión pública: especifican lo que se supone que harán, y cómo se supone que serán utilizados. Se proporciona soporte a los elementos API: el equipo de la plataforma Eclipse solventará los problemas de implementación allí donde se produzca una desviación del funcionamiento especificado. Como siempre se asocia un alto coste a los cambios sustancialesdel API, el equipo de la plataforma Eclipse intentará asimismo una cuidadosa evolución de los elementos de API en los releases principales y consecutivos.
Cómo distinguir API de no-API
Por su naturaleza misma, los elementos API están documentados y tienen una especificación, al contrario de los elementos no-API, que son detalles de implementación interna por regla general sin documentación publicada ni especificaciones. Así pues, si no puede encontrarse la documentación de algo, es un buen indicador de que no es API.
Para intentar una distinción más clara, observemos que el código base para la plataforma está separado en paquetes de API y de no-API, con todos los elementos API convenientemente declarados en los paquetes de API designados.
-
Paquete de API - paquete de Java que contiene al menos una clase de API o un interfaz de API. Los nombres de los paquetes de API están anunciados en la documentación de ese componente; donde sea viable, el resto de paquetes conteniendo únicamente detalles de implementación muestran "internal" en el nombre del paquete. Los nombres de paquetes de API pueden aparecer legítimamente en el código cliente. Los nombres válidos para la plataforma Eclipse son:
-
org.eclipse.foo.* - por ejemplo, org.eclipse.swt.widgets,
org.eclipse.ui,
o org.eclipse.core.runtime
-
org.eclipse.foo.internal.* - no API; paquetes de implementación internos
-
org.eclipse.foo.examples.* - no API; son ejemplos
-
org.eclipse.foo.tests.* - no API; son juegos de prueba
-
Clase o interfaz de API - clase o interfaz pública en un paquete de API, o un miembro de clase o interfaz público o protegido declarado en, o heredado por algún otra clase o interfaz de API.
Los nombres de clases e interfaces de API pueden aparecer legítimamente en el código cliente.
-
método o constructor API - método o constructor público o protegido
declarado en, o heredado por una clase o interfaz de API. Los nombres de los métodos de API pueden aparecer legítimamente en el código cliente.
-
campo de API - campo público o protegido declarado en, o heredado por una clase o interfaz de API. Los nombres de los campos de API pueden aparecer legítimamente en el código cliente.
El resto se consideran detalles de implementación interna y zona prohibida para todos los clientes. El código de cliente legítimo nunca debe mencionar los nombres de los elementos no API (incluso utilizando reflejo de Java). En algunos casos, las reglas de accesibilidad al nombre del lenguaje Java se utilizan para anular referencias ilegales.
Sin embargo, en muchos casos esto es sencillamente imposible. La observación de esta sencilla regla evita por completo el problema:
-
Limítese a los API documentados oficialmente. Consulte únicamente los paquetes que estén documentados en el Javadoc de API publicado del componente.
Nunca mencione un paquete que pertenezca a otro componente que muestre "interno"
en su nombre---pues éstos jamás son API. Nunca mencione un paquete para el que no exista un API Javadoc publicado---éstos tampoco son API.
Reglas generales
Los comentarios del Javadoc en el código fuente del elemento de Java generan la especificación de los elementos API. Para algunos tipos de elementos, la especificación es en forma de contrato. Por ejemplo, en el caso de los métodos, el contrato es entre dos partes, el que llama al método y el que lo implementa. La directriz fundamental es:
-
Cumplir con todos los contratos. Los contratos se describen en el Javadoc publicado para los elementos API que esté utilizando.
El término "debe", cuando se utiliza en un contrato de API, significa que es incumbencia de la parte el asegurar que la condición se cumplirá; cualquier incumplimiento será considerado un error de programación con consecuencias inespecíficas (y quizás imprevisibles).
-
Debe respetar el término "debe". Preste especial atención a las condiciones donde se utilice el término "debe".
Otras reglas de sentido común:
-
No confíe en comportamientos imprevistos. El comportamiento secundario es una conducta observada al experimentar o en la práctica, pero no está garantizado por ninguna especificación de API.
-
No trate el carácter nulo como objeto. Nulo significa más bien la ausencia de un objeto. Asuma todo como nulo excepto cuando la especificación de API diga lo contrario.
-
No intente hacer trampas con el reflejo de Java. Utilizar el reflejo de Java para burlar la comprobación del compilador de Java no le aporta ningún beneficio. A efectos del reflejo no existen los contratos adicionales de API; el reflejo sencillamente aumenta la posibilidad de confiar en comportamientos inespecíficos y en detalles de implementación interna.
-
Utilice sus propios paquetes. No declare su código en un paquete que corresponda a otro componente. Declare siempre su propio código en sus propios paquetes.
Llamada a métodos de API públicos
Para la mayoría de clientes, la mayor parte del API de Eclipse es en forma de métodos públicos sobre interfaces o clases API, proporcionados para que el usuario los llame cuando sea conveniente.
-
Asegurar las precondiciones. Asegúrese que se cumplan las precondiciones del método de API antes de llamar al método. A la inversa, el que efectúa la llamada puede asumir con seguridad que las condiciones posteriores del método habrán sido archivadas inmediatamente después de la respuesta.
-
Parámetros nulos. No pase nulo como un parámetro a un método de API a menos que el parámetro documente explícitamente que lo permite. Este quizás sea el error de programación que se da con más frecuencia.
-
LLamadas restringidas. No efectúe llamadas a un método de API que esté documentado como disponible únicamente para ciertas personas a menos que sea uno de ellos. En algunas situaciones, los métodos requieren formar parte del API público para beneficiar cierta clase de personas (a menudo interna); llamar a uno de estos métodos en un momento inadecuado tiene consecuencias indeterminadas(y quizás imprevisibles).
-
Métodos de depuración. No efectúe llamadas a aquel método de API etiquetado "sólo para depurar". Por ejemplo, la mayoría de los métodos toString() se encuentran en esta categoría.
-
Captura de parámetros No pase como parámetro una matriz, colección u otro objeto mutable a un método de API y a continuación modifique el objeto pasado. Esto es simplemente un modo de buscar problemas.
Creación de instancias de clases API de la plataforma
No es intención de todas las clases de API concretas el poder recibir instancias por parte de cualquiera.
Las clases de API están sujetas a un contrato de recepción de instancias que indica los términos bajo los cuales puede crearse una instancia. El contrato puede asimismo cubrir cosas tales como las responsabilidades residuales de inicialización (por ejemplo, configurar una cierta propiedad antes de que la instancia esté plenamente activa) y responsabilidades respecto del ciclo vital asociado (por ejemplo, efectuar llamadas dispose() para liberar recursos del sistema operativo que la instancia había suspendido. Las clases diseñadas para que los clientes efectúen instancias están explícitamente marcadas en el Javadoc comentario de clases (con frases del tipo "Los clientes pueden crear instancias").
-
Instancias restringidas. No cree instancias a una clase de API documentada como únicamente disponible para ciertos grupos, a menos que usted sea uno de ellos.
En algunos casos, las clases requieren formar parte del API público para beneficio de cierto grupo (a menudo interno); efectuar una instancia a una de esas clases incorrectamente tendrá consecuencias indeterminadas (y quizás imprevisibles).
Creación de subclases de clases del API de la plataforma
Únicamente un subconjunto de las clases API están diseñadas para permitir la creación de subclases. Las clases API están sujetas a un contrato que indica los términos bajo los cuales pueden declararse subclases. Este contrato también cubre las responsabilidades de inicialización y de ciclo vital. Las clases diseñadas para que los clientes creen subclases están marcadas explícitamente en el Javadoc de comentario de clase (con frases del tipo "Los clientes pueden crear subclases").
-
Subclases restringidas. No cree subclases de una clase API que no tenga intención de ser subclase. Trate estas clases como si estuvieran declaradas como finales. (Éstas son referidas a veces como clases de "final suave").
Llamada a métodos de API protegidos
Efectuar llamadas a métodos públicos protegidos y heredados desde una subclase está por lo general permitido; no obstante, esto requiere más cuidado en la corrección de la llamada que las llamadas a métodos públicos externas a la jerarquía.
Alteración de métodos de API
Únicamente un subconjunto de los métodos API públicos y protegidos están diseñados para permitir su alteración. Cada método de API posee un contrato de subclase indicando los términos bajo los cuales una subclase lo puede alterar. Por omisión, no se permite la alteración.
Es importante comprobar el contrato de subclase de la implementación de método que se vaya a alterar; los términos de contratos de subclase no son pasados por alto automáticamente al alterar tal método.
-
No altere un método de API público o protegido a menos que esté explícitamente permitido. Salvo que se indique lo contrario, trate todos los métodos como si hubieran sido declarados finales. (Éstos son referidos algunas veces como métodos de "final suave").
Si el tipo de alteración permitido es:
"implementar" - el método abstracto declarado en la subclase debe ser implementado por una subclase en particular.
"ampliar" - el método declarado en la subclase debe invocar al método de la superclase (exactamente una vez).
"reimplementar" - el método declarado en la subclase no debe invocar al método de la superclase
"alterar" - el método declarado en la subclase es libre de invocar al método de la superclase si lo considera oportuno
-
Asegurar las condiciones a posteriori. Asegúrese de que la implementación cumpla toda condición posterior especificada por el método API.
-
Comprobación exhaustiva de las precondiciones. No dé por sentado que las precondiciones especificadas para el método API se hayan cumplido al entrar. Aunque la implementación del método esté en su derecho de no comprobar las precondiciones especificadas, es por regla general una buena idea el comprobarlas (cuando sea viable y razonablemente económico) para que avise ante llamadas incorrectas.
-
Resultado nulo. No devuelva como nulo como resultado de un método de API a menos que el resultado esté documentado explícitamente (en el interfaz o superclase especificado) como que permite nulo.
-
Emisión de copias. No emita como resultado de un método de API una matriz, colección u otro objeto mutable que sea irreemplazable. Emita siempre una copia para evitar problemas ocasionados por llamadas que podrían modificar el objeto.
Implementar interfaces de API de plataforma
Sólo un subconjunto de los interfaces API están diseñados para permitir ser implementados por los clientes. Los interfaces API poseen un contrato que indica los términos bajo los cuales se pueden implementar. Los interfaces diseñados para ser implementados por los clientes están marcados explícitamente en el Javadoc de comentario de clase (con frases del tipo "Implementable por clientes"). Un cliente puede declarar un subinterfaz de un interfaz API solamente si le está permitido implementarlo.
-
Implementaciones restringidas. No implemente un interfaz API documentado como únicamente disponible para ciertas personas, a menos que sea una de ellas. En muchos casos, los interfaces son utilizados para ocultar a la vista detalles de implementación interna.
Implementar métodos de API públicos
Consulte "Alteración de métodos de API".
Acceso a campos de clases e interfaces API
Los clientes pueden leer campos de API, la mayoría de los cuales son finales. Ciertos objetos de estructura semejante pueden tener campos públicos no finales, en los cuales los clientes pueden leer y escribir a menos que se indique lo contrario.
-
Campos nulos. No establezca como nulo un campo de API a menos que esté explícitamente permitido.
Formular objetos de un tipo conocido de API
Un objeto de un tipo de API conocido puede ser formulado para un tipo de API diferente únicamente (o lanzado condicionalmente utilizando instanceof) si ello es permitido explícitamente en el API.
-
Formulación e instanceof. No utilice las expresiones instanceof y formular para aumentar lo que se conoce acerca de un objeto más allá de lo soportado por el API. Su uso inadecuado pone al descubierto detalles de implementación incidental no garantizados por el API.
Y, por supuesto, formular cualquier objeto para una clase o interfaz no-API es siempre inapropiado.
No cumplir las reglas
Transgredir las reglas, consciente o inconscientemente, trae consecuencias. Sería más fácil para todos los implicados que existiese una policía del API que pudiera detenerte por infringir las reglas. Sin embargo, éste no es el caso.
Para la mayoría de las partes, el API opera conforma a un sistema basado en el honor, por lo que cada cliente es responsable de conocer las reglas y aceptarlas.
Los contratos de los elementos API delimitan el comportamiento soportado y sostenido. A medida que la plataforma Eclipse madura y evoluciona, serán los contratos de API quienes guíen el desarrollo de esta evolución. Fuera de estos contratos, todo es no soportado y sujeto a cambios, sin aviso, y en cualquier momento (incluso entre releases o entre plataformas de sistemas operativos diferentes). El código cliente que sobrepase las reglas anteriores puede fallar en versiones diferentes y niveles de parcheado de la plataforma; o cuando se ejecuta en distintos sistemas operativos subyacentes; o cuando se ejecuta con una mezcla distinta de plug-ins corresidentes; o cuando se ejecuta con una perspectiva de entorno de trabajo diferente; y así sucesivamente. En efecto, nadie está interesado particularmente en especular exactamente cómo una transgresión especial puede afectarle. Para aquellos que eligen ignorar las reglas, que no digan que no se les advirtió. Y que no esperen mucho más que un cordial "Te lo dije".
Por otro lado, el código del plug-in cliente que se rige por las reglas anteriores debería continuar trabajando en las diferentes versiones y niveles de parcheado de la plataforma, atravesando los diferentes sistemas operativos subyacentes, y debería coexistir pacíficamente con otros plug-ins. Si todo el mundo cumple las reglas, la plataforma Eclipse proporcionará una base estable y soportada en la cual construir nuevos y excitantes productos.