2008-10-10 11 views
10

Je n'ai jamais vu un moyen de le faire bien, je serais intéressé de voir comment les autres le font. Actuellement, je formate comme ceci:Comment formater des méthodes avec de grandes listes de paramètres

public Booking createVehicleBooking(Long officeId, 
            Long start, 
            Long end, 
            String origin, 
            String destination, 
            String purpose,   
            String requirements, 
            Integer numberOfPassengers) throws ServiceException { 
/*..Code..*/ 
} 

Répondre

15

Un grand nombre de paramètres comme celui-ci est souvent (mais pas toujours) un indicateur que vous pourriez utiliser un objet pour représenter l'ensemble des paramètres. Cela est particulièrement vrai si:

  • Il existe plusieurs méthodes avec de grands ensembles de paramètres similaires, qui peuvent être remplacés par une seule méthode prenant un objet de paramètre.

  • La méthode est appelée create...

donc votre code ci-dessus pourrait devenir (pardonnez mon C++, je suis un développeur Java):

class BuildVehicleBooking { 
    Long officeId; 
    Long start; 
    Long end; 
    String origin; 
    String destination; 
    String purpose;    
    String requirements; 
    Integer numberOfPassengers; 

    Booking createVehicleBooking() throws ServiceException { ... } 
} 

C'est le modèle Builder . L'avantage de ce modèle est que vous pouvez construire un ensemble complexe de paramètres, y compris de multiples variations sur la façon dont les paramètres sont reliés entre eux, et même écraser les paramètres lorsque de nouvelles informations deviennent disponibles avant d'appeler finalement la méthode create .

Un autre avantage potentiel est que vous pouvez ajouter une méthode verifyParameters qui vérifie leur consistance avant d'aller jusqu'à creating l'objet final. Ceci est applicable dans les cas où la création de l'objet implique des étapes non réversibles, telles que l'écriture dans un fichier ou une base de données. Notez que, comme pour tous les modèles, cela ne s'applique pas dans tous les cas et peut ne pas s'appliquer dans les vôtres. Si votre code est assez simple, il se peut que ce modèle soit trop complexe. Si le code devient en désordre, refactoring dans ce modèle peut être un bon moyen de le simplifier.

+0

Malheureusement, je ne pense pas que je peux m'en tirer parce que c'est un point de terminaison SOAP pour un service web, mais néanmoins très instructif. – abarax

+0

Vous pouvez absolument utiliser cette technique, même pour les services Web. Vous devez rendre votre classe sérialisable, et potentiellement déployer le schéma en fonction de ce que vous utilisez pour héberger des services Web (axe, par exemple exigera que je crois, alors qu'asp.net le gérera pour vous) – Jeremy

+1

Le modèle de générateur est utile, bon conseil! Pour une domination totale du monde (sécurité du thread), assurez-vous que la méthode create copie tous les paramètres avant de les valider. (Aussi, astuces mineures: utilisez long au lieu de Lon, int au lieu de Integer et fournissez des méthodes getter/setter.) – volley

8
public Booking createVehicleBooking(
    Long officeId, 
    Long start, 
    Long end, 
    String origin, 
    String destination, 
    String purpose,     
    String requirements, 
    Integer numberOfPassengers) 

throws ServiceException { 
/*..Code..*/ 
} 
+0

S'il y a plusieurs exceptions levées, est-ce que vous les lignez verticalement? –

+0

Chris - dépend de combien. Si c'est suffisant pour que ça coule du côté de l'écran, oui. La règle générale est: si elle s'écoule du côté, alignez-les. Si le nom de la fonction est trop long, imbriquez et indentez. –

+1

c'est plutôt sympa. le seul changement que je ferais est de déplacer la parenthèse fermante sur la même ligne que le "jette", de sorte que vous puissiez facilement voir que cela fait partie d'une déclaration plus large. – nickf

3

Je suis enclin à le faire avec plusieurs objets au lieu d'un seul.

Ainsi, il devient

public Booking createVehicleBooking(Long officeId, DateRange dates, TripDetails trip) 

Alors que DateRange et les détails de voyage ne contiennent que les parties pertinentes des données. Bien que sans doute le dateRange pourrait faire partie du voyage tandis que les exigences et le nombre de passagers pourraient être retirés de TripDetails et fait partie de la demande. En fait, il existe plusieurs façons de découper les données, mais je dois dire que le découpage de votre grande liste en groupes de paramètres associés et la construction d'un objet pour eux permettront un style de programmation plus clair et augmenteront la réutilisation possible.

Et rappelez-vous, il est toujours possible d'incruster des objets en objets vous permettant ainsi d'avoir

public Booking createVehicleBooking(BookingParameters parameters) 

Bien que BookingParameters Contient TripDetails et objets DateRange ainsi que les autres paramètres.

+0

Cette question concerne le formatage. (Parfois vous avez besoin de travailler avec la base de code que vous avez donnée avant de refactoriser ;-) –

2

Du côté appelant j'aime simuler des paramètres nommés en utilisant des commentaires comme celui-ci:

booking.createVehicleBooking(
    getOfficeId(),  // Long officeId 
    startVariable,  // Long start 
    42,     // Long end 
    getOrigin(),  // String origin 
    "destination",  // String destination 
    "purpose",   // String purpose  
    "requirements",  // String requirements 
    3     // Integer numberOfPassengers 
); 
1

J'aime une approche par param ligne que vous montrez. Je trouve qu'il est très facile de le scanner visuellement et de voir ce qui est présent.

Je trouve que lorsque les gens utilisent quelque chose comme Guice, vous vous retrouvez souvent avec un grand nombre de paramètres, ce qui facilite la lecture.

+0

Si vous avez une autre question, posez-la en cliquant sur le bouton [Poser une question] (// stackoverflow.com/questions/ask). – manetsus

+0

Manetsus, quelle partie de mon texte vous fait penser que c'est une question? Je soulignais qu'il y a un certain nombre de bibliothèques tierces qui finissent par appeler avec de nombreux paramètres où avoir une liste verticale de paramètres le rend plus facile à lire. – Evvo

1

Le Google Java Style Guide ne répond pas directement, mais je suis d'accord avec la façon dont ils ont mis en forme des choses dans Goyave, à savoir

En com.google.common.collect.Collections2.transform:

public static <F, T> Collection<T> transform(
    Collection<F> fromCollection, Function<? super F, T> function) { 
    return new TransformedCollection<>(fromCollection, function); 
} 

Dans com.google.common.collect.ImmutableRangeMap.toImmutableRangeMap

public static <T, K extends Comparable<? super K>, V> 
    Collector<T, ?, ImmutableRangeMap<K, V>> toImmutableRangeMap(
     Function<? super T, Range<K>> keyFunction, 
     Function<? super T, ? extends V> valueFunction) { 
    return CollectCollectors.toImmutableRangeMap(keyFunction, valueFunction); 
} 

I pense que les règles sont:

  • (Essayez de le garder sur une ligne si possible)
  • Pause après le nom de la méthode et croisillon
  • Indentation les paramètres d'un niveau supplémentaire pour les distinguer du corps

Personnellement, je préfère briser après chaque paramètre si je dois rompre du tout, par exemple

public static Foo makeFoo(
    Foo foo, 
    Bar bar, 
    Baz baz) 
     throws FooException { 
    f(); 
} 
Questions connexes