Проектирование класса на примере User
От: Kalastiuz Ниоткуда  
Дата: 13.07.09 08:00
Оценка:
Существует некоторый класс User в котором описан метод IsValidUser(login, password). В реализации метода необходимо подключаться к БД и опеределять существует ли пользователь с параметрами логин и пароль.
Необходимо реализовать класс так, чтобы его можно было повторно использовать и в других приложениях. Но в других приложениях может измениться имя таблицы и/или имена полей в таблице.
Возникли затруднения с самой его реализацией и на ум проходят два выхода, между которыми не могу сделать выбор.
1. В других приложениях описывать какой-то дочерний класс от User и в новом классе переопределять метод IsValidUser, но тогда толку от реализации логики в базовом классе, если его все равно придется переписать.
2. В каком-то конфиг-классе или в настройках приложения или в настройках "первого запуска приложения" (не столь важно) указывать имя таблицы пользователей и имена полей login и password. И в реализации метода использовать именно эти значения.

Класс User взят в качестве примера, в библиотеке может быть большое количество классов реализованных по такому-же принципу. Даже в этом же классе, например методы: IsExist(login), IsActive(user_id) и т.п.
Re: Проектирование класса на примере User
От: komaz Россия  
Дата: 13.07.09 10:23
Оценка:
Здравствуйте, Kalastiuz, Вы писали:

K>Существует некоторый класс User в котором описан метод IsValidUser(login, password). В реализации метода необходимо подключаться к БД и опеределять существует ли пользователь с параметрами логин и пароль.

K>Необходимо реализовать класс так, чтобы его можно было повторно использовать и в других приложениях. Но в других приложениях может измениться имя таблицы и/или имена полей в таблице.
K>Возникли затруднения с самой его реализацией и на ум проходят два выхода, между которыми не могу сделать выбор.
K>1. В других приложениях описывать какой-то дочерний класс от User и в новом классе переопределять метод IsValidUser, но тогда толку от реализации логики в базовом классе, если его все равно придется переписать.
K>2. В каком-то конфиг-классе или в настройках приложения или в настройках "первого запуска приложения" (не столь важно) указывать имя таблицы пользователей и имена полей login и password. И в реализации метода использовать именно эти значения.

K>Класс User взят в качестве примера, в библиотеке может быть большое количество классов реализованных по такому-же принципу. Даже в этом же классе, например методы: IsExist(login), IsActive(user_id) и т.п.


Почему методы IsValidUser, IsExist и IsActive что-то принимают? Они статические? Или класс User на самом деле не то чем кажется?
public class User {
    public User(IUserProvider provider, int id) {
        this.id = id;
        this.provider = provider;
    }
    
    public boolean isValid(String password) {
        return provider.isValid(id, password);
    }

    public boolean isActive() {
        return provider.isActive(id);
    }
}

public class MyDatabaseUserProvider implements IUserProvider {
    public DatabaseUserProvider(Properties properties) {
        this.usersTable = properties.getString("usersTable");
        this.nameColumn = properties.getString("nameColumn");
        this.passwordColumn = properties.getString("passwordColumn");
    }
}
Re: Проектирование класса на примере User
От: sentyaev  
Дата: 13.07.09 10:30
Оценка:
Можно сделать так:

class UserBase
{
// и в медодах класса используй это поле
private DBConf conf;

public UserBase(DBConf config)
{ ... }

public bool IsValidUser(login, password)
{ ... }
}

class DBConf
{
public string TableName {get;set;}
public string LoginColumnName {get;set;}
public string PasswordColumnName {get;set;}
// и другие необходимые настройки

// этот метод можно переопределить, чтоб получать
// настройки в одном приложении например из Базы1,
// а в другом из Базы2, а в третем из файла
public virtual void Init (string connectionString)
{
...
// сдесь получаешь настройки из файла, базы (откуда хочешь)
...
}
}
Re[2]: Проектирование класса на примере User
От: sentyaev  
Дата: 13.07.09 10:31
Оценка:
Упс... Меня уже опередили в предыдущем посте....
Re[2]: Проектирование класса на примере User
От: Kalastiuz Ниоткуда  
Дата: 13.07.09 13:08
Оценка:
Здравствуйте, komaz, Вы писали:

K>Почему методы IsValidUser, IsExist и IsActive что-то принимают? Они статические? Или класс User на самом деле не то чем кажется?


Могут быть и методы без параметров, а можно перегрузить и так так. А можно в конструкторе инициализировать объект данными о логине и пароле. Это не столь важно.
Важно понять идею и то как же все таки правильнее реализовать, что бы в последствии можно было использовать классы повторно.

В случае если я опишу метод следующим образом:

  public Boolean IsValidUser(String login, String password)
  {
     ...
    String query = @"SELECT user_id FROM tbl_users WHERE tbl_users.login = @login AND tbl_users.password = @password";
     ...
  }


То какова вероятность того, что пользователь назовет таблицу и имена полей именно так, а не например users? Крайне мала.
Значит привязывать запрос к определенной таблице/полям не совсем правильно. А если пользователю придется переопределять метод в дочернем классе, то тогда можно оставить тело метода пустым. Пусть переопределяет как хочет. Такой вариант, тоже не особо нравится.

С другой стороны, если в каком-то конфиге сопоставить данные о таблице и ее полях. Получится громоздкий конфиг файл. Таблица пользователей же не одна да и полей можно быть какое-то количество.

Как вариант еще с библиотекой классов поставлять некий скрипт, создающий таблицы используемые в ней, автоматически с теми названиями которые удобны мне, как разработчику данных классов.
Вот и пробую найти наиболее удачное решение.
Re: Проектирование класса на примере User
От: ZevS  
Дата: 13.07.09 14:50
Оценка: :)
Здравствуйте, Kalastiuz, Вы писали:

Сделай класс самым очевидным образом, а потом попробуй покрыть его юнит тестами. Скорее всего, что бы сделать это, классс придется рефакторить. А результат, скорее всего, уже можно будет повторно использовать.
Или вообще, попробуй TDD.
Re[3]: Проектирование класса на примере User
От: IB Австрия http://rsdn.ru
Дата: 13.07.09 16:02
Оценка: 1 (1) +2
Здравствуйте, Kalastiuz, Вы писали:

K>Важно понять идею и то как же все таки правильнее реализовать, что бы в последствии можно было использовать классы повторно.

Классы повторно можно, а вот метод IsValidUser — вряд ли, как ты уже сам докадался.

K>Вот и пробую найти наиболее удачное решение.

Наиболее удачное решение — вынести методы тип IsValidUser и всю логику завязанную на конкретное окружение во внешние классы. Например, метод IsValidUser — должен принадлежать не классу User, а конкретной подсистеме аутентификации, где вообще никакого SQL-я может не быть, а быть, например AD, или вообще что-то смешанное.
... << RSDN@Home 1.2.0 alpha 4 rev. 1082>>
Мы уже победили, просто это еще не так заметно...
Re[4]: Проектирование класса на примере User
От: Аноним  
Дата: 13.07.09 17:50
Оценка:
Здравствуйте, IB, Вы писали:

IB>Здравствуйте, Kalastiuz, Вы писали:


K>>Важно понять идею и то как же все таки правильнее реализовать, что бы в последствии можно было использовать классы повторно.

IB>Классы повторно можно, а вот метод IsValidUser — вряд ли, как ты уже сам докадался.

K>>Вот и пробую найти наиболее удачное решение.

IB>Наиболее удачное решение — вынести методы тип IsValidUser и всю логику завязанную на конкретное окружение во внешние классы. Например, метод IsValidUser — должен принадлежать не классу User, а конкретной подсистеме аутентификации, где вообще никакого SQL-я может не быть, а быть, например AD, или вообще что-то смешанное.

Полностью поддерживаю. Валидаторов может быть много, и разных, а класс User — всё тот же.

Причем валидировать можно даже не один класс, а консистентность сочетаний: например, валидация связки User и Car будет задавать вопрос: почему у юзера с зарплатой в сто тугриков в гараже стоят Ламборджини и Майбах
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.