LINUX.ORG.RU

ООП true way

 ,


1

2

Приветствую. Существует некая веб-страничка. Она получает данные с сервера через AJAX/WebSocket (способ не важен) в виде JSON-строки следующего вида.

Для авторизованных пользователей:

[{"id": 1, "name": "Худ. литература", "typed": 123040, "averageSpeed": 43420}]

Для неавторизованных:

[{"id": 1, "name": "Худ. литература"}]

Теперь к вопросу. Меня перестал устраивать просто расшифрованный JSON-массив с объектами (понадобилось создать интерфейсы к этим данным) и захотелось вынести эти данные в отдельный тип Category.

Я столкнулся с проблемой: как быть с полями для авторизованных пользователей? Ведь их не должно быть у неавторизованных.

Накидал пару решений:

1) сделать конструктор которому необязательно передавать эти два поля (для гостей).

2) сделать разные сущности вроде UserCategory (который содержит эти поля) и AnonymousCategory (который не содержит).

В поддержку этого решения скажу что если пользователь не авторизован, то по логике моего приложения обращения к этим полям не будет. Т.е. можно сделать некий общий интерфейс между UserCategory и AnonymousCategory, но UserCategory будет содержать также и специфичные для себя интерфейсы.

Какой способ лучше на ваше мнение? Может вы можете предложить что-то другое? Буду рад выслушать, спасибо! (=

★★

Последнее исправление: Razip (всего исправлений: 1)

1 способ для не авторизованных пользователей не создает специфичные поля или будет делать их пустыми.

Razip ★★
() автор топика
Последнее исправление: Razip (всего исправлений: 1)

Почему вдруг оба набора полей не может хранить один объект? Они ведь не разные, а сокращенный является подмножеством полного.

blexey ★★★★★
()

От общего к частному, ес-нно, типа того


User={
 showId: function(){alert(this.id)},
 create: function(spec){var o=Object.create(this); if(spec) o.extend(spec); return o}
}

Anon=User.create({showIdAndName: function(){alert([this.id, this.name])}})
JustUser=User.create({showLoginAndIdAndName: function(){alert([this.login, this.id, this.name])}})

user=JustUser.create({name: "literature", id: 100, login: "foo"})
anon=Anon.create({name: "chemestry", id: 150})

user.showId()                 //  100
user.showLoginAndIdAndName()  //  [ 'foo', 100, 'literature' ]
anon.showId()                 //  150
anon.showIdAndName()          //  [ 150, 'chemestry' ]

Как вариант, если все поля анона совпадают с полями юзера, можно унаследовать юзера от анона.

newuser1001
()
Ответ на: комментарий от newuser1001

Такого же мнения, спасибо.

Razip ★★
() автор топика
function GuestCategory(id, name) {
    this.id = id;
    this.name = name;
}

GuestCategory.prototype = {
    getID: function() {
        return this.id;
    },

    getName: function() {
        return this.name;
    }
};

// Категория, содержащая даные пользователя
function UserCategory(id, name, typed, averageSpeed, errorsPercent) {
    this.id = id;
    this.name = name;
    this.typed = typed;
    this.averageSpeed = averageSpeed;
    this.errorsPercent = errorsPercent;
}

// Наследуем протип
UserCategory.prototype = GuestCategory.prototype;

// Добавляем специфичные UserCategory методы
UserCategory.prototype.getTyped = function() {
    return this.typed;
};

UserCategory.prototype.getAverageSped = function() {
    return this.averageSpeed;
};

UserCategory.prototype.getErrorsPercent = function() {
    return this.errorsPercent;
};

UserCategory.prototype.increaseTyped = function() {
    this.typed++;
    
    return this;
}

var oneCategory = new UserCategory(1, 'Худ. литература', 0, 0, 0);

console.log(oneCategory.getName());

Типа того, но хотелось бы запускать родительский конструктор. Это как-то с помощью метода call можно провернуть.

Razip ★★
() автор топика
Ответ на: комментарий от Razip

Вот так:

// Категория, содержащая даные пользователя
function UserCategory(id, name, typed, averageSpeed, errorsPercent) {
    GuestCategory.call(this, id, name);
    
    this.typed = typed;
    this.averageSpeed = averageSpeed;
    this.errorsPercent = errorsPercent;
}

Razip ★★
() автор топика

Если у тебя класс это просто хранилище данных, достаточно одного класса, для несуществующих полей храни null, в геттере выбрасывай исключение. Ну и сделай свойство «тип объекта».

Если у тебя класс имеет поведение помимо данных, тогда надо смотреть на это поведение. Если у тебя планируются if-ы по типу объекта (если анониный, то одно поведение, если не анонимный, то второе), то надо два класса. Если это поведение будет идентичным, то два класса не нужны.

Как общий совет могу порекомендовать начинать с простого решения, одного класса. Потом сам увидишь, если нужно делать два класса. Наследование это очень опасный инструмент и его лучше применять только там, где это необходимо. Просто так не стоит.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)
Ответ на: комментарий от Legioner

Не хочу объединять две сущности в одним тип, т.к. в целевом объекте могут быть пустые, не характерные текущей сущности поля, а в его конструкторе будут проверки на количество аргументов и их наличие (если учитывать что сущности имеют разное количество полей и что значения полей устанавливаются через параметры конструктора).

Логика моего приложения не зависит от объекта, а объект зависит от логики. Т.е. не может быть такого чтобы был вызван несуществующий метод у GuestCategory, и чтобы не было какого-нибудь метода у UserCategory (объекты создаются и методы вызываются на основании флага авторизации).

Т.е. пустое свойство у GuestCategory не может быть получено, хоть и может быть.

Итого: я могу свести эти два типа в один, но будет не в духе ООП.

Razip ★★
() автор топика
Ответ на: комментарий от Razip

Итого: я могу свести эти два типа в один, но будет не в духе ООП.

Доктор, у меня левое яичко висит ниже правого. Неаккуратно как-то.

metrokto ★★
()
Ответ на: комментарий от metrokto

Я не вижу причин городить костыли. Но если тебе нравиться - дерзай.

Razip ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.