泛化具有不同参数的相似函数
Generalize similar function with different parameters
想象一下应用程序中的两种内容:“歌曲”和“电影”。
我有两个非常相似的辅助方法:
/**
* @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];
}
和
/**
* @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];
}
如您所见,两个函数中都存在代码重复。我该怎么做才能更多地概括它们?任何设计模式?
我正在处理的问题是两种方法都调用不同的 api 方法,并且具有不同的参数...但是,另一方面,我试图在逻辑上不重复我自己。
您可以将随机函数和趋势函数传入公共重构函数。为了迎合不同趋势函数行为方式的差异(一个不需要参数,一个需要类别),您可以将它们包装在函数中:
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];
}
现在两个函数都可以调用重构后的函数了:
function fillRemainingSongsList(currentSongs, currentUserId) {
function getRandom () {
return api.songs.getRandomSongs();
}
function getTrending () {
return api.songs.getTrendingSongs();
}
return fillRemaining(currentSongs, getRandom, getTrending);
}
为了清楚起见,上面的函数是用命名函数编写的。或者你可以使用匿名函数:
async function fillRemainingFilmsList(currentFilms, category) {
return fillRemaining(
currentFilms,
() => api.films.getRandomFilms(category),
() => api.films.getTrendingFilms(category)
);
}
两种样式的作用完全相同。
想象一下应用程序中的两种内容:“歌曲”和“电影”。
我有两个非常相似的辅助方法:
/**
* @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];
}
和
/**
* @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];
}
如您所见,两个函数中都存在代码重复。我该怎么做才能更多地概括它们?任何设计模式?
我正在处理的问题是两种方法都调用不同的 api 方法,并且具有不同的参数...但是,另一方面,我试图在逻辑上不重复我自己。
您可以将随机函数和趋势函数传入公共重构函数。为了迎合不同趋势函数行为方式的差异(一个不需要参数,一个需要类别),您可以将它们包装在函数中:
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];
}
现在两个函数都可以调用重构后的函数了:
function fillRemainingSongsList(currentSongs, currentUserId) {
function getRandom () {
return api.songs.getRandomSongs();
}
function getTrending () {
return api.songs.getTrendingSongs();
}
return fillRemaining(currentSongs, getRandom, getTrending);
}
为了清楚起见,上面的函数是用命名函数编写的。或者你可以使用匿名函数:
async function fillRemainingFilmsList(currentFilms, category) {
return fillRemaining(
currentFilms,
() => api.films.getRandomFilms(category),
() => api.films.getTrendingFilms(category)
);
}
两种样式的作用完全相同。