Разрабатывайте высококачественные серверные API

API RESTful
Разрабатывайте высококачественные серверные API

Автор этой статьи: NetEase Cloud Music Front-end EngineerБао Юнмин

предисловие

Независимо от использования Node.js в реальных продуктах, считается, что существуют миллионы проектов, разработанных с использованием Node.js в качестве сервера, и подавляющее большинство разработчиков являются фронтенд-инженерами, поскольку Node.js является их естественным языком. инструмент. В будущем к разработке Node.js будет присоединяться все больше фронтенд-инженеров.

Поскольку Node.js используется в качестве языка разработки на стороне сервера, мы должны разработать интерфейс API. В этой статье используется пример требования для описания того, как эффективно разрабатывать высококачественные интерфейсы API на стороне сервера.

нужно

Сначала посмотрите на требования, всего имеется 3 таблицы базы данных (база данных MySQL), а именно:

CREATE TABLE `user` (
    `id`            INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '唯一标识',
    `name`          VARCHAR(50) NULL DEFAULT '' COMMENT '帐号',
    `email`         VARCHAR(50) NULL DEFAULT '' COMMENT '邮箱',
    `nickname`      VARCHAR(50) NOT NULL DEFAULT '' COMMENT '真实姓名',
    `createTime`    DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '帐号创建时间',
    PRIMARY KEY (`id`),
    UNIQUE INDEX `uk_email` (`email` ASC)
)
ENGINE=InnoDB AUTO_INCREMENT=1 COMMENT='用户表';

CREATE TABLE `project` (
    `id`            INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '唯一标识',
    `name`          VARCHAR(100) NULL DEFAULT NULL COMMENT '名称',
    `description`   VARCHAR(500) NULL DEFAULT '' COMMENT '描述',
    `creatorId`     INT UNSIGNED NOT NULL COMMENT '创建者标识',
    `createTime`    DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    `deletedAt`     DATETIME(3) COMMENT '删除时间',
    PRIMARY KEY (`id`)
)
ENGINE=InnoDB AUTO_INCREMENT=1 COMMENT='项目表';

CREATE TABLE `project_user` (
    `role`        TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户角色0-成员;9-管理员;10-创建者',
    `userId`      INT UNSIGNED NOT NULL COMMENT '用户标识',
    `projectId`   INT UNSIGNED NOT NULL COMMENT '项目标识',
    `createTime`  DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    PRIMARY KEY (`userId`, `projectId`),
    INDEX `idx_projectId` (`projectId` ASC)
)
ENGINE=InnoDB COMMENT='项目-用户关系表';

Смысл в следующем:

  • пользовательская таблицаuserПервичный ключid, автоинкрементный, уникальный индексemail.
  • Таблица проектаproject, первичный ключid, самовозрастающая. Пользователи могут создавать проекты,creatorIdПоле — это личность творца.
  • Таблица отношений между проектами и пользователями, которая представляет отношения сопоставления между проектами и пользователями, и общий первичный ключuserIdа такжеprojectId. В проекте может быть несколько пользователей, у пользователей разные роли, использованиеroleполе, чтобы указать, что разные роли имеют разные разрешения, как показано ниже:
    • Только участники, администраторы и создатели проекта могут видеть проект.
    • Только администраторы и создатели проекта могут изменять проект.
    • Только создатель элемента может удалить элемент.

Операции, связанные с пользователем, не являются предметом этой статьи. В этой статье только описывается, как реализовать интерфейсы CRUD, связанные с проектами:

  • Создайте проект.
  • Элемент запроса.
  • Измените элемент.
  • Удалить пункт.

Поскольку мы хотим эффективно разрабатывать высококачественные интерфейсы, мы не можем ждать, пока пользовательский интерфейс разработает интерфейс.Только когда интерфейс разработки и страница разработки разрабатываются параллельно, можно повысить общую эффективность разработки команды. Друзья, которые имели дело с серверной разработкой, должны знать, что когда серверная сторона разрабатывает интерфейс локально, она будет использовать такие инструменты, как Postman, для проверки правильности интерфейса. Мы должны сделать все возможное, чтобы разработка интерфейса не выходила за рамки страницы.Хотя разработка интерфейса на странице очень интуитивно понятна и удобна, она имеет много ограничений.

Для удобства используемeggjsframework, формат обмена данными использует JSON, интерфейс использует спецификацию RESTful, и оба имеют вид/apiначало. Кроме того, в этой статье представлена ​​только разработка функции самого интерфейса, а другие аспекты, такие как кэширование, затронуты не будут.

Создать проект

Согласно спецификации RESTful, адрес интерфейсаPOST /api/projects. Хотя мы разрабатываем интерфейс отдельно от пользовательского интерфейса, логика взаимодействия со страницей должна быть ясной (как правило, будет черновик дизайна взаимодействия). Для создания проекта пользователь обычно представляет собой форму для заполнения информации о проекте, которая содержит имя и описание проекта.После того, как пользователь заполнит, нажмите кнопку «Отправить», чтобы отправить данные формы, и после Бэкэнд получает данные, вставляет их в базу данных. Это процесс создания проекта.

Запрос, отправленный клиентом, сначала будет обработан некоторым общим промежуточным программным обеспечением, а затем поступит на уровень контроллера, где записывается код бизнес-логики. Мы не можем доверять данным, представленным пользователем, и нам необходимо выполнить самую простую проверку данных. согласно сprojectТаблица базы данных,nameПоле имеет строковый тип и не может превышать 100 в длину,descriptionПоле также является строковым типом, длина не может превышать 500, и оба могут быть пустыми.

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

// ~ /controller/project.js
const createRule = {
    name: {
        type: 'string',
        max: 100,
    },
    description: {
        type: 'string',
        max: 500,
        required: false,
    },
};

async create() {
    const ctx = this.ctx;
    // 接收到的 JSON 数据
    const data = ctx.request.body;
    // 对数据进行验证,如果验证不通过,会直接报错返回
    ctx.validate(createRule, data);
    // 调用 service 方法去创建项目
    const id = await ctx.service.project.create(data);
}

Я считаю, что многие друзья видели, что в приведенном выше коде есть серьезная проблема, то естьdataВ объекте отсутствует информация о создателе проекта. Кто создатель? Очевидно, это должен быть текущий авторизованный пользователь. Предпосылка, что пользователь может создать проект, состоит в том, что он вошел в систему. В современных веб-проектах информация о вошедшем в систему пользователе обычно хранится в куки-файле клиента, а слово сервера соответственно сохраняется в сеансе. Когда клиент отправляет запрос, запрос по умолчанию будет содержать информацию о файлах cookie, и нет необходимости явно отправлять эти данные. Сервер извлекает соответствующую информацию о пользователе из сеанса в соответствии с запрошенным файлом cookie. Однако вся эта работа, фреймворк или промежуточное ПО уже реализованы за нас, это не является предметом этой статьи, поэтому она не будет расширяться.

Помимо проблемы, которую не ставил создатель, следует отметить следующие моменты:

  • справаnameПри проверке уберите пробелы с обеих сторон от него, ведь имя не может состоять из одних пробелов.descriptionНеважно, ничего не будет сделано.
  • Данные, отправляемые клиентом, могут содержать данные с другими именами полей, это вполне возможно, поэтому в методе create, передаваемом Сервису, должно быть только три чистых поля:name,descriptionа такжеcreatorId.

Обратите внимание, что для обеспечения чистоты метода Сервиса (удобного для повторного использования) мы не идем в Сессию в Сервисе для получения пользовательских данных вошедшего в данный момент пользователя, а передаем пользователя в Сервис в Контроллере .

Модифицированный код примерно такой:

// ~ /controller/project.js
const createRule = {
    name: {
        ...
        // 去掉两边的空格,默认是 false
        trim: true
    },
    ...
};

async create() {
    const ctx = this.ctx;
    // extract 是自定义的根据 rule 规则抽取有效数据的方法
    const data = ctx.helper.extract(ctx.request.body, createRule);
    ctx.validate(createRule, data);
    // 设置创建者
    data.creatorId = ctx.session.user.id;
    const id = await ctx.service.project.create(data);
}

Код для создания проекта выглядит «безупречно», но кажется, что работы немного меньше.

Проанализируем реальную ситуацию: даже если разрабатывается новый интерфейс, код интерфейса постепенно совершенствуется, и за это время может много раз подвергаться рефакторингу — это общий статус-кво в реальном процессе разработки.

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

Должно быть много инструментов для сохранения тестовых данных в локальной разработке в виде тестовых случаев, таких как инструмент Postman, который чаще всего используется бэкенд-инженерами-разработчиками. Сегодня я также рекомендую вам инструментNEI.

NEI — это платформа управления интерфейсом, которая в настоящее время разрабатывается и поддерживается NetEase Cloud Music. На платформе NEI вы можете определить контракт интерфейса HTTP, а также создать тестовые примеры для определенных интерфейсов.Во время теста он будет автоматически проверять, совпадают ли типы полей в ответе интерфейса, отсутствуют ли поля, поля избыточны и т. д. Сэкономьте много драгоценного времени для разработчиков. Для получения дополнительной информации о NEI обратитесь к его официальной документации и руководствам.

При тестировании интерфейса «создать проект», описанного в этом разделе, не следует обращать внимание на конкретную логику реализации бэкэнда, поэтому теоретически нам необходимо создать следующие тестовые случаи:

  • Поля не отправляются.
  • отправить толькоnameполе, но его значение недопустимо. Существует три типа незаконных ситуаций:
    • Пустая строка, включая все пробелы.
    • Длина превышает 500.
    • Тип не строка.
  • отправить толькоnameполе, его значение допустимо.
  • отправить толькоdescriptionполе, значение которого неверно.
  • отправить толькоdescriptionполе, его значение допустимо.
  • Отправитьnameа такжеdescriptionполя, все их значения недопустимы.
  • Отправитьnameа такжеdescriptionполя, все их значения допустимы.
  • Отправитьnameа такжеdescriptionполе,nameЦенность законно,descriptionЗначение является незаконным.
  • Отправитьnameа такжеdescriptionполе,nameЗначение является незаконным,descriptionЗначение является законным.
  • Помимо отправкиnameа такжеdescriptionВ дополнение к полям отправляются и другие поля.
  • Отправляются только другие поля.

Из-за неопределенности фактической реализации кода теоретически невозможно полностью полагаться на тестовые примеры для обеспечения корректности интерфейса. В реальном процессе разработки невозможно создать тест-кейсы по вышеописанной логике.

Нам просто нужно создать несколько ключевых тестовых случаев. Для этого интерфейса «создать проект» есть один вариант использования, который может быть успешно создан, и один или два варианта использования, которые не удалось создать из-за отправки недопустимых значений.

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

элемент запроса

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

Согласно спецификациям, о которых мы договорились ранее:

  • Запросите один элемент по идентификатору элемента, адрес интерфейсаGET /api/projects/:id:idВызывается параметр пути (Path Variable), указывающий id проекта.
  • Запросите список проектов пользователя, адрес интерфейсаGET /api/projects.

Давайте проанализируем первый интерфейс, то есть запрос одного элемента по идентификатору элемента, он должен делать:

  • Сначала определите, является ли id целым числом, если нет, вернитесь напрямую参数无效. Здесь следует отметить, что тип самого параметра пути — это строка, представляющая собой целое число типа строка, которое необходимо преобразовать.
  • Затем возьмите этот id и зайдите в базу данных, чтобы узнать, есть ли этот элемент, вернуть, если есть, или вернуть, если нет参数无效.

Как вы заметили, когда id не может быть преобразован в целое число или в базе нет элемента с таким id, мы все возвращаемся参数无效это сообщение об ошибке. Кто-то может спросить, а почему бы не вернуть очень четкое сообщение об ошибке? Таким образом, устранение неполадок происходит быстро, и разработчики клиентов или пользователи продукта могут видеть это более четко.

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

Вернемся к интерфейсу элемента запроса. Выше были проанализированы две логические ветки, но была забыта очень серьезная проблема, то есть проект с таким id существует в базе данных, но авторизованный в данный момент пользователь не имеет прав на его просмотр. В back-end разработке есть два основных понятия, одно называется аутентификацией (аутентификацией), другое называется аутентификацией (авторизацией). Проблема, с которой мы только что столкнулись, — это проблема аутентификации, и ресурс должен быть аутентифицирован. Поскольку существует множество операций, требующих оценки разрешений, таких как запрос, обновление, удаление и т. д., самая базовая логика аутентификации (поскольку проблема с разрешениями также связана с определенной бизнес-логикой, может быть извлечена только из самой базовой логики аутентификации) , Основная общая логика) разделена на один слой, в Node.js мы называем это промежуточным ПО. Общие фреймворки также предоставляют такое промежуточное ПО, например, eggjs, поддерживающееegg-cancan.

С приведенным выше анализом нетрудно написать следующий код:

// ~ /controller/project.js
async get() {
    const ctx = this.ctx;
    const id = parseInt(ctx.params.id, 10);
    if (Number.isNaN(id)) {
        // wrapResponse 是自定义封装方法,此处省略实现
        ctx.body = this.wrapResponse(id, 'BAD_REQUEST');
    } else {
        // canReadProject 方法会去调用鉴权中间件的方法,此处省略实现
        const canRead = await this.canReadProject(id);
        if (canRead) {
            const project = await ctx.service.project.get(id);
            ctx.body = this.wrapResponse(project);
        } else {
            ctx.body = this.wrapResponse(id, 'BAD_REQUEST');
        }
    }
}

Давайте посмотрим на второй интерфейс, который должен запрашивать список элементов пользователя. Первое, что нужно понять, это то, что нужно бизнесу, то есть какие элементы видны пользователям. Мы дали понять в самом начале: проект могут видеть только участники, администраторы и создатели проекта. Для связи между проектами и пользователями используется отдельная таблица.project_userЧтобы сэкономить, давайте рассмотрим дизайн этой таблицы:

CREATE TABLE `project_user` (
    `role`  TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户角色0-成员;9-管理员;10-创建者',
    ...
)

осторожностьroleОписание комментария поля, его значение — число, каждое число представляет собой другую роль, например10Указывает создателя этого элемента. Внимательные друзья могли заметить, что когда мы ранее анализировали интерфейс «Создать проект», мы не анализировали, что при создании проекта мы собиралисьprojectПри вставке записи в таблицу также необходимоproject_userПлагин таблицы — это запись, которая представляет отношения между элементом и создателем. Некоторые друзья могут возразить, что эта запись на самом деле избыточна, потому чтоprojectуже в таблицеcreatorIdполе для записи отношений между проектом и создателем.

Так тебе нужно идти вproject_userВставить эту запись в таблицу? Это может быть вопрос о том, что доброжелательный увидит доброжелательный, а мудрый увидит мудрость. Что касается этого требования, которое мы объяснили сегодня, согласноproject_userстолroleЛучше всего вставить эту запись.Иногда может быть полезно правильно дублировать некоторые данные, и, возможно, это также может улучшить производительность запросов к базе данных.

Согласно приведенному выше анализу, чтобы запросить список проектов пользователя, вам необходимо запросить две таблицы, прежде всего, в соответствии с идентификатором пользователя.project_userстол обрабатывать всеuserIdУзнайте идентификатор проекта (то есть projectId) идентификатора пользователя, результатом будет набор массивов, а затем в соответствии с этим набором идентификаторов проекта пакетный переход кprojectТаблица может проверить проект. Конкретный код не будет продемонстрирован.

Следует отметить еще одну деталь:projectВ таблице есть одинdeletedAtПоле, указывающее, когда элемент был удален. Для удаления элементов мы решили использовать схему маркировки полей вместо прямого физического удаления данных. При возврате данных элемента клиенту вам необходимо отфильтровать этоdeletedAtПоле, это поле, используемое внутренней логикой бэкенда, и разработчику клиента не обязательно его видеть. Это общая логика обработки, которую можно инкапсулировать в метод.

Наконец, не забывайте, нам также нужно добавить тестовые примеры к этим двум интерфейсам:

  • Запрос тестовых случаев для одного проекта по id:
    • Отправить нечисловую строку.
    • Отправить несуществующий идентификатор.
    • Отправьте правильный идентификатор.
    • Отправляется правильный идентификатор, но у пользователя нет разрешения на его просмотр.
  • Тестовый пример для запроса списка элементов пользователя:
    • Хотя для реализации требуется много логики, поскольку нет необходимости отправлять какие-либо параметры, достаточно написать вариант использования, который может правильно возвращать данные элемента.

Изменить элемент

Первый шаг - проанализировать бизнес-требования и изменить эту операцию, которая тесно связана с конкретной бизнес-логикой. Например, только создатель проекта может изменить проект, или все участники проекта могут изменить проект. Наши требования также были описаны в начале «Только администраторы и создатели проекта могут изменить проект».

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

у нас также есть столproject_usertable, поэтому должна быть такая страница, на которой можно задать участников проекта, например добавить пользователя в проект или назначить пользователя администратором. Хотя разумнее разработать отдельный интерфейс для этой операции, чтобы отличать ее от операции «изменить имя и описание проекта», код также понятнее для написания.

Интерфейс «Изменить элемент», который будет реализован в этом разделе, поддерживает оба сценария. Согласно предыдущему анализу, адрес интерфейса должен бытьPATCH /api/project/:id. Давайте проанализируем логику кода ниже:

  • Клиенты обычно отправляют только те поля, которые вы хотите изменить, поэтому, если поле отсутствует, напримерname, вы не должны обновлять его, потому что интерфейс, который мы хотим реализовать, может включать две таблицы, что может сократить операции с базой данных.Вы должны знать, что работа с базой данных очень дорогая.Похоже на работу с объектами DOM, этого можно избежать, чтобы избежать.
  • Добавление участников проекта и настройка администраторов могут выполняться пакетно, поэтому данные, отправляемые клиентом, должны представлять собой массив, например следующий:
{
    "members": [],
    "admins": []
}

так,roleЭта информация может быть прозрачной для клиента. При разработке клиента не нужно задавать это значение. Это может сэкономить некоторые затраты на связь и сэкономить некоторые затраты на связь. В противном случае вам нужно указать клиенту добавлять участников при добавлении участников.roleЗначение поля устанавливается равным 0. При настройке администратора должно бытьroleЗначение установлено равным 9, что не только требует затрат на связь, но и легко приводит к ошибкам.

  • Если данные, отправленные клиентом, содержатmembersилиadminsполе, которое необходимо обновить в это времяproject_userтаблице необходимо учитывать следующие ситуации:
    • еслиmembersявляется пустым массивом, что означает, что все члены элемента удалены.
    • еслиmembersЕсли это непустой массив, вам необходимо вычислить, какие элементы удаляются, а какие добавляются, а затем обновлять базу данных в пакетном режиме.
    • adminsа такжеmembersЛогика та же и здесь повторяться не буду.
    • Кроме того, пользователь может быть только участником или администратором, то есть пользователь не может отображаться в обоихmembersа такжеadminsв массиве. Хотя этой ситуации можно избежать, работая через интерфейс пользовательского интерфейса, сервер не должен полностью доверять данным, отправленным клиентом, поскольку данные запроса могут быть подделаны инструментами. Очевидно,membersа такжеadminsСоздатель элемента также не должен отображаться в файле .

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

Точно так же вам нужно добавить соответствующие тестовые случаи для этого интерфейса, ключевые из них:

  • Идентификатор элемента недействителен.
  • Идентификатор проекта действителен, но у пользователя нет разрешения на его изменение.
  • Название и описание предмета являются законными.
  • Название и описание предмета являются незаконными.
  • members,adminsДанные легальны.
  • members,adminsПользователь, не зарегистрированный в системе, появляется в .
  • members,adminsТот же пользователь появляется в .
  • members,adminsСоздатель появляется в .

удалить пункт

Согласно предыдущему анализу адрес интерфейса удаленного элементаDELETE /api/projects/:id, и вместо физического удаления записей мы переходим кdeletedAtПолевое задание. Значение в этом поле указывает на то, что элемент был удален.

Код Project Controller на стороне сервера, просто вызовите Project ServiceupdateМетода достаточно.Конечно, не забудьте аутентифицировать проект.Наши требования оговаривали, что только создатель проекта может удалить проект.Окончательный код примерно такой:

// ~ /controller/project.js
async remove() {
    const ctx = this.ctx;
    const id = parseInt(ctx.params.id, 10);
    if (Number.isNaN(id)) {
        ctx.body = this.wrapResponse(id, 'BAD_REQUEST');
    } else {
        const canDelete = await this.canDeleteProject(id);
        if (canDelete) {
            // 删除时更新 deletedAt 字段,不是真正物理删除
            const result = await ctx.service.project.update({
                id,
                deletedAt: new Date()
            });
            if (result.success) {
                ctx.body = this.wrapResponse({ id });
            } else {
                ctx.body = this.wrapResponse(
                    {},
                    result.resType || 'SERVER_ERROR'
                );
            }
        } else {
            ctx.body = this.wrapResponse({}, 'BAD_REQUEST');
        }
    }
}

Приведенный выше код обновляется толькоdeletedAtполе.还有一个细节问题我们没有考虑,就是删除项目的时候,要不要把project_userВ этом проекте и удалите все связанные записи? В противном случае проект был удален, эти записи также бесполезны, сохраняйте базу данных не занята пространством? Если пользователь является очень большим количеством продукта, эта проблема должна быть решена, то, вероятно, не будет использоватьdeletedAtполе, чтобы отметить статус удаляемого элемента, скорее всего, другие сценарии. Для небольших проектов при удалении проекта удалять его или нетproject_userНеважно, какие записи, просто посмотрите на реальную ситуацию и примите решение сейчас. Вообще говоря, лучше не удалять его, что может снизить нагрузку при восстановлении проекта.

Интерфейс «Обновление проекта», продемонстрированный в этой статье, уже обрабатывает логику участников и администраторов проекта, поэтому для удаления этих записей требуется изменить очень мало кода:

const result = await ctx.service.project.update({
    id,
    deletedAt: new Date(),
    // 设置成空数组表示将成员记录全部删除
    members: [],
    admins: []
});

Наконец, в этот интерфейс необходимо добавить два ключевых тестовых случая:

  • Идентификатор элемента недействителен.
  • Идентификатор проекта действителен, но у пользователя нет разрешения на его удаление.

резюме

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

Будь то фронтенд-инженер или бэкенд-инженер, если вы хотите эффективно разрабатывать высококачественные API-интерфейсы, вы должны сделать следующее:

  • Наточите нож и нарубите дров по ошибке.Прежде чем начать программировать, разберитесь во всех ответвлениях бизнес-логики. Хотя некоторые ветки логики недоступны при взаимодействии с пользовательским интерфейсом, во избежание ненужных проблем все ветки логики должны обрабатываться при написании кода.
  • Бэкэнд не может доверять данным, присланным клиентом, и старается быть максимально отделенным от разработки страницы. Поскольку данные могут быть подделаны, внутренняя часть должна выполнять проверку данных, а внешняя проверка данных предназначена только для улучшения взаимодействия с пользователем. Например, при пополнении следует судить о том, больше ли значение нуля, иначе начисление отрицательного числа является серьезным сбоем в сети.
  • В дополнение к односторонней логической ветви, мы также должны рассмотреть логическую ветвь в ситуации комбинирования, которая наиболее подвержена ошибкам, а ситуация комбинирования будет очень сложной. Здесь могут быть некоторые компромиссы и компромиссы в зависимости от важности системы.
  • Пишите тест-кейсы. Это может быть код модульного теста или вариант использования вызова интерфейса в виде http. Времени на написание тест-кейсов уходит не меньше, чем на код бизнес-логики, в важных системах рекомендуется строго реализовывать это звено.

Многие люди, которые только что поработали какое-то время, спрашивают меня, как мне улучшить свои способности? Из-за уровня языка программирования они чувствуют, что освоили его. Давайте представим, какие факторы будут учитываться при оценке способностей человека? Одним из них является знание, о котором обычно можно спросить во время интервью. Во-вторых, при составлении требований необходимо учитывать такие параметры, как сложность проблемы, количество вызванных ошибок, сотрудничество с коллегами и т. д. Все это места, где вы можете доказать свои способности. Имеется в виду могущественный человек. Так же, как и описанная в этой статье разработка API-интерфейса, если разработанный API-интерфейс реализован очень правильно и не имеет лазеек, то вы способный человек в сердцах коллег-клиентов.

постскриптум

Когда я закончил первый набросок этой статьи, все подумали, что это учебник, который научит вас разрабатывать API-интерфейсы, потому что он был написан очень подробно, в основном до практического применения. Эта цель является основной, но не совсем целью этой статьи. Конечная цель этой статьи — доказать, сколько усилий требуется, чтобы сделать что-то до крайности, а также ответить на вопрос, как улучшить свои способности.

Эта статья была опубликована сКоманда внешнего интерфейса NetEase Cloud Music, Любое несанкционированное воспроизведение статьи запрещено. Мы всегда нанимаем, если вы готовы сменить работу и вам нравится облачная музыка, тоПрисоединяйтесь к нам!