Краткое изложение стандартов кодирования твердости
Краткое изложение стандартов кодирования твердости

На прошлой неделе была завершена видеозапись спецификаций кодирования Solidity, которая была загружена на Bilibili, Youtube и видеоаккаунт. Всего он разделен на 6 секций, а адрес сбора на станции B:

https://space.bilibili.com/60539794/channel/collectiondetail?sid=3780183

Чтобы облегчить некоторым студентам, которые привыкли читать статьи, за последние два дня я составил текстовую версию. Ниже приводится краткое изложение стандартов кодирования Solidity.

Зачем нужны стандарты кодирования

Мы знаем, что каждый язык кодирования будет иметь свои собственные спецификации кодирования. А как насчет зачем нужны стандарты кодирования? Я обобщил следующие причины:

  1. Улучшить читаемость кода: кодирование Стандарты делают структуру кода более понятной,Именование становится более интуитивным,Логика стала более понятной,Это облегчает понимание и поддержку кода другими разработчиками (включая самих разработчиков).
  2. Содействие командной работе: существовать Команда развивается,Унифицированная спецификация кодирования позволяет различным разработчикам писать код в едином стиле.,Избегайте путаницы и недоразумений, вызванных различиями в стилях кодирования.,Способствует сотрудничеству и интеграции кода среди членов команды.
  3. Уменьшите количество ошибок: Передовая практика обычно включает в себя некоторые передовые практики.,Например, правила именования переменных, код Комментарий и т. д. Эти спецификация помогает разработчикам избежать типичных ошибок.,Повышайте надежность и надежность кода.
  4. Улучшение ремонтопригодности: Когда стиль кода един,Объем работы по сопровождению кода значительно сократится. Разработчики могут быстро понять код и логику,Вносить изменения и расширения,Уменьшите затраты на техническое обслуживание и трудности.
  5. Помогает при проверке кода: Спецификация кодирования делает проверку кода более эффективной,Рецензенты могут сосредоточиться на логике и функциональности кода.,Вместо того, чтобы тратить время на стиль кодирования.
  6. Улучшите качество кода: Унифицированные спецификации обычно сопровождаются опасениями по поводу качества кода. например, масштабируемость кода, тестируемость и т. д. Эти спецификация помогает писать высококачественный код.
  7. Следуйте отраслевым стандартам: кодирование Спецификации обычно разрабатываются на основе отраслевых стандартов или консенсуса сообщества.,Соблюдение этической спецификации гарантирует совместимость кода с другими проектами и библиотеками с открытым исходным кодом.,Поощряйте повторное использование и обмен кодом.

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

именование файлов

Наш первый шаг — создать исходный файл,Итак, первый шаг, с которого я хочу начать, — это именование файлов. И оименование файлов этой части спецификации кодирования,Я могу свести это к четырем пунктам:

  • Используйте номенклатуру Camel Case
  • Соблюдайте соответствие имени компонента контракта.
  • В каждом файле определен только один компонент контракта.
  • interface Дополнительная капитализация имен I как префикс

В официальной документации Solidity перечислено несколько различных стилей именования:

  • b (single lowercase letter)
  • B (single uppercase letter)
  • lowercase
  • UPPERCASE
  • UPPER_CASE_WITH_UNDERSCORES
  • CapitalizedWords (or CapWords)
  • mixedCase (differs from CapitalizedWords by initial lowercase character!)

Прежде всего, так называемая номенклатура верблюжьих дел на самом деле CapitalizedWords Этот стиль номенклатуры представляет собой комбинацию слов с заглавной буквой. и mixedCase Также известна как номенклатура CamelCase.

Компонент контракта на самом деле interfacelibrarycontract。Требуется имя файла Соблюдайте соответствие имени компонента контракта., что означает, что он должен соответствовать определению в файле. interface/library/contract Имя то же самое. Например, имя файла UniswapV3Pool.sol,определено в файлеиз contract Имя UniswapV3Pool

Определяйте только один компонент контракта в каждом файле, то есть не определяйте в файле несколько компонентов контракта одновременно. Например, ядро ​​Uniswap v3 определяет несколько интерфейсов классов обратного вызова:

  • IUniswapV3FlashCallback
  • IUniswapV3MintCallback
  • IUniswapV3SwapCallback

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

Язык кода:javascript
копировать
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0

interface IUniswapV3FlashCallback {
  ...
}

interface IUniswapV3MintCallback {
  ...
}

interface IUniswapV3SwapCallback {
  ...
}

С грамматической точки зрения это не является ошибкой. Однако Uniswap делит его на три файла следующим образом:

  • IUniswapV3FlashCallback.sol
  • IUniswapV3MintCallback.sol
  • IUniswapV3SwapCallback.sol

Это означает, что в каждом файле определен только один компонент контракта.

Кроме того, в приведенном выше примере также используется последнее соглашение об именах, то есть interface Дополнительная капитализация имен I как префикс。тыможно увидеть Эти interface Все большими буквами I в качестве префикса, в то время как library и contract Такой префикса не будет. Следуя этой спецификации, вы можете напрямую скачать с именования. файлы различают какие из них interface .

Макет файла

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

Например, существует несколько interface , это могут быть interface Файлы в совокупности подразделяются на interfaces каталог. И несколько library Документы можно разделить на libraries каталог. Абстрактные контракты могут быть размещены в base или utils каталог. Большинство основных контрактов, которые необходимо развернуть, размещаются непосредственно в contracts или src в домашнем каталоге.

кроме того,Если файлов много, каталог можно разделить еще раз. например,Uniswap/v3-core из interfaces Он далее разделен ниже callback и pool два подкаталога.

Мне нравится OpenZeppelin Этот тип библиотеки отличается,Это скорее классификация каталогов, основанная на функциональных модулях.,Различные файлы контрактов разделены на разные функциональные каталоги. существуют Эти функции каталога,Большинство из них не разделены на каталоги по типам компонентов контракта. например,access Поместите его прямо в каталог IAccessControl.sol,Как только я приду,не так уж и много interface,Во-вторых,Расположение каталогов больше основано на функциональных настройках. Но у него все еще есть interfaces В каталоге хранятся все файлы интерфейса.

Заявление о контракте

Следующий,Приступим к вводу спецификации внутреннего кодирования документа. Этот раздел.,Давайте сначала подведем итог части «Заявление о контракте».

Во-первых, в первой строке мы должны объявить SPDX-License-Identifier,Укажите, что будет использоваться лицензия. Хотя я этого не заявляю,Компиляция не сообщит об ошибке,Но будут предупреждения,Чтобы устранить предупреждение,так Нам лучше составить это заявление。

Во второй строке используйте pragma Заявление в поддержку из solidity Версия. Что касается этого, я полагаю, что это зависит от ситуации. в случае Рекомендуется объявить интерфейс, библиотеку и абстрактные контракты как совместимые версии, например: ^0.8.0。Если необходимо развернутьиз Рекомендуется объявить основной контракт как фиксированную версию.。об этом,Uniswap/v4-core Это хороший пример. его основной контракт PoolManager из pragma Заявление заключается в следующем:

Язык кода:javascript
копировать
pragma solidity 0.8.26

Как видите, она заявлена ​​как фиксированная версия. 0.8.26

И все Интерфейс, библиотека и абстрактные контракты объявлены как совместимые версии, да. ^0.8.0,да ^0.8.24。объявлен как ^0.8.24 из-за использования этой версии обычно начинает поддерживать некоторые функции.

И о import Частично есть два основных предложения: одно — указать имя для импорта, другое — указать; import из Когда сторонний контракт хранит несколько версий,Рекомендуется указать номер версии。

Просто посмотрите на следующие примеры:

Язык кода:javascript
копировать
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20} from "@openzeppelin/contracts@0.5.2/token/ERC20/ERC20.sol";

Вышеупомянутые три import Из метода записи первый из них наиболее часто используется многими людьми (включая меня) и заключается в прямом импорте всего файла. Второй тип добавляет конкретное имя импортируемого контракта. Это то, что я говорил ранее. Рекомендуется указать имя для импорта. Третий тип существует contracts добавлено позже @0.5.2 из, чтобы указать конкретный номер версии из, которую нужно импортировать.

Этот третий способ записи — наш наиболее рекомендуемый метод импорта. Потому что OpenZeppelin выпустил несколько разных версий библиотек.

но,Если вы хотите импортировать сторонний контракт и существует несколько его версий,Тогда нет необходимости добавлять объявление версии. Например.,@uniswap/v3-core Толькоиметьверсияиз Библиотека,Тогда нет необходимости указывать версию при импорте контракта библиотеки.,Следующее:

Язык кода:javascript
копировать
import {IUniswapV3Pool} from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";

interface

interface Это контрактное взаимодействие, которое также используется во внешнем и внутреннем взаимодействии. abi из исходного кода, поэтому, когда мы пишем настоящий код, мы обычно сначала определяем его интерфейс. В этом разделе пойдет речь interface Каковы стандарты кодирования при кодировании.

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

  • Errors
  • Events
  • Enums
  • Structs
  • Functions

Сначала определите Errorserror Тип находится в 0.8.4 только начал поддерживать из, так что если interface там есть определение error,Предлагаемое заявление pragma если указано как минимум ^0.8.4。И заявление error При именовании рекомендуется использовать метод именования в большом верблюжьем регистре. Если есть параметры, для параметров используется метод именования в маленьком верблюжьем регистре. Пример:

Язык кода:javascript
копировать
error ZeroAddress();
error InvalidAddress(address addr);

Далее определите Events。определенныйизсобытиеимя Используйте номенклатуру Camel Case,Параметры событий также используют номенклатуру верблюжьего регистра. кроме того,Если параметров много,,Рекомендуется каждый параметр располагать на отдельной строке. Пример:

Язык кода:javascript
копировать
event Transfer(address indexed from, address indexed to, uint value);
event TransferBatch(
    address indexed operator,
    address indexed from,
    address indexed to,
    uint256[] ids,
    uint256[] values
);

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

Далее, если есть из, его можно определить Enums,То есть тип перечисления. Название также используется в номенклатуре Camel Case.,Пример:

Язык кода:javascript
копировать
enum OrderStatus {
    Pending,
    Shipped,
    Delivered,
    Canceled
}

После этого вы можете определить Structs,Такова структура. Структура из Название Используйте номенклатуру Camel Case,В поле «из» используется небольшая номенклатура верблюжьего регистра.,Пример:

Язык кода:javascript
копировать
struct PopulatedTick {
    int24 tick;
    int128 liquidityNet;
    uint128 liquidityGross;
}

Затем вы можете определить Functions .Но функцию можно подразделить и объявить в следующем порядке:

  • External functions with payable
  • External functions
  • External functions with view
  • External functions with pure

То есть мы interface При определении нескольких функций рекомендуется располагать этифункции в следующем порядке. Вот несколько примеров:

Язык кода:javascript
копировать
// external function with payable
function burn(uint256 tokenId) external payable;
function createAndInitializePoolIfNecessary(
    address token0,
    address token1,
    uint24 fee,
    uint160 sqrtPriceX96
) external payable returns (address pool);

// external function
function mint(
    address recipient,
    int24 tickLower,
    int24 tickUpper,
    uint128 amount,
    bytes calldata data
) external returns (uint256 amount0, uint256 amount1);

// external function with view
function getPopulatedTicksInWord(address pool, int16 tickBitmapIndex)
    external
    view
    returns (PolulatedTick[] memory populatedTicks);

function ticks(int24 tick)
    external
    view
    returns (
        uint128 liquidityGross,
        int128 liquidityNet,
        uint256 feeGrowthOutside0X128,
        uint256 feeGrowthOutside1X128,
        int56 tickCumulativeOutside,
        uint160 secondsPerLiquidityOutsideX128,
        uint32 secondsOutside,
        bool initialized
    );
    
// external function with pure
function mulDiv(uint a, uint b, uint c) external pure returns (uint d);

Помимо заказа, есть некоторые детали, о которых нужно поговорить.

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

Во-вторых,возвращатьсяможно увидетьиметьнет то же самоеизформат новой строки。createAndInitializePoolIfNecessary и mint эти двоефункция Вседа Параметры по одной строке каждый。getPopulatedTicksInWord затем становится модификатором функции returns Заявления по одной строке каждое,Это также новая строка метода записи. наконец,ticks Функция: Список возвращаемых параметров разбит на отдельную строку для каждого возвращаемого параметра. Это также распространенный метод записи, когда имеется много возвращаемых параметров.

library

Далее поговорим о library изиспользование.

library Переменные состояния здесь не могут быть определены, поэтому library Фактически, это лицо без гражданства.

Синтаксически говоря, библиотека Могут быть определены различные функции видимости, но в практических приложениях они обычно определяются только internal и private изфункция, редко определяемая, внешне видимая из external и public функция. если library Определено, что внешняя видимая функция, при ее развертывании, также будет и только внутренней функцией. library нет то же самое. Конечно, это другая тема.

library Также можно определить постоянные errors。иметь些当纯Только定义了постоянныйиз library,например Uniswap/v4-periphery Есть один в library следующее:

Язык кода:javascript
копировать
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

/// @title Action Constants
/// @notice Common constants used in actions
/// @dev Constants are gas efficient alternatives to their literal values
library ActionConstants {
    /// @notice used to signal that an action should use the input value of the open delta on the pool manager
    /// or of the balance that the contract holds
    uint128 internal constant OPEN_DELTA = 0;
    /// @notice used to signal that an action should use the contract's entire balance of a currency
    /// This value is equivalent to 1<<255, i.e. a singular 1 in the most significant bit.
    uint256 internal constant CONTRACT_BALANCE = 0x8000000000000000000000000000000000000000000000000000000000000000;

    /// @notice used to signal that the recipient of an action should be the msgSender
    address internal constant MSG_SENDER = address(1);

    /// @notice used to signal that the recipient of an action should be the address(this)
    address internal constant ADDRESS_THIS = address(2);
}

Как видите, это ActionConstants Это просто определение 4 Просто константа.

library Большинство сценариев использованияизна самом деледаконкретномутипиз Инкапсулируйте расширенные функции。UniswapV3Pool В начале тела кода есть куча объявлений. using for,Как показано ниже:

Язык кода:javascript
копировать
contract UniswapV3Pool is IUniswapV3Pool, NoDelegateCall {
    using LowGasSafeMath for uint256;
    using LowGasSafeMath for int256;
    using SafeCast for uint256;
    using SafeCast for int256;
    using Tick for mapping(int24 => Tick.Info);
    using TickBitmap for mapping(int16 => uint256);
    using Position for mapping(bytes32 => Position.Info);
    using Position for Position.Info;
    using Oracle for Oracle.Observation[65535];
  ...
}

Эти using обратно из libraries Функция инкапсуляции в основном правильная for типиз Расширение функции。например,LowGasSafeMath Можно понять, что это правильно uint256 Тип расширения функции, первый параметр, определенный в нем, — это функция. uint256 типиз。LowGasSafeMath Существует определенный add функция,следующее:

Язык кода:javascript
копировать
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
    require((z = x + y) >= x);
}

существовать UniswapV3Pool привыкший LowGasSafeMath из add На самом деле существует множество функциональных мест, например следующие:

Язык кода:javascript
копировать
uint256 balance0Before = balance0();
require(balance0Before.add(uint256(amount0)) <= balance0(), 'IIA');

в,balance0Before.add(uint256(amount0)) На самом деле это называется LowGasSafeMath из add Функция. и,Вызывается через этот синтаксический сахар из оболочки,Не значит ли это, что оно сталоuint256 Сам этот тип расширяется функцией, поэтому говорят library Его можно понимать как функциональное расширение определенного типа.

Наконец, хотя library Нет прямого доступа к переменным состояния,нопеременные Состояние может быть передано косвенно через метод функции. library Чтобы получить доступ к функции, просто объявите параметр функции как storage Вот и все. например library Position,заявил get и update Функция, первый параметр обеих функций берется storage Модификация, ее основной код следующий:

Язык кода:javascript
копировать
function get(
    mapping(bytes32 => Info) storage self,
    address owner,
    int24 tickLower,
    int24 tickUpper
) internal view returns (Position.Info storage position) {
    position = self[keccak256(abi.encodePacked(owner, tickLower, tickUpper))];
}

function update(
    Info storage self,
    int128 liquidityDelta,
    uint256 feeGrowthInside0X128,
    uint256 feeGrowthInside1X128
) internal {
  ...
  // update the position
    if (liquidityDelta != 0) self.liquidity = liquidityNext;
    self.feeGrowthInside0LastX128 = feeGrowthInside0X128;
    self.feeGrowthInside1LastX128 = feeGrowthInside1X128;
    if (tokensOwed0 > 0 || tokensOwed1 > 0) {
        // overflow is acceptable, have to withdraw before you hit type(uint128).max fees
        self.tokensOwed0 += tokensOwed0;
        self.tokensOwed1 += tokensOwed1;
    }
}

get функцияиз self Параметры storage из, а тип данных mapping из, означает, что параметр, переданный в из, является переменным состояние, и возвращаемое значение также storage из, так что вернись из position Фактически, это тоже переменная состояния.

update функцияиз self Параметры тоже такие же storage из, также переменные состояния,существовать код внутри self Модификации также будут напрямую отражены в переменных состояниесуществовать в сети из-за изменения статуса.

contract

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

  • using for
  • постоянный
  • переменные состояния
  • Events
  • Errors
  • Modifiers
  • Functions

Во-первых, если вам нужно использовать библиотеку, используйте ее в первую очередь. using for Объявите используемую библиотеку.

Далее определитепостоянный。постоянныйвозвращатьсяразделен на public постоянныйи private Константы, обычно рекомендуется сначала их объявить. public из Пересчет private из。кроме того,постоянный именуется заглавными буквами с подчеркиванием и з,так:UPPER_CASE_WITH_UNDERSCORES

После объявления констант вы можете объявить переменные состояния. Переменные состояния также объявляются первыми. public из, то объяви private из。жизньимя则通常采用小驼峰式жизньимя Закон。кроме того,private изпеременные Состояние обычно также добавляет начальное подчеркивание к и public изотдельные переменные。Пример:

Язык кода:javascript
копировать
// public state variable
uint256 public totalSupply;
// private state variable
address private _owner;
mapping(address => uint256) private _balanceOf;

Впоследствии, если есть событие, которое необходимо объявить, объявите это событие. Впоследствии, если есть ошибка, которую необходимо объявить, объявите об ошибке.

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

Далее, есть заявление Настроитьиз. modifiers .кроме того,modifier в именовании используется метод именования верблюжьего регистра. Ниже приведен пример:

Язык кода:javascript
копировать
modifier onlyOwner() {
    if(msg.sender != _owner) revert OwnableUnauthorizedAccount(msg.sender);
    _;
}

наконец,Это просто набор определений функций, потому что их много.,такнасвозвращаться Необходимо реорганизовать,Его можно расположить в следующем порядке:

  • структурафункция
  • receive функция
  • fallback функция
  • external функция
    • external payable
    • external
    • external view
    • external pure
  • public функция
    • public payable
    • public
    • public view
    • public pure
  • internal функция
    • internal
    • internal view
    • internal pure
  • private функция
    • private
    • private view
    • private pure

Видно, что сначала определяется конструктор, а затем receive и fallback Функция обратного вызова, если не требуется, то она и не нужна.

После этого отсортируйте по видимости, порядок такой external、public、internal、private

Различные функции невидимости,А затем отсортировать по изменчивости,к external Если взять в качестве примера функции класса, то порядок следующий: payable функция,внешняя Писатьфункция, внешняя view функция, внешняя pure функция。Другая видимостьтипфункциятакжеда Та же причина。

Кроме того, относительно internal и private функцияизжизньимя,предположениеияиметьпеременные Как и в случае с состоянием, добавьте начальное подчеркивание как префикс,кивнешнийфункцияразличать。Пример:

Язык кода:javascript
копировать
// internal functions
function _transfer(address from, address to, uint256 value) internal {}
function _getBalance(address account) internal view returns (uint256) {}
function _tryAdd(uint256 a, uint256 b) internal pure returns (uint256) {}

// private functions
function _turn() private {}
function _isParsed() private view returns (bool) {}
function _canAdd(uint256 a, uint256 b) private pure returns (uint256) {}

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

  • Видимость (внешняя/публичная/внутренняя/частная)
  • Вариативность (платная/просмотр/чистая)
  • Virtual
  • Override
  • Пользовательские модификаторы

Просто посмотрите на следующий пример:

Язык кода:javascript
копировать
function mint() external payable virtual override onlyOwner {}

Выше речь идет о contract Частичное изкодирование нормативных рекомендаций.

Комментарий

наконецчат Комментарий。

первый,Что-то, что стоит запомнить:Хорошо из именования, т.е. Комментарий

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

Solidity поддерживает теги из Комментарий, включая следующие:

  • @title
  • @author
  • @notice
  • @dev
  • @param
  • @return
  • @inheritdoc
  • @custom:...

Описание этического тега «существовать» также объясняется в официальном документе, как показано ниже:

Официальная спецификация кодирования рекомендует для всех публичных интерфейсов добавлять полный из Комментарий.,То есть,нас可к Давать interface Добавить полный Комментарий. Унисвап Как видите, это очень хорошая практика. Uniswap все interface Все очень полные из Комментариев.

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

  • https://etherscan.io/address/0xc00e94cb662c3520282e6f5717214004a7f26888#code

существуют интерактивные страницы, при нажатии кнопки «Одобрить» следующее:

Проверьте исходный код еще раз. approve функцияиз Комментарий:

Язык кода:javascript
копировать
/**
 * @notice Approve `spender` to transfer up to `amount` from `src`
 * @dev This will overwrite the approval amount for `spender`
 *  and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
 * @param spender The address of the account which may transfer tokens
 * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)
 * @return Whether or not the approval succeeded
 */
function approve(address spender, uint rawAmount) external returns (bool) {
    ...
}

Это можно увидеть,@notice@dev и @param из контента отображается блок браузера, интерактивная страница существует.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose