Concatenando mensajes de retroalimentación múltiple -- java campo con strings campo con formatting campo con optional camp codereview Relacionados El problema

Concatenating multiple feedback messages


5
vote

problema

Español

El objetivo es construir un String de un conjunto dado donde Feedback5 es una interfaz y 9988776655544336 , y ProductFeedback Son sus clases de implementación.

  private void formatOrderFeedbackZendeskBody(final ImmutableSet<Feedback> feedback) {     StringBuilder feedbackMessage = new StringBuilder("The feedback: ");     feedback.forEach(                     f -> {                         if (f instanceof DeliveryFeedback) {                             feedbackMessage                                     .append("  Type: ")                                     .append(FeedbackType.DELIVERY)                                     .append(" Reason(s):  ")                                     .append(                                             ((DeliveryFeedback) f)                                                     .getReasons()                                                     .stream()                                                     .map(Reason::name)                                                     .collect(joining("    ")));                             if (((DeliveryFeedback) f).getComment().isPresent()) {                                 feedbackMessage                                         .append(" Comment: ")                                         .append(((DeliveryFeedback) f).getComment().get());                             }                         } else if (f instanceof ProductFeedback) {                             feedbackMessage                                     .append("  Type: ")                                     .append(FeedbackType.PRODUCT)                                     .append(" Reason(s):  ")                                     .append(                                             ((ProductFeedback) f)                                                     .getReasons()                                                     .stream()                                                     .map(                                                             ProductFeedbackInterface.Reason                                                                     ::name)                                                     .collect(joining("    ")))                                     .append(" Article ID: ")                                     .append(((ProductFeedback) f).getArticleId());                             if (((ProductFeedback) f).getImageIds().isEmpty()) {                                 feedbackMessage.append(                                         " No images available.");                             } else {                                 feedbackMessage                                         .append(" Image URLs: ")                                         .append(                                                 ((ProductFeedback) f)                                                         .getImageIds()                                                         .stream()                                                         .collect(joining(", ")));                             }                             if (((ProductFeedback) f).getComment().isPresent()) {                                 feedbackMessage                                         .append(" Comment: ")                                         .append(((ProductFeedback) f).getComment().get());                             }                         }                      }); }   

Estoy obteniendo el 9988776655544339 :

  #include <stdlib.h> /* malloc(), EXIT_SUCCESS */ #include <stdio.h> /* fprintf */ #include <stddef.h> /* size_t */  struct Coordinate {     int x;     int y; };  struct Queue_node {     struct Queue_node *next; };  struct Queue {     struct Queue_node *front;     struct Queue_node *back;      size_t size; };  struct Queue* create_queue(void) {      struct Queue *created_queue = malloc(sizeof(*created_queue));      if (created_queue == NULL) {         return NULL;     }      created_queue->back = NULL;     created_queue->front = NULL;     created_queue->size = 0;      return created_queue; }  void destroy_queue(struct Queue *input_queue, void (*delete_node)(void*)) {      while (input_queue->front != NULL) {          struct Queue_node *deleted_node = input_queue->front;         input_queue->front = input_queue->front->next;         if (delete_node != NULL) {             delete_node(deleted_node);         }     }     free(input_queue); }  void queue_push(struct Queue *input_queue, void *input_node) {      ++input_queue->size;      if (input_queue->front == NULL) { // first insert          input_queue->front = (struct Queue_node*) input_node;         input_queue->back = (struct Queue_node*) input_node;          return;     }      input_queue->back->next = (struct Queue_node*) input_node;     input_queue->back = input_queue->back->next; }  void* queue_pop(struct Queue* input_queue) {      if (input_queue->front == NULL) { // empty queue         return NULL;     }      --input_queue->size;      struct Queue_node *deleted_node = input_queue->front;     input_queue->front = input_queue->front->next;      return deleted_node; }  /* nodes that are queue_pop()'d must be free()'d by caller */  static struct Weighted_coord_node {     struct Queue_node *next;     // parent property      int weight;     struct Coordinate coord;     // child properties };  static struct Weighted_coord_node* create_node(struct Coordinate coord, int weight) {      struct Weighted_coord_node *node = malloc(sizeof(*node));      if (node == NULL) {         return NULL;     }     node->next = NULL;     node->coord = coord;     node->weight = weight;      return node; }  int main() {      struct Queue *my_queue = create_queue();     if (!my_queue) {         return EXIT_FAILURE;     }      struct Weighted_coord_node *my_node;          my_node = create_node((struct Coordinate){5,5}, 0);     if (!my_node) {         return EXIT_FAILURE;     }     queue_push(my_queue, my_node);      my_node = create_node((struct Coordinate){7,7}, 2);     if (!my_node) {         return EXIT_FAILURE;     }     queue_push(my_queue, my_node);      my_node = create_node((struct Coordinate){11,11}, 5);     if (!my_node) {         return EXIT_FAILURE;     }     queue_push(my_queue, my_node);      while (my_node = queue_pop(my_queue)) {         fprintf(stderr, "POP->  X: %i, Y:%i   weight: %i ", my_node->coord.x, my_node->coord.y, my_node->weight);         free(my_node);     }      destroy_queue(my_queue, free);      return EXIT_SUCCESS; } 0  

Solo pienso que este código no es muy legible y tal vez haya otra mejor manera de hacer esto que me falta :)

Editar 1: Solo para aclarar, el uso de la interfaz #include <stdlib.h> /* malloc(), EXIT_SUCCESS */ #include <stdio.h> /* fprintf */ #include <stddef.h> /* size_t */ struct Coordinate { int x; int y; }; struct Queue_node { struct Queue_node *next; }; struct Queue { struct Queue_node *front; struct Queue_node *back; size_t size; }; struct Queue* create_queue(void) { struct Queue *created_queue = malloc(sizeof(*created_queue)); if (created_queue == NULL) { return NULL; } created_queue->back = NULL; created_queue->front = NULL; created_queue->size = 0; return created_queue; } void destroy_queue(struct Queue *input_queue, void (*delete_node)(void*)) { while (input_queue->front != NULL) { struct Queue_node *deleted_node = input_queue->front; input_queue->front = input_queue->front->next; if (delete_node != NULL) { delete_node(deleted_node); } } free(input_queue); } void queue_push(struct Queue *input_queue, void *input_node) { ++input_queue->size; if (input_queue->front == NULL) { // first insert input_queue->front = (struct Queue_node*) input_node; input_queue->back = (struct Queue_node*) input_node; return; } input_queue->back->next = (struct Queue_node*) input_node; input_queue->back = input_queue->back->next; } void* queue_pop(struct Queue* input_queue) { if (input_queue->front == NULL) { // empty queue return NULL; } --input_queue->size; struct Queue_node *deleted_node = input_queue->front; input_queue->front = input_queue->front->next; return deleted_node; } /* nodes that are queue_pop()'d must be free()'d by caller */ static struct Weighted_coord_node { struct Queue_node *next; // parent property int weight; struct Coordinate coord; // child properties }; static struct Weighted_coord_node* create_node(struct Coordinate coord, int weight) { struct Weighted_coord_node *node = malloc(sizeof(*node)); if (node == NULL) { return NULL; } node->next = NULL; node->coord = coord; node->weight = weight; return node; } int main() { struct Queue *my_queue = create_queue(); if (!my_queue) { return EXIT_FAILURE; } struct Weighted_coord_node *my_node; my_node = create_node((struct Coordinate){5,5}, 0); if (!my_node) { return EXIT_FAILURE; } queue_push(my_queue, my_node); my_node = create_node((struct Coordinate){7,7}, 2); if (!my_node) { return EXIT_FAILURE; } queue_push(my_queue, my_node); my_node = create_node((struct Coordinate){11,11}, 5); if (!my_node) { return EXIT_FAILURE; } queue_push(my_queue, my_node); while (my_node = queue_pop(my_queue)) { fprintf(stderr, "POP-> X: %i, Y:%i weight: %i ", my_node->coord.x, my_node->coord.y, my_node->weight); free(my_node); } destroy_queue(my_queue, free); return EXIT_SUCCESS; } 1 es solo para dar un tipo:

  #include <stdlib.h> /* malloc(), EXIT_SUCCESS */ #include <stdio.h> /* fprintf */ #include <stddef.h> /* size_t */  struct Coordinate {     int x;     int y; };  struct Queue_node {     struct Queue_node *next; };  struct Queue {     struct Queue_node *front;     struct Queue_node *back;      size_t size; };  struct Queue* create_queue(void) {      struct Queue *created_queue = malloc(sizeof(*created_queue));      if (created_queue == NULL) {         return NULL;     }      created_queue->back = NULL;     created_queue->front = NULL;     created_queue->size = 0;      return created_queue; }  void destroy_queue(struct Queue *input_queue, void (*delete_node)(void*)) {      while (input_queue->front != NULL) {          struct Queue_node *deleted_node = input_queue->front;         input_queue->front = input_queue->front->next;         if (delete_node != NULL) {             delete_node(deleted_node);         }     }     free(input_queue); }  void queue_push(struct Queue *input_queue, void *input_node) {      ++input_queue->size;      if (input_queue->front == NULL) { // first insert          input_queue->front = (struct Queue_node*) input_node;         input_queue->back = (struct Queue_node*) input_node;          return;     }      input_queue->back->next = (struct Queue_node*) input_node;     input_queue->back = input_queue->back->next; }  void* queue_pop(struct Queue* input_queue) {      if (input_queue->front == NULL) { // empty queue         return NULL;     }      --input_queue->size;      struct Queue_node *deleted_node = input_queue->front;     input_queue->front = input_queue->front->next;      return deleted_node; }  /* nodes that are queue_pop()'d must be free()'d by caller */  static struct Weighted_coord_node {     struct Queue_node *next;     // parent property      int weight;     struct Coordinate coord;     // child properties };  static struct Weighted_coord_node* create_node(struct Coordinate coord, int weight) {      struct Weighted_coord_node *node = malloc(sizeof(*node));      if (node == NULL) {         return NULL;     }     node->next = NULL;     node->coord = coord;     node->weight = weight;      return node; }  int main() {      struct Queue *my_queue = create_queue();     if (!my_queue) {         return EXIT_FAILURE;     }      struct Weighted_coord_node *my_node;          my_node = create_node((struct Coordinate){5,5}, 0);     if (!my_node) {         return EXIT_FAILURE;     }     queue_push(my_queue, my_node);      my_node = create_node((struct Coordinate){7,7}, 2);     if (!my_node) {         return EXIT_FAILURE;     }     queue_push(my_queue, my_node);      my_node = create_node((struct Coordinate){11,11}, 5);     if (!my_node) {         return EXIT_FAILURE;     }     queue_push(my_queue, my_node);      while (my_node = queue_pop(my_queue)) {         fprintf(stderr, "POP->  X: %i, Y:%i   weight: %i ", my_node->coord.x, my_node->coord.y, my_node->weight);         free(my_node);     }      destroy_queue(my_queue, free);      return EXIT_SUCCESS; } 2  
Original en ingles

The goal is to build a String from a given set where Feedback is an interface and DeliveryFeedback, and ProductFeedbackare its implementing classes.

private void formatOrderFeedbackZendeskBody(final ImmutableSet<Feedback> feedback) {     StringBuilder feedbackMessage = new StringBuilder("The feedback: ");     feedback.forEach(                     f -> {                         if (f instanceof DeliveryFeedback) {                             feedbackMessage                                     .append("\n\nType: ")                                     .append(FeedbackType.DELIVERY)                                     .append("\nReason(s):  ")                                     .append(                                             ((DeliveryFeedback) f)                                                     .getReasons()                                                     .stream()                                                     .map(Reason::name)                                                     .collect(joining("\n\t\t\t")));                             if (((DeliveryFeedback) f).getComment().isPresent()) {                                 feedbackMessage                                         .append("\nComment: ")                                         .append(((DeliveryFeedback) f).getComment().get());                             }                         } else if (f instanceof ProductFeedback) {                             feedbackMessage                                     .append("\n\nType: ")                                     .append(FeedbackType.PRODUCT)                                     .append("\nReason(s):  ")                                     .append(                                             ((ProductFeedback) f)                                                     .getReasons()                                                     .stream()                                                     .map(                                                             ProductFeedbackInterface.Reason                                                                     ::name)                                                     .collect(joining("\n\t\t\t")))                                     .append("\nArticle ID: ")                                     .append(((ProductFeedback) f).getArticleId());                             if (((ProductFeedback) f).getImageIds().isEmpty()) {                                 feedbackMessage.append(                                         "\nNo images available.");                             } else {                                 feedbackMessage                                         .append("\nImage URLs: ")                                         .append(                                                 ((ProductFeedback) f)                                                         .getImageIds()                                                         .stream()                                                         .collect(joining(", ")));                             }                             if (((ProductFeedback) f).getComment().isPresent()) {                                 feedbackMessage                                         .append("\nComment: ")                                         .append(((ProductFeedback) f).getComment().get());                             }                         }                      }); } 

I am getting the expected String:

Detailed feedback:   Type: DELIVERY Reason(s):  REASON1             REASON2 Comment: another comment  Type: PRODUCT Reason(s):  REASON3             REASON4 Article ID: idsug Image URLs: idsug, dfgh Comment: comment  Type: PRODUCT Reason(s):  REASON5             REASON6             REASON7 Article ID: dfddddddddgh No images available 

I just think this code is not very readable and maybe there is another better way to do this that I am missing :)

Edit 1: Just to make clear, the usage of the OrderFeedback interface is only to give a type:

@JsonSubTypes({     @Type(name = FeedbackType.PRODUCT, value = ProductFeedback.class),     @Type(name = FeedbackType.DELIVERY, value = DeliveryFeedback.class), }) @JsonTypeInfo(include = As.PROPERTY, property = "type", use = Id.NAME) public interface OrderFeedback {} 
           
       
       

Lista de respuestas

6
 
vote
vote
La mejor respuesta
 

Fallo de polimorfismo. Determine quién es responsable de decidir cómo se supone que la producción se vea y va desde allí. Si la retroalimentación es responsable, solo implemente y sobrecargue @STUDENT_ID7 . Si la impresora es responsable, encuentre una manera de obtener la mayor parte de la información detallada en la interfaz.

  @STUDENT_ID8  

Esto está mal.

Básicamente, ¿cuál es el punto de tener la interfaz si solo va a pisar la interfaz y echar un vistazo a la clase de implementación?

por ejemplo ...

  @STUDENT_ID9  

¿Por qué el 9988777665544332020 no tiene un método 998877766554433321 ? Entonces usted podría simplemente

  @tableCourse2  
 

Polymorphism failure. Determine who is responsible for deciding what the output is supposed to look like and go from there. If the feedback is responsible, just implement and overload toString(). If the printer is responsible, find a way to get most of the detailed information into the interface.

if (f instanceof DeliveryFeedback) { } else if (f instanceof ProductFeedback) { 

This is just wrong.

Basically, what's the point of having the interface if you're just gonna side-step the interface and take a look at the implementing class?

For example...

if (((DeliveryFeedback) f).getComment().isPresent()) {     feedbackMessage             .append("\nComment: ")             .append(((DeliveryFeedback) f).getComment().get()); } if (((ProductFeedback) f).getComment().isPresent()) {     feedbackMessage             .append("\nComment: ")             .append(((ProductFeedback) f).getComment().get()); } 

Why does the Feedback interface not have a getComment method? Then you could just

feedbackMessage.append(f.getComment().map(c -> "\nComment: " + c).orElse("")); 
 
 
     
     
2
 
vote

Interfaz sobre la implementación

  @tableCourse3  

Se recomienda encarecidamente el código contra las interfaces en lugar de las implementaciones, de modo que pueda cambiar fácilmente las implementaciones cuando sea deseable, por ejemplo. Pruebas de escritura. Este método debe estar aceptando un @tableCourse4 en su lugar:

  @tableCourse5  

Confiando en @tableCourse6 ...

Si puede modificar el @tableCourse7 Implementación de su @tableCourse8 Implementar clases, debe hacerlo en su lugar. El cuerpo de @tableCourse9 puede ser tan simple como:

  @tableCourse0  

... o Métodos de construcción de salida sobrecargados

Alternativamente, puede usar los métodos sobrecargados que toman una implementación específica 998877665554433331

  @tableCourse2  

 

Interface over implementation

private void formatOrderFeedbackZendeskBody(ImmutableSet<Feedback> feedback) {     // ... } 

It's strongly recommended to code against interfaces instead of implementations, so that you can easily switch the implementations when it is desirable, e.g. writing tests. This method should be accepting a Set instead:

private void formatOrderFeedbackZendeskBody(Set<Feedback> feedback) {     // ... } 

Relying on toString()...

If you can modify the toString() implementation of your Feedback implementing classes, you should do that instead. The body of formatOrderFeedbackZendeskBody(Set) can be as simple as:

private String formatOrderFeedbackZendeskBody(final Set<Feedback> feedback) {     return feedback.stream()                     .map(Object::toString)                     .collect(Collectors.joining("\n\n", "The feedback: ", "")); } 

... or overloaded output building methods

Alternatively, you can use overloaded methods that take in a specific Feedback implementation (one of the rare cases where you'll actually want the method parameter to use the implementation), and a helper method to do the appropriate casting. It's all about managing the resolution outside of the stream-based processing. :)

private static String print(Feedback feedback) {     if (feedback instanceof DeliveryFeedback) {         return print((DeliveryFeedback) feedback);     }     if (feedback instanceof ProductFeedback) {         return print((ProductFeedback) feedback);     }     return null; // or throw an Exception? }  private static String print(DeliveryFeedback deliveryFeedback) {     // ... }  private static String print(ProductFeedback productFeedback) {     // ... }  private String formatOrderFeedbackZendeskBody(final Set<Feedback> feedback) {     return feedback.stream()                 .map(ThisClass::print)                 .collect(Collectors.joining("\n\n", "The feedback: ", "")); } 
 
 
0
 
vote

Evite la gran sangría causada por la lambda. En este caso, el uso de un bucle 9988776665544330 en un código mucho más legible.

 

Avoid the large indentation caused by the lambda. In this case, using a forloop results in much more readable code.

 
 

Relacionados problema

11  Un opcional_ref <t>  ( An optional reft ) 
omití a todos los operadores gratuitos, pero la igualdad comparaciones por la verbosidad. Me alegro de cualquier comentario y mejoras. Motivación Sé que l...

1  Manejo de múltiples operaciones de IO que devuelven valores opcionales  ( Handling multiple io operations that return optional values ) 
El siguiente código Haskell lee un documento PANDOC desde la base de datos y luego lo sirve al usuario después de realizar una transformación, después de la p...

3  Coge el primer par exitoso de una lista de mapas  ( Grab first successful pair from a list of maps ) 
Tengo una función que analiza las coordenadas geográficas a través de una lista de diferentes proveedores. En este caso quiero buscar dos direcciones. El prin...

4  Propiedad sin envoltura de fuerza como contrato  ( Force unwrapped property as a contract ) 
Tengo una clase, que está destinada a mostrar un controlador modal de pantalla completa con un conjunto de acciones (aparte de las acciones, también tiene un ...

3  Implementación simple / ingenua de la identidad y tal vez Mónad en elixir  ( Simple naive implementation of identity and maybe monad in elixir ) 
Esta es mi primera grieta en una identidad monada y una Mónada Tal vez en Elixir: sign_up_individual()4 Me gustaría ver si hay una manera de hacer que l...

3  Añadiendo dos valores en un mapa, si existen  ( Adding two values in a map if they exist ) 
Mi código se parece al código de estilo imperativo. Quiero hacer mi código más funcional. ¿Cómo puedo reescribir mi programa para que se convierta en un códig...

2  `std :: opcional` bajo C ++ 14 V1  ( Stdoptional under c14 v1 ) 
Esta es una primera versión de una implementación de std::optional se supone que se compila con C ++ 14. La interfaz pública de la clase está completa, pero...

7  Plantilla de clase para la encapsulación de las especificaciones de la hoja de datos utilizando opcionales  ( Class template for the encapsulation of datasheet specifications using optionals ) 
Hace un par de años escribí una Par de plantillas de clase para encapsular especificaciones que tienen uno o más de un mínimo, típico , y / o valor máximo , ...

5  ¿Vale la pena usar la declaración IFS OSSE como patrón opcional de Java?  ( Is it worth to use if else statement as java optional pattern ) 
Llegué a un punto mientras te refactorizaba usando Add_User3 código con opcionals java. Mientras optimiza el código se convirtió en un resultado a esto: ...

6  Implementación opcional <T>  ( Optionalt implementation ) 
Escribí una implementación ENFMPCodegenData.Empty0 en C ++ 14 para admitir el compilador Pre-C ++ 17. Diferencias a ENFMPCodegenData.Empty1 : Mi impl...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos