Supongamos que tengo un segmento de código para conectarme a internet y mostrar resultados de conexión como este:
HttpRequest* httpRequest=new HttpRequest();
httpRequest->setUrl("(some domain .com)");
httpRequest->setRequestType(HttpRequest::Type::POST);
httpRequest->setRequestData("(something like name=?&age=30&...)");
httpRequest->setResponseCallback([=](HttpClient* client, HttpResponse* response){
string responseString=response->getResponseDataString();
if(response->getErrorCode()!=200){
if(response->getErrorCode()==404){
Alert* alert=new Alert();
alert->setFontSize(30);
alert->setFontColor(255,255,255);
alert->setPosition(Screen.MIDDLE);
alert->show("Connection Error","Not Found");
}else if((some other different cases)){
(some other alert)
}else
Alert* alert=new Alert();
alert->setFontSize(30);
alert->setPosition(Screen.MIDDLE);
alert->setFontColor(255,255,255);
alert->show("Connection Error","unknown error");
}
}else{
(other handle methods depend on different URL)
}
}
el código es largo y se usa comúnmente, pero el código anterior no requiere elementos adicionales como la función personalizada y la clase (HttpRequest y Alert se proporcionan de forma predeterminada por el marco), y aunque el segmento de código es largo, es sencillo y no complejo (es largo solo porque hay paquetes de configuraciones como url, tamaño de fuente ...), y el segmento de código tiene pequeñas variaciones entre clases (por ejemplo: url, datos de solicitud, casos de manejo de código de error, manejo normal casos...)
Mi pregunta es, ¿es aceptable copiar y pegar código largo pero directo en lugar de envolverlos en una función para reducir la dependencia del código?
Alert
objetos?) Ahora imagine que tiene que encontrar cada instancia copiada de este código para corregir el error. Ahora imagine que no es usted quien tiene que hacerlo, sino un asesino de hachas loco que sabe que usted fue quien creó todas estas copias en primer lugar.Respuestas:
Debe considerar el costo del cambio. ¿Qué pasaría si quisieras cambiar cómo se hacen las conexiones? ¿Qué tan fácil sería? Si tiene una gran cantidad de código duplicado, encontrar todos los lugares que deben cambiarse puede llevar mucho tiempo y ser propenso a errores.
También debe tener en cuenta la claridad. Lo más probable es que tener que mirar 30 líneas de código no sea tan fácil de entender como una sola llamada a una función "connectToInternet". ¿Cuánto tiempo se perderá tratando de entender el código cuando sea necesario agregar una nueva funcionalidad?
Hay ciertos casos raros donde la duplicación no es un problema. Por ejemplo, si está haciendo un experimento y el código será desechado al final del día. Pero, en general, el costo de la duplicación supera el pequeño ahorro de tiempo de no tener que extraer el código en una función separada .
Consulte también /software//a/103235/63172
fuente
HttpRequest
son todas iguales " es una falacia fácil de hacer.No.
De hecho, incluso su código "simple" debe dividirse en partes más pequeñas. Al menos dos.
Uno para hacer la conexión y manejar la respuesta normal 200. Por ejemplo, ¿qué sucede si cambia de POST a PUT en algunos casos? ¿Qué sucede si está haciendo miles de millones de estas conexiones y necesita un subproceso múltiple o agrupación de conexiones? Tener el código en un solo lugar, con un argumento para el método, lo hará mucho más fácil.
Del mismo modo, otro para manejar errores. Por ejemplo, si cambia el color o el tamaño de fuente de la alerta. O tiene problemas con las conexiones intermitentes y desea registrar los errores.
fuente
No.
Para mí, el argumento decisivo es este:
Si usa un código en más de un lugar, cuando cambia, debe cambiarlo en más de un lugar o comienza a tener inconsistencias: comienzan a ocurrir "cosas extrañas" (es decir, introduce errores).
Y así debería ser más fácil refactorizar en una función.
¿Y qué les gusta cambiar a los usuarios ? Fuentes, tamaños de fuente, colores, etc., etc.
Ahora; ¿en cuántos lugares tendrá que cambiar ese mismo código para que vuelvan a tener el mismo color / fuente / tamaño? (Respuesta recomendada: solo una ).
Variación => parámetro (s) de función.
fuente
Esto realmente no tiene nada que ver con copiar y pegar. Si toma el código de otra parte, en el segundo que toma el código es su código y su responsabilidad, por lo que si lo copia o escribe completamente usted mismo no hace la diferencia.
En sus alertas, toma algunas decisiones de diseño. Lo más probable es que se tomen decisiones de diseño similares para todas las alertas. Por lo tanto, es probable que deba tener un método en algún lugar "ShowAlertInAStyleSuitableForMyApplication" o tal vez un poco más corto, y eso debería llamarse.
Tendrá muchas solicitudes http con un manejo de errores similar. Probablemente no debería duplicar el manejo de errores una y otra vez, sino extraer un manejo de errores común. Especialmente si su manejo de errores se vuelve un poco más elaborado (qué pasa con los errores de tiempo de espera, 401, etc.).
fuente
La duplicación está bien en algunas circunstancias. Pero no en este. Ese método es demasiado complejo. Hay un límite inferior, cuando la duplicación es más fácil que "factorizar" un método.
Por ejemplo:
es estúpido, solo haz a + b.
Pero cuando te vuelves un poco, un poco más complejo, entonces usualmente estás muy por encima de la línea.
debe convertirse
En su caso, veo cuatro "métodos". Probablemente en diferentes clases. Uno para realizar la solicitud, otro para obtener la respuesta, otro para mostrar errores y algún tipo de devolución de llamada para que se llame después de que la respuesta regrese para procesar la respuesta. Es probable que yo personalmente agregue una especie de "envoltorio" además de eso para facilitar las llamadas.
Al final, para hacer una solicitud web, me gustaría que una llamada se vea así:
Esa línea es la que tendría en todo mi código. Luego, cuando necesitaba hacer cambios en "cómo obtengo las cosas", podía hacerlo rápidamente, con mucho menos esfuerzo.
Esto también mantiene el código SECO y ayuda con SRP .
fuente
En un proyecto de cualquier tamaño / complejidad, quiero poder encontrar código cuando lo necesito para los siguientes propósitos:
¿No sería maravilloso unirse a un proyecto en progreso o continuar trabajando en un proyecto durante varios años y cuando una nueva solicitud para "conectarse a Internet y mostrar resultados de conexión" fuera fácil de encontrar debido a que buen diseño en lugar de confiar en hacer una búsqueda en todo el código para una httprequest? Probablemente sea más fácil encontrarlo con Google de todos modos.
No se preocupe, soy el nuevo y refactorizaré este bloque de código porque estoy muy molesto por unirme a este equipo despistado con la base de código horrible o ahora estoy bajo mucha presión como el resto de usted y simplemente lo copiará y pegará. Al menos mantendrá al jefe alejado de mí. Luego, cuando el proyecto se identifique realmente como un desastre, seré el primero en recomendar que lo reescribamos copiando y pegando la versión en el último y mejor marco que ninguno de nosotros comprende.
fuente
Una clase y / o una función es mejor, al menos en mi opinión. Por una vez, hace que el archivo sea más pequeño, lo que es una gran ganancia si maneja aplicaciones web o aplicaciones para dispositivos con poco almacenamiento (IoT, teléfonos más antiguos, etc.)
Y, obviamente, el mejor punto es que si tiene algo que cambiar debido a nuevos protocolos, etc., simplemente cambia el contenido de la función y no innumerables veces pone esta función en algún lugar que incluso podría estar en diferentes archivos, lo que hace que sea aún más difícil encontrar y cambiar
Escribí un intérprete SQL completo para poder cambiar mejor de MySQL a MySQLi en PHP, porque solo tengo que cambiar mi intérprete y todo funciona, aunque ese es un ejemplo un poco extremo.
fuente
Para decidir si un código debe duplicarse o moverse a una función que se llama dos veces, intente determinar cuál es más probable:
Será necesario cambiar ambos usos del código de la misma manera.
Será necesario cambiar al menos un uso del código para que difieran.
En el primer caso, probablemente será mejor que una función maneje ambos usos; en este último caso, probablemente sea mejor tener un código separado para los dos usos.
Al decidir si un código que se usará una vez debe escribirse en línea o extraerse en otra función, descubra cómo describiría completamente el comportamiento requerido de la función. Si una descripción completa y precisa del comportamiento requerido de la función fuera tan larga o más larga que el código en sí, mover el código a una función separada puede hacer que las cosas sean más difíciles de entender en lugar de ser más fáciles. Puede que valga la pena hacerlo si existe una alta probabilidad de que una segunda persona que llama necesitará usar la misma función, y cualquier cambio futuro a la función tendrá que afectar a ambas personas, pero en ausencia de tal consideración, la legibilidad favorecería dividir las cosas. al nivel donde el código y una descripción de su comportamiento requerido serían aproximadamente igual de largos.
fuente