¿Es excesivo encerrar una colección en una clase simple solo para una mejor lectura?

15

Tengo el siguiente mapa:

Map<Double, List<SoundEvent>> soundEventCells = new HashMap<Double, List<SoundEvent>>();

Este HashMap asigna los valores de double (que son puntos en el tiempo) al correspondiente SoundEvent 'celda': cada 'celda' puede contener un número de SoundEvent s. Por eso se implementó como List<SoundEvent> , porque eso es exactamente lo que es.

En aras de una mejor legibilidad del código, pensé en implementar una clase interna estática muy simple como:

private static class SoundEventCell {
    private List<SoundEvent> soundEvents = new ArrayList<SoundEvent>();
    public void addEvent(SoundEvent event){
        soundEvents.add(event);
    }
    public int getSize(){
        return soundEvents.size();
    }
    public SoundEvent getEvent(int index){
        return soundEvents.get(index);
    }
    // .. remove() method unneeded
}

Y que la declaración del mapa (y muchos otros códigos) se vería mejor, por ejemplo:

Map<Double, SoundEventCell> soundEventCells = new HashMap<Double, SoundEventCell>();

¿Esto es una exageración? ¿Harías esto en tus proyectos?

    
pregunta Aviv Cohn 17.09.2014 - 16:32
fuente

4 respuestas

12

No es una exageración en absoluto. Comience con las operaciones que necesita, en lugar de comenzar con "Puedo usar un HashMap". A veces, un HashMap es justo lo que necesitas.
En tu caso sospecho que no lo es. Lo que probablemente quieras hacer es algo como esto:

public class EventsByTime {
    public EventsByTime addEvent(double time, SoundEvent e);
    public List<SoundEvent> getEvents(double time);
    // ... more methods specific to your use ...
}

Definitivamente no quieres tener un montón de código diciendo esto:

List<SoundEvent> events = eventMap.get(time);
if (events == null) {
   events = new ArrayList<SoundEvent>();
   eventMap.put(time, events);
}

O tal vez podría usar uno de los Guimoto Multimap implementaciones.

    
respondido por el kevin cline 17.09.2014 - 23:28
fuente
13

Aunque puede ayudar en la legibilidad en algunas áreas, también puede complicar las cosas. Personalmente, me alejo de envolver o extender las colecciones en aras de la fluidez, ya que la nueva envoltura, en la lectura inicial, me indica que puede haber un comportamiento que debo tener en cuenta. Considéralo un tono de Principio de Menos Sorpresa.

Mantener la implementación de la interfaz significa que solo debo preocuparme por la interfaz. La implementación concreta puede, por supuesto, albergar un comportamiento adicional, pero no debería tener que preocuparme por ello. Entonces, cuando trato de encontrar mi camino a través del código de alguien, prefiero las interfaces simples para facilitar la lectura.

Si, por otro lado, está encontrando un caso de uso que se beneficia de un comportamiento agregado, entonces tiene un argumento para mejorar el código creando una clase completa.

    
respondido por el FeedbackLoop 17.09.2014 - 17:07
fuente
2

Envolviéndolo, limita su funcionalidad a solo aquellos métodos que decida escribir, básicamente incrementando su código sin ningún beneficio. Como mínimo, intentaría lo siguiente:

private static class SoundEventCell : List<SoundEvent>
{
}

Aún puedes escribir el código de tu ejemplo.

Map<Double, SoundEventCell> soundEventCells = new HashMap<Double, SoundEventCell>();

Dicho esto, solo he hecho esto cuando hay alguna funcionalidad que la lista necesita. Pero creo que tu método sería excesivo para esto. A menos que haya un motivo para querer limitar el acceso a la mayoría de los métodos de List.

    
respondido por el Lawtonfogle 17.09.2014 - 22:15
fuente
-1

Otra solución podría ser definir su clase contenedora con un solo método que exponga la lista:

private static class SoundEventCell
{
    private List<SoundEvent> events;

    public SoundEventCell(List<SoundEvent> events)
    {
        this.events = events;
    }

    public List<SoundEvent> getEvents()
    {
        return events;
    }
}

Esto le da a su clase bien nombrada con un código mínimo, pero aún así le da encapsulación, lo que le permite, por ejemplo, haga que la clase sea inmutable (haciendo una copia defensiva en el constructor y utilizando Collections.unmodifiableList en el descriptor de acceso).

(Sin embargo, si estas listas solo se usan en esta clase, creo que sería mejor reemplazar su Map<Double, List<SoundEvent>> con un Multimap<Double, SoundEvent> ( docs ), ya que a menudo ahorra mucha lógica de comprobación de nulos y errores.)

    
respondido por el MikeFHay 17.09.2014 - 23:14
fuente

Lea otras preguntas en las etiquetas