Классное дизайнерское решение
-
09-06-2019 - |
Вопрос
У меня есть небольшая дилемма, которая может помочь мне разобраться. Р>
Сегодня я работал над изменением членства в ASP.NET, чтобы повысить уровень косвенности. По сути, членство ASP.NET поддерживает пользователей и роли, оставляя все правила авторизации в зависимости от того, принадлежит ли пользователь роли или нет. Р>
Что мне нужно сделать, это добавить концепцию Function, в которой пользователь будет принадлежать к роли (или ролям), а роль будет иметь одну или несколько функций, связанных с ними, что позволит нам авторизовать конкретное действие на основе пользователь принадлежит роли, которой назначена функция. Р>
Сказав это, моя проблема не имеет к этому никакого отношения, это общая проблема проектирования классов. Р>
Я хочу предоставить абстрактный метод в своем базовом классе RoleProvider для создания функции (и сохранения ее), но я хочу сделать необязательным сохранение описания этой функции, поэтому мне нужно создать свой метод CreateFunction с перегрузка, одна подпись принимает имя, а другая принимает имя и описание. Р>
Я могу подумать о следующих сценариях:
<Ол>Создайте обе подписи с модификатором abstract. В этом есть проблема, заключающаяся в том, что разработчик может не соблюдать передовую практику, которая гласит, что одна перегрузка должна вызывать другую с нормализованными параметрами, и логика должна быть только в последней (та, которая имеет все параметры). Кроме того, не стоит требовать, чтобы оба метода были реализованы разработчиком. Р>
Создайте первый как виртуальный, а второй как абстрактный. Вызовите второй из первого, разрешите разработчику переопределить поведение. У него та же проблема: разработчик может принимать «неправильные решения». при переопределении. Р>
То же, что и раньше, но не допускайте переопределения первого (удалите виртуальный модификатор). Проблема здесь в том, что разработчик должен знать, что метод может быть вызван с нулевым описанием, и должен обрабатывать эту ситуацию. Р>
Я думаю, что лучший вариант - третий ...
Как этот сценарий обрабатывается в целом? Когда вы разрабатываете абстрактный класс, он содержит перегруженные методы. Я думаю, это не так уж редко ...
Решение
Я чувствую, что лучшая комбинация DRYness и форсирования контракта выглядит следующим образом (в псевдокоде):
class Base {
public final constructor(name) {
constructor(name, null)
end
public abstract constructor(name, description);
}
или, альтернативно:
class Base {
public abstract constructor(name);
public final constructor(name, description) {
constructor(name)
this.set_description(description)
}
private final set_description(description) {
...
}
}
В Java есть правило, поддерживающее это решение: "никогда не вызывать неокончательные методы из конструктора."
Другие советы
Чтобы ответить на первую часть вашего сообщения, ознакомьтесь с AzMan (диспетчером авторизации), который, кстати, встроен в Windows. Он имеет возможность указывать операции, которые могут быть объединены в роли или назначены непосредственно пользователям.
Чтобы ответить на вторую часть вашего вопроса, я бы не стал использовать класс Abstract. Вместо этого просто предоставьте функциональность в конструкторе и покончите с этим. Кажется, вам нужно указанное поведение, и вы не хотите, чтобы оно изменилось. Зачем заставлять потомков обеспечивать реализацию.