Imagina dos tipos de contenido en una aplicación: "Canciones" y "Películas".
Tengo dos métodos auxiliares que son realmente similares:
/** * @protected <-- No need to validate arguments, as the method is "protected". * ... */ function fillRemainingSongsList(currentSongs, currentUserId) { const remainingSongs = MAX_LIST_SIZE - currentSongs.length; const shouldFetchTrending = Math.random() < FETCH_TRENDING_PROBABILITY; const promises = [ api.songs.getRandomSongs(), shouldFetchTrending ? api.songs.getTrendingSongs() : undefined ]; const [ randomSongs = [], trendingSongs = [], ] = await Promise.all(promises); return [...currentSongs, ...randomSongs, ...trendingSongs]; }y
/** * @protected * ... */ async function fillRemainingFilmsList(currentFilms, category) { const remainingFilms = MAX_LIST_SIZE - currentFilms.length; const shouldFetchTrending = Math.random() < FETCH_TRENDING_PROBABILITY; const promises = [ api.films.getRandomFilms(category), shouldFetchTrending ? api.films.getTrendingFilms(category) : undefined ]; const [ randomFilms = [], trendingFilms = [], ] = await Promise.all(promises); return [...currentFilms, ...randomFilms, ...trendingFilms]; }Como puede ver, hay repetición de código en ambas funciones. ¿Cómo puedo hacer para generalizarlos más? ¿Algún patrón de diseño?
El problema que estoy manejando es que ambos métodos llaman a diferentes métodos api y tienen diferentes parámetros ... pero, por otro lado, estoy tratando de no repetirme en la lógica.
Puede pasar las funciones aleatorias y de tendencia a la función refactorizada común. Para atender las diferencias en el comportamiento de las diferentes funciones de tendencias (una no requiere parámetros y la otra requiere una categoría), puede envolverlas en funciones:
async function fillRemaining(currentItems, getRandomFn, getTrendingFn) { const remainingItems = MAX_LIST_SIZE - currentItems.length; // this is never used? const shouldFetchTrending = Math.random() < FETCH_TRENDING_PROBABILITY; const promises = [ getRandomFn(), shouldFetchTrending ? getTrendingFn() : undefined ]; const [ randomItems = [], trendingItems = [], ] = await Promise.all(promises); return [...currentItems, ...randomItems, ...trendingItems]; }Ahora ambas funciones pueden llamar a la función refactorizada:
function fillRemainingSongsList(currentSongs, currentUserId) { function getRandom () { return api.songs.getRandomSongs(); } function getTrending () { return api.songs.getTrendingSongs(); } return fillRemaining(currentSongs, getRandom, getTrending); }La función anterior está escrita con funciones nombradas para mayor claridad. Alternativamente, puede usar funciones anónimas:
async function fillRemainingFilmsList(currentFilms, category) { return fillRemaining( currentFilms, () => api.films.getRandomFilms(category), () => api.films.getTrendingFilms(category) ); }Ambos estilos hacen exactamente lo mismo.