Я работаю над веб-приложением, и я нашел около 1000 строк кода и заметил, что многие мои функции точно такие же, за исключением нескольких изменений в зависимости от контекста. Например, приложение, которое я построил, управляет SharePoint, поэтому я либо работаю с группами, либо я работаю с пользователями. Я пытаюсь найти лучший способ уменьшить избыточность/дублирование в моем коде.
Вот как это выглядит:
Прямо сейчас у меня есть две функции, одна из которых заполняет всех моих пользователей, а другая - заполняет все мои группы. У меня есть другие функции, которые также очень похожи, но имеют несколько изменений в зависимости от того, с чем я работаю.
JS:
function populateGroups(){
//Populate the group list
strHTMLSiteGroups = "";
userAssigned.empty();
userAvailable.empty();
$("#my_SiteGroups option:gt(0)").remove();
$().SPServices({
operation: "GetGroupCollectionFromSite",
completefunc: function(xData, Status) {
groupCollection = $(xData.responseXML);
groupCollection.find("Group").each(function() {
strHTMLSiteGroups += "<option value='" + $(this).attr("Name")+ "' data-groupid='" + $(this).attr("ID") + "'>" + $(this).attr("Name") + "</option>";
});
group.append(strHTMLSiteGroups);
$('#groupOwner').append('<optgroup label="---Groups---"></optgroup>');
$('#groupOwner').append(strHTMLSiteGroups);
}
});
}
function populateUsers() {
//Populate the user list
strHTMLSiteUsers = "";
$("#my_SiteUsers option:gt(0)").remove(); //remove all except first
$().SPServices({
operation: "GetUserCollectionFromSite",
completefunc: function(xData, Status) {
userCollection = $(xData.responseXML);
userCollection.find("User").each(function() {
strHTMLSiteUsers += "<option value='" + $(this).attr("LoginName") + "' data-userid='"+ $(this).attr("ID")+ "'>" + $(this).attr("Name") + "</option>";
});
user.append(strHTMLSiteUsers);
$('#groupOwner').append(strHTMLSiteUsers);
}
});
}
Я планирую использовать это приложение с угловыми, опорными или нокаутами. Я их еще не знаю, так что мне нужно научиться. Моя цель, однако, состоит в том, чтобы иметь один из этих ящиков, а не два. Оттуда есть контроллер (пункт меню), показывающий пользователю возможность работать с пользователями или группами. В этот момент обновите представление, чтобы отразить элементы, связанные с контекстом (пользователь или группа), и иметь одну функцию для возврата групп или пользователей в зависимости от того, в каком контексте я вхожу.
Есть ли способ улучшить функции, которые у меня есть для этого, или имеет 2 функции для каждого контекста?
Это должно сочетать код ваших 2-х функций в 1:
function populateGroups() {
populate('Groups', 'Name', group);
}
function populateUsers() {
populate('Users', 'LoginName', user);
}
function populate(entity, nameKey, entityVar) {
//Populate the list
strHTMLSite = "";
if (entity == 'user') {
userAssigned.empty();
userAvailable.empty();
}
$("#my_Site" + entity + " option:gt(0)").remove();
$("#my_SiteGroups option:gt(0)").remove();
$().SPServices({
operation: "Get" + entity + "GroupCollectionFromSite",
completefunc: function (xData, Status) {
collection = $(xData.responseXML);
collection.find(entity).each(function () {
strHTMLSite += "<option value='" + $(this).attr(nameKey) + "' data-" + entity.toLowerCase() + "id='" + $(this).attr("ID") + "'>" + $(this).attr("Name") + "</option>";
});
entityVar.append(strHTMLSiteGroups);
if (entity == 'group') {
$('#groupOwner').append('<optgroup label="---Groups---"></optgroup>');
}
$('#groupOwner').append(strHTMLSiteGroups);
}
});
}
Как вы можете видеть, разница между двумя решениями составляет всего 2 строки (35 против 33). Тем не менее, по-прежнему неплохо объединить ваш код, поскольку это позволит меньше ошибиться в будущем. Обновление кода в одном месте, а затем забывание обновить его в подобном фрагменте кода является одной из самых распространенных ошибок человека в разработке программного обеспечения, и вы можете предотвратить это, не записывая избыточный код.
Если у вас есть две аналогичные функции, вы можете уменьшить число, добавив параметр. как это:
function populateThings(whatThings)
{
//Populate the list
strHTMLSiteUsers = "";
$("#my_Site" + whatThings + "s option:gt(0)").remove(); //remove all except first
$().SPServices({
operation: "GetUserCollectionFromSite",
completefunc: function(xData, Status) {
userCollection = $(xData.responseXML);
userCollection.find(whatThings).each(function() {
strHTMLSiteUsers += "<option value='" + $(this).attr("LoginName") + "' data-userid='"+ $(this).attr("ID")+ "'>" + $(this).attr("Name") + "</option>";
});
user.append(strHTMLSiteUsers);
$('#groupOwner').append(strHTMLSiteUsers);
}
});
}
и т.д..
Принцип DRY определенно то, что вам нужно. Я бы рекомендовал иметь одну функцию, но добавить некоторые параметры, например:
function populate(entity)
{
// common code
if (entity === "User") {
// put specific code for User here..
}
if (entity === "Group") {
// put specific code for Group here..
}
}