Позвольте мне объяснить свое понимание с помощью четырех примеров. Java является pass-by-value, а не pass-by-reference
/ **
Pass By Value
В Java все параметры передаются по значение, т. е. назначение аргумента метода не отображается вызывающему.
* /
Пример 1:
public class PassByValueString {
public static void main(String[] args) {
new PassByValueString().caller();
}
public void caller() {
String value = "Nikhil";
boolean valueflag = false;
String output = method(value, valueflag);
/*
* 'output' is insignificant in this example. we are more interested in
* 'value' and 'valueflag'
*/
System.out.println("output : " + output);
System.out.println("value : " + value);
System.out.println("valueflag : " + valueflag);
}
public String method(String value, boolean valueflag) {
value = "Anand";
valueflag = true;
return "output";
}
}
Результат
output : output
value : Nikhil
valueflag : false
Пример 2:
/ ** * * Pass By Value * * /
public class PassByValueNewString {
public static void main(String[] args) {
new PassByValueNewString().caller();
}
public void caller() {
String value = new String("Nikhil");
boolean valueflag = false;
String output = method(value, valueflag);
/*
* 'output' is insignificant in this example. we are more interested in
* 'value' and 'valueflag'
*/
System.out.println("output : " + output);
System.out.println("value : " + value);
System.out.println("valueflag : " + valueflag);
}
public String method(String value, boolean valueflag) {
value = "Anand";
valueflag = true;
return "output";
}
}
Результат
output : output
value : Nikhil
valueflag : false
Пример 3:
/ ** У этого «Pass By Value» есть ощущение «Pass By Reference»
Некоторые говорят, что примитивные типы и «String» являются «pass by value», а объекты «проходят» по ссылке '.
Но из этого примера мы можем понять, что это infact передается только по значению, имея в виду, что здесь мы передаем ссылку как значение. т.е.: ссылка передается по значению. Вот почему они могут меняться, и все же это верно после локального масштаба. Но мы не можем изменить фактическую ссылку за пределами исходной области. что это означает, показано в следующем примере PassByValueObjectCase2.
* /
public class PassByValueObjectCase1 {
private class Student {
int id;
String name;
public Student() {
}
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
}
public static void main(String[] args) {
new PassByValueObjectCase1().caller();
}
public void caller() {
Student student = new Student(10, "Nikhil");
String output = method(student);
/*
* 'output' is insignificant in this example. we are more interested in
* 'student'
*/
System.out.println("output : " + output);
System.out.println("student : " + student);
}
public String method(Student student) {
student.setName("Anand");
return "output";
}
}
Результат
output : output
student : Student [id=10, name=Anand]
Пример 4:
/ **
В дополнение к тому, что упоминалось в примере 3 (PassByValueObjectCase1.java), мы не можем изменить фактическую ссылку вне исходной области. "
Примечание: я не вставляю код для private class Student
. Определение класса для Student
такое же, как в примере 3.
* /
public class PassByValueObjectCase2 {
public static void main(String[] args) {
new PassByValueObjectCase2().caller();
}
public void caller() {
// student has the actual reference to a Student object created
// can we change this actual reference outside the local scope? Let's see
Student student = new Student(10, "Nikhil");
String output = method(student);
/*
* 'output' is insignificant in this example. we are more interested in
* 'student'
*/
System.out.println("output : " + output);
System.out.println("student : " + student); // Will it print Nikhil or Anand?
}
public String method(Student student) {
student = new Student(20, "Anand");
return "output";
}
}
Результат
output : output
student : Student [id=10, name=Nikhil]
TL; DR: GraphQL светит, когда Firebase падает. Мощное моделирование данных, гибкие и эффективные запросы и открытая спецификация - все необходимые компоненты GraphQL, которые отсутствуют в Firebase.
Firebase получила много критики, основанных на его ограниченное моделирование данных. В принципе, ваши данные структурированы как единый гигантский JSON, который многократно указывает одни и те же данные. Вначале кажется, что вначале возникает неуправляемый клиентский код, когда вам нужно обновлять данные, так как вы должны отслеживать все ссылки на одни и те же данные вручную.
Структура данных, используемая в GraphQL, с другой стороны очень интуитивно понятен и привычен думать, поскольку он моделируется как график. Используя синтаксис IDL , мы можем легко описать нашу модель данных, называемую схемой GraphQL. Для приложения Twitter схема может выглядеть так:
type Tweet {
id: ID!
title: String!
author: User! @relation(name: "Tweets")
}
type User {
id: ID!
name: String!
tweets: [Tweet!]! @relation(name: "Tweets")
}
Здесь мы определили два типа Tweet
и User
с некоторыми скалярными свойствами, а также отношение один ко многим между User
и Tweet
. Единые элементы данных называются узлами - и пользовательский узел может быть подключен ко многим узлам твитов. Эта структура данных является простой и гибкой, за исключением подхода JSON от Firebase.
Гибкие возможности запросов GraphQL являются одним из его основных преимуществ. Запросы являются иерархическими, это означает, что вы можете указать требования к данным, которые отражают структуру графика. В нашем примере Twitter у нас может быть запрос на выбор всех пользователей и их твитов:
query {
allUsers {
id
name
tweets {
title
}
}
}
Обратите внимание, что мы можем свободно включать или оставлять поля, которые мы хотим запросить, и мы можем даже запросить связи. Это означает, что нам не нужно делать несколько запросов и мы не запрашиваем ненужные данные, что делает запросы GraphQL чрезвычайно эффективными.
Добавляя аргументы запроса к соединению, мы можем добавлять такие функции, как пользовательский порядок или фильтры, чтобы получить мощный графический API .
Все это просто невозможно в Firebase.
Возможности реального времени Firebase сделали это популярный - но поскольку сообщество GraphQL собирается достичь консенсуса относительно реального времени , наибольшее преимущество Firebase также сведено к нулю. Я рекомендую этот видеоурок для подписки GraphQL, чтобы лучше понять базовые понятия
Итак, чтобы ответить на ваш вопрос: GraphQL превосходит Firebases в большинстве что делает его предпочтительным выбором.
Если вас интересует GraphQL, я рекомендую вам проверить Graphcool , который сочетает в себе силы GraphQL с мощными функциями, такими как встроенная аутентификация и гибкие привязки к AWS Lambda или другие серверные функции для реализации пользовательской бизнес-логики.
Отказ от ответственности: я работаю в Graphcool:)
Нужно ли использовать firebase? Существуют более специфичные для GraphQL службы, которые могут предложить то, что вы ищете. https://scaphold.io - компания YC Fellowship, которая выглядит особенно многообещающей и дает вам опыт работы с firebase, но работает на платформе GraphQL.
Я категорически не согласен с некоторыми рекомендациями здесь. GraphQL можно использовать реляционным способом, но его также можно использовать в режиме без sql. Firebase, с ее RTD и firestore, должна быть смоделирована как база данных no-sql, потому что это база данных no-sql !, есть компромиссы к этому подходу:
1. Оптимизированное чтение:
Как база данных без sql, коллекции должны быть смоделированы как ваши взгляды на ваших клиентах (мобильных или веб-сайтах), поэтому, когда вы делаете запрос, все уже слито, и вы не должны делать расчетные реквизиты в клиенте, а также функции firebase. Этот подход делает чтение действительно ДЕЙСТВИТЕЛЬНО быстрым.
2. Де-оптимизированная запись:
Основной компромисс заключается в том, что вы несете ответственность за обновление каждого документа в базе данных, если вы касаетесь связанных данных (например, обновите имя пользователя, изображение профиля и т. Д.). В этом случае вы должны найти каждый документ в своей базе данных (IE: сообщения, комментарии и т. Д.) И обеспечить атомарность. Этот подход рекомендуется, если у вас есть приложение, которое будет иметь гораздо больше операций чтения, чем операции записи (например, в блоге, 7000 читает 1 запись в качестве примера)
3. Простота в масштабировании:
Поскольку ваши коллекции не имеют жестких отношений с другими документами, вы можете иметь полную коллекцию только на одном сервере или разделить ее среди многих из них (поэтому, почему базовая станция дешева для масштабирования, например dynamoDB ).
GraphQL - это только язык запросов, он должен упростить вам запрос, но он не должен диктовать, как вы моделируете свою базу данных, вы должны диктовать, как моделировать вашу базу данных, ваши запросы и мутации .
Вы можете использовать graphql & amp; firebase локально.
Одно слово о «многих обратных переходах, необходимых для разрешения запроса»: если вы не возражаете против данных передано, это не так много, так как все «roundtrips» объединены в один и тот же сокет. Но если вы хотите избежать больших кадров, вам просто нужно положить немного dataloader
перед вашей базой данных firebase.
Для обновлений в реальном времени вам нужно только подписаться на события в реальном времени от firebase и отправить их для веб-администратора, чтобы преобразовать их в реальные подписки graphql, которые могут быть решены с помощью вашей схемы.
Более подробную информацию по этой самой проблеме можно найти на моей средней должности: «Только для клиентской стороны» в реальном времени веб-приложения с Firebase, GraphQL и apollo-client 2.0
Надеюсь, что это поможет!
Чтобы ответить на ваш вопрос, вы можете иметь дело с тремя способами:
Если вы настроены на использование Firebase, вы можете сделать взаимно однозначное сопоставление API Firebase в запросах и мутациях GraphQL.
Вы можете, конечно, обернуть API Firebase в преобразователи GraphQL, и таким образом вызывать вызовы. Это хороший пример этого :
const ref = path => firebase.database().ref(path)
const getValue = path => ref(path).once('value')
const mapSnapshotToEntities = snapshot => snapshot.val().map((value, id) => ({ id, ...value }))
const getEntities = path => getValue(path).then(mapSnapshotToEntities)
const resolvers = {
Author: {
posts(author) {
return getEntities('posts').then(posts => filter(posts, { authorId: author.id }))
},
},
Post: {
author(post) {
return getEntities('authors').then(posts => filter(authors, { id: authorId }))
},
},
};
По сути, вы здесь используете Firebase в качестве базы данных, которая работает, пока вы не захотите запросить свои данные в реляционная манера в ваших решениях. Без возможности выполнять соединения на стороне сервера поверх вашего хранилища данных вы будете делать тонны запросов на обратный путь к Firebase в ваших распознавателях, чтобы выполнить только один запрос.
Причина, по которой большинство люди используют Firebase для своих возможностей в реальном времени, а не в первую очередь как хранилище данных, поскольку средства реляционного моделирования данных в этом аспекте довольно отсутствуют. При этом вам, вероятно, лучше перейти на GraphQL с использованием другого источника данных.
Учитывая, что вы открыты для использования продуктов BaaS, таких как Firebase, вы можете перейти на GraphQL BaaS.
Если вы можете перейти на самостоятельное решение с помощью собственного хранилища данных, это также принесет много преимуществ. Вот несколько больших нападающих: