2010-05-29 13 views
7

Estoy trabajando duro en el empaquetado de una API para el consumo público. Como tal, trato de limitar los métodos que están expuestos solo a aquellos que deseo que sean públicos y compatibles. Debajo de esto, por supuesto, hay una multitud de métodos de acceso limitado.¿Deberían mis clases API internas ser todo en un solo paquete?

El problema es que tengo un montón de código interno que necesita acceder a estos métodos restringidos sin hacer públicos esos métodos. Esto crea dos problemas:

  • No puedo crear interfaces para comunican entre clases ya que esto haría que estos mis métodos internos públicas.
  • No puedo acceder a los métodos protegidos o predeterminados a menos que ponga la mayoría de mis clases internas en el mismo paquete .

Por lo tanto, tengo alrededor de 70 u 80 clases internas en paquetes segregados limpiamente PERO con modificadores de acceso excesivamente permisivos. ¿Diría que un solo paquete es el menor de dos males o hay una mejor manera de poder enmascarar mis métodos internos mientras se mantienen paquetes más granulares?

Estaría interesado en conocer las mejores prácticas aquí.

ya estoy al tanto de This

+0

Creo que la pregunta es un poco subjetiva: personalmente, no me gustan las decisiones de diseño que conducen a una organización interna deficiente, como el caso de todas las clases en un solo paquete. Pero la forma correcta de hacer tales cosas no se viene a la mente en este momento. – incarnate

Respuesta

7

Hay dos soluciones a su pregunta que no implican mantener todas las clases en el mismo paquete.

El primero es utilizar el patrón Friend Accessor/Friend Package descrito en (Practical API Design, Tulach 2008).

El segundo es usar OSGi. Hay un artículo here que explica cómo OSGi logra esto.

Preguntas relacionadas: 1, 2, 3 y 4.

+0

Esta es una excelente respuesta y el enlace al paquete de amigos fue la solución que estaba buscando. – Chris

+0

Me alegro de poder ayudar. Yo también necesitaba una solución a esta limitación aparentemente grave de Java. Este patrón debería ser un candidato ideal para extender Java utilizando Jetbrains MPS u otra herramienta de desarrollo impulsada por modelos. –

+0

Bueno, todavía tiene que hacer público el Accesorio abstracto interno (por lo tanto, una parte de API). Peor aún, un usuario malvado puede proporcionar su propio AccessorImpl, lo que obliga a su paquete interno a utilizar su propia API en su lugar. Esto funcionará hasta que la clase Item se inicialice y active IllegalStateException. – charlie

2

Un ejemplo podría ser el Servlet API como ves se han separado API servlet HTTP común y en dos paquetes.

Si separa el código en api.jar y implementation.jar, podría utilizar interfaces para su implementación que no sean visibles para los usuarios de api.jar. Si los objetos de las clases, independientemente de su paquete, tienen que colaborar de alguna manera, los métodos, por supuesto, deben ser visibles (al menos en la implementación).

+0

+1 Gracias por la información. Soy consciente de que puedo empaquetar el problema pero realmente deseo restringir a los usuarios que tienen la API y los archivos de implementación de poder acceder a los métodos de implementación que no son de interfaz de una manera no intencionada. – Chris

1

sí, simplemente no puede proteger el acceso interno a las cosas de implementación. Hay algunas tecnologías (como OSGi), que ofrecen una solución a eso durante el inicio del tiempo de ejecución/aplicación. Esta es una falla de modularización del diseño del lenguaje java (pero también muy difícil de agregar después debido a la baja compatibilidad).

me gusta la convención para agregar artefactos visibles públicamente a /api paquete y el funcionamiento interno de / interna. Al final terminas con.

 

# this package is allowed to be accessed by api-users 
com.foo.users.api 
# this is completely internal logic (api implementation) 
# should only be touched by the api-module itself. 
com.foo.users.internal 
 

De esta manera tiene una separación limpia y también puede ejecutar reglas de código de análisis de código estático.

Al igual que con servlet-api mencionado anteriormente, puede dividir api vs impl en diferentes jarrones. Pero esto implica un mayor esfuerzo para construir el ciclo de vida y mantener los módulos, por lo que solo lo haría allí donde tenga sentido una división completa de artefactos en tiempo de ejecución (como en jsr-spec vs. impl).

Cuestiones relacionadas