Stil Klavuzu
Giriş
Bu kılavuz, Solidity kodu yazmak için kodlama kuralları sağlamayı amaçlamaktadır. Bu kılavuz, yararlı kurallar bulundukça ve eski kurallar kullanılmaz hale geldikçe zaman içinde değişen bir belge olarak düşünülmelidir.
Birçok proje kendi stil kılavuzlarını uygulayabilir. Uyuşmazlık durumunda, projeye özgü stil kılavuzları önceliklidir.
Bu stil kılavuzunun yapısı ve içindeki önerilerin çoğu python’un pep8 stil kılavuzundan alınmıştır.
Bu kılavuzun amacı Solidity kodu yazmanın doğru yolu ya da en iyi yolunu göstermek değildir. Bu kılavuzun amacı tutarlılıktır. Python’un pep8 adlı kitabından bir alıntı bu kavramı iyi özetlemektedir.
Not
Stil rehberi tutarlılıkla ilgilidir. Bu stil rehberi ile tutarlılık önemlidir. Bir proje içindeki tutarlılık daha önemlidir. Bir modül veya fonksiyon içindeki tutarlılık ise en mühim olanıdır.
Ama en önemlisi: Ne zaman tutarsız olmanız gerektiğini bilmenizdir — bazen bu stil kılavuzu geçerli olmayabilir. Şüpheye düştüğünüzde, en iyi kararınızı verip yolunuza devam edin. Diğer örneklere bakın ve neyin en iyi göründüğüne karar verin. Ayrıca soru sormaktan çekinmeyin!
Kod Düzeni
Girintiler
Her girinti seviyesi için 4 boşluk kullanın.
Sekmeler(Tab) veya Boşluklar
Boşluklar en çok tercih edilen girinti oluşturma yöntemidir.
Tablar ve boşlukları karıştırmaktan kaçınmalısınız.
Boş Satırlar
Solidity kaynağındaki üst düzey bildirimleri iki boş satırla çevreleyin.
Yapın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
contract A {
// ...
}
contract B {
// ...
}
contract C {
// ...
}
Yapmayın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
contract A {
// ...
}
contract B {
// ...
}
contract C {
// ...
}
Bir sözleşme içinde fonksiyon tanımlarının etrafını tek bir boş satırla çevreleyin.
Birbiriyle ilişkili tek satırlık gruplar arasında boş satırlar atlanabilir ( abstract sözleşme için stub fonksiyonları gibi)
Yapın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;
abstract contract A {
function spam() public virtual pure;
function ham() public virtual pure;
}
contract B is A {
function spam() public pure override {
// ...
}
function ham() public pure override {
// ...
}
}
Yapmayın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;
abstract contract A {
function spam() virtual pure public;
function ham() public virtual pure;
}
contract B is A {
function spam() public pure override {
// ...
}
function ham() public pure override {
// ...
}
}
Maksimum Satır Uzunluğu
Tavsiye edilen maksimum satır uzunluğu 120 karakterdir.
Sarılmış(Wrapped) satırlar aşağıdaki yönergelere uygun olmalıdır.
İlk argüman açılış parantezine eklenmemelidir.
Bir ve yalnızca bir girinti kullanılmalıdır.
Her argüman kendi satırında yer almalıdır.
Sonlandırıcı öğe,
);
, tek başına son satıra yerleştirilmelidir.
Fonksiyon Çağrıları
Yapın:
thisFunctionCallIsReallyLong(
longArgument1,
longArgument2,
longArgument3
);
Yapmayın:
thisFunctionCallIsReallyLong(longArgument1,
longArgument2,
longArgument3
);
thisFunctionCallIsReallyLong(longArgument1,
longArgument2,
longArgument3
);
thisFunctionCallIsReallyLong(
longArgument1, longArgument2,
longArgument3
);
thisFunctionCallIsReallyLong(
longArgument1,
longArgument2,
longArgument3
);
thisFunctionCallIsReallyLong(
longArgument1,
longArgument2,
longArgument3);
Atama İfadeleri
Yapın:
thisIsALongNestedMapping[being][set][toSomeValue] = someFunction(
argument1,
argument2,
argument3,
argument4
);
Yapmayın:
thisIsALongNestedMapping[being][set][toSomeValue] = someFunction(argument1,
argument2,
argument3,
argument4);
Event Tanımları ve Event Emitterları
Yapın:
event LongAndLotsOfArgs(
address sender,
address recipient,
uint256 publicKey,
uint256 amount,
bytes32[] options
);
LongAndLotsOfArgs(
sender,
recipient,
publicKey,
amount,
options
);
Yapmayın:
event LongAndLotsOfArgs(address sender,
address recipient,
uint256 publicKey,
uint256 amount,
bytes32[] options);
LongAndLotsOfArgs(sender,
recipient,
publicKey,
amount,
options);
Kaynak Dosya Encoding
UTF-8 yada ASCII encoding tercih edilir.
Imports (İçe Aktarmalar)
İçe aktarma ifadeleri her zaman dosyanın en üstüne yerleştirilmelidir.
Yapın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
import "./Owned.sol";
contract A {
// ...
}
contract B is Owned {
// ...
}
Yapmayın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
contract A {
// ...
}
import "./Owned.sol";
contract B is Owned {
// ...
}
Fonksiyonların Sıralaması
Sıralandırma, okuyucuların hangi fonksiyonları çağırabileceklerini belirlemelerine ve constructor ve fallback tanımlamalarını daha kolay bulmalarına yardımcı olur.
Fonksiyonlar görünürlük durumlarına göre gruplandırılmalı ve sıralanmalıdır:
constructor
receive fonksiyon (eğer mevcutsa)
fallback fonksiyon (eğer mevcutsa)
external
public
internal
private
Bir gruplandırma yaparken, view
ve pure
fonksiyonlarını en sona yerleştirin.
Yapın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract A {
constructor() {
// ...
}
receive() external payable {
// ...
}
fallback() external {
// ...
}
// External functions
// ...
// External functions that are view
// ...
// External functions that are pure
// ...
// Public functions
// ...
// Internal functions
// ...
// Private functions
// ...
}
Yapmayın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract A {
// External functions
// ...
fallback() external {
// ...
}
receive() external payable {
// ...
}
// Private functions
// ...
// Public functions
// ...
constructor() {
// ...
}
// Internal functions
// ...
}
İfadelerde Boşluk Bırakma
Aşağıdaki durumlarda gereksiz boşluk bırakmaktan kaçının:
Tek satırlık fonksiyon tanımlamaları hariç olmak üzere, parantez, köşeli parantez veya ayraçların hemen içinde.
Yapın:
spam(ham[1], Coin({name: "ham"}));
Yapmayın:
spam( ham[ 1 ], Coin( { name: "ham" } ) );
İstisna:
function singleLine() public { spam(); }
Virgülden, noktalı virgülden hemen önce:
Yapın:
function spam(uint i, Coin coin) public;
Yapmayın:
function spam(uint i , Coin coin) public ;
Bir atama veya başka bir operatörün etrafında, diğeriyle hizalamak için birden fazla boşluk:
Yapın:
x = 1;
y = 2;
longVariable = 3;
Yapmayın:
x = 1;
y = 2;
longVariable = 3;
receive ve fallback fonksiyonlarına boşluk eklemeyin:
Yapın:
receive() external payable {
...
}
fallback() external {
...
}
Yapmayın:
receive () external payable {
...
}
fallback () external {
...
}
Kontrol Yapıları (Control Structures)
Bir sözleşmenin, kütüphanenin, fonksiyonların ve struct’ların gövdelerini belirten parantezler:
Bildirim (Declaration) ile aynı satırda açılmalıdır
Bildirimin başlangıcıyla aynı girinti seviyesinde kendi satırlarında kapanmalıdır.
Açılış parantezinden önce tek bir boşluk bırakılmalıdır.
Yapın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
contract Coin {
struct Bank {
address owner;
uint balance;
}
}
Yapmayın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
contract Coin
{
struct Bank {
address owner;
uint balance;
}
}
Aynı öneriler if
, else
, while
ve for
kontrol yapıları için de geçerlidir.
Ayrıca, if
, while
ve for
kontrol yapıları ile koşulu temsil eden parantez bloğu arasında tek bir boşluk ve koşullu parantez bloğu ile açılış parantezi arasında tek bir boşluk olmalıdır.
Yapın:
if (...) {
...
}
for (...) {
...
}
Yapmayın:
if (...)
{
...
}
while(...){
}
for (...) {
...;}
Gövdesi tek bir ifade içeren kontrol yapıları için, parantezleri atlamak eğer ifade tek bir satırda yer alıyorsa uygundur.
Yapın:
if (x < 10)
x += 1;
Yapmayın:
if (x < 10)
someArray.push(Coin({
name: 'spam',
value: 42
}));
Bir else
veya else if
ibaresi içeren if
blokları için, else
ibaresi if
ibaresinin kapanış paranteziyle aynı satıra yerleştirilmelidir. Bu, diğer blok benzeri yapıların kurallarına kıyasla bir istisnadır.
Yapın:
if (x < 3) {
x += 1;
} else if (x > 7) {
x -= 1;
} else {
x = 5;
}
if (x < 3)
x += 1;
else
x -= 1;
Yapmayın:
if (x < 3) {
x += 1;
}
else {
x -= 1;
}
Fonksiyon Tanımlamaları
Kısa fonksiyon bildirimleri için, fonksiyon gövdesinin açılış ayracının fonksiyon bildirimiyle aynı satırda tutulması önerilir.
Kapanış parantezi fonksiyon bildirimi ile aynı girinti seviyesinde olmalıdır.
Açılış ayracından önce tek bir boşluk bırakılmalıdır.
Yapın:
function increment(uint x) public pure returns (uint) {
return x + 1;
}
function increment(uint x) public pure onlyOwner returns (uint) {
return x + 1;
}
Yapmayın:
function increment(uint x) public pure returns (uint)
{
return x + 1;
}
function increment(uint x) public pure returns (uint){
return x + 1;
}
function increment(uint x) public pure returns (uint) {
return x + 1;
}
function increment(uint x) public pure returns (uint) {
return x + 1;}
Bir fonksiyon için modifier sırası şöyle olmalıdır:
Visibility
Mutability
Virtual
Override
Custom modifiers
Yapın:
function balance(uint from) public view override returns (uint) {
return balanceOf[from];
}
function shutdown() public onlyOwner {
selfdestruct(owner);
}
Yapmayın:
function balance(uint from) public override view returns (uint) {
return balanceOf[from];
}
function shutdown() onlyOwner public {
selfdestruct(owner);
}
Uzun fonksiyon bildirimleri için, her argümanın fonksiyon gövdesiyle aynı girinti seviyesinde kendi satırına bırakılması önerilir. Kapanış parantezi ve açılış parantezi de fonksiyon bildirimi ile aynı girinti seviyesinde kendi satırlarına yerleştirilmelidir.
Yapın:
function thisFunctionHasLotsOfArguments(
address a,
address b,
address c,
address d,
address e,
address f
)
public
{
doSomething();
}
Yapmayın:
function thisFunctionHasLotsOfArguments(address a, address b, address c,
address d, address e, address f) public {
doSomething();
}
function thisFunctionHasLotsOfArguments(address a,
address b,
address c,
address d,
address e,
address f) public {
doSomething();
}
function thisFunctionHasLotsOfArguments(
address a,
address b,
address c,
address d,
address e,
address f) public {
doSomething();
}
Uzun bir fonksiyon bildiriminde modifier’lar varsa, her modifier kendi satırına bırakılmalıdır.
Yapın:
function thisFunctionNameIsReallyLong(address x, address y, address z)
public
onlyOwner
priced
returns (address)
{
doSomething();
}
function thisFunctionNameIsReallyLong(
address x,
address y,
address z
)
public
onlyOwner
priced
returns (address)
{
doSomething();
}
Yapmayın:
function thisFunctionNameIsReallyLong(address x, address y, address z)
public
onlyOwner
priced
returns (address) {
doSomething();
}
function thisFunctionNameIsReallyLong(address x, address y, address z)
public onlyOwner priced returns (address)
{
doSomething();
}
function thisFunctionNameIsReallyLong(address x, address y, address z)
public
onlyOwner
priced
returns (address) {
doSomething();
}
Çok satırlı çıktı parametreleri ve return ifadeleri, Maximum Line Length bölümünde bulunan uzun satırları çevrelemek için önerilen aynı stili izlemelidir.
Yapın:
function thisFunctionNameIsReallyLong(
address a,
address b,
address c
)
public
returns (
address someAddressName,
uint256 LongArgument,
uint256 Argument
)
{
doSomething()
return (
veryLongReturnArg1,
veryLongReturnArg2,
veryLongReturnArg3
);
}
Yapmayın:
function thisFunctionNameIsReallyLong(
address a,
address b,
address c
)
public
returns (address someAddressName,
uint256 LongArgument,
uint256 Argument)
{
doSomething()
return (veryLongReturnArg1,
veryLongReturnArg1,
veryLongReturnArg1);
}
Tabanları argüman gerektiren inherited sözleşmelerdeki constructor fonksiyonları için, fonksiyon bildirimi uzunsa veya okunması zorsa, temel constructor’ların modifier’larla aynı şekilde yeni satırlara bırakılması önerilir.
Yapın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
// Base contracts just to make this compile
contract B {
constructor(uint) {
}
}
contract C {
constructor(uint, uint) {
}
}
contract D {
constructor(uint) {
}
}
contract A is B, C, D {
uint x;
constructor(uint param1, uint param2, uint param3, uint param4, uint param5)
B(param1)
C(param2, param3)
D(param4)
{
// do something with param5
x = param5;
}
}
Yapmayın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
// Base contracts just to make this compile
contract B {
constructor(uint) {
}
}
contract C {
constructor(uint, uint) {
}
}
contract D {
constructor(uint) {
}
}
contract A is B, C, D {
uint x;
constructor(uint param1, uint param2, uint param3, uint param4, uint param5)
B(param1)
C(param2, param3)
D(param4) {
x = param5;
}
}
contract X is B, C, D {
uint x;
constructor(uint param1, uint param2, uint param3, uint param4, uint param5)
B(param1)
C(param2, param3)
D(param4) {
x = param5;
}
}
Kısa fonksiyonları tek bir ifadeyle bildirirken, bunu tek bir satırda yapmaya izin verilir.
İzin verilebilir:
function shortFunction() public { doSomething(); }
Fonksiyon bildirimleri için bu kılavuzun amacı okunabilirliği artırmaktır. Bu kılavuz, fonksiyon bildirimleri için olası tüm olasılıkları kapsamaya çalışmadığından, yazarlar en iyi kararlarını vermelidir.
Mappingler
Değişken bildirimlerinde, mapping
anahtar sözcüğünü türünden bir boşlukla ayırmayın. İç içe geçmiş mapping
anahtar sözcüğünü türünden boşluk ile ayırmayın.
Yapın:
mapping(uint => uint) map;
mapping(address => bool) registeredAddresses;
mapping(uint => mapping(bool => Data[])) public data;
mapping(uint => mapping(uint => s)) data;
Yapmayın:
mapping (uint => uint) map;
mapping( address => bool ) registeredAddresses;
mapping (uint => mapping (bool => Data[])) public data;
mapping(uint => mapping (uint => s)) data;
Değişken Bildirimleri
Dizi değişkenlerinin bildirimlerinde tür ile parantezler arasında boşluk olmamalıdır.
Yapın:
uint[] x;
Yapmayın:
uint [] x;
Diğer Öneriler
Stringler tek tırnak yerine çift tırnak ile alıntılanmalıdır.
Yapın:
str = "foo";
str = "Hamlet says, 'To be or not to be...'";
Yapmayın:
str = 'bar';
str = '"Be yourself; everyone else is already taken." -Oscar Wilde';
Operatörleri her iki tarafta tek bir boşlukla çevrelendirmelisiniz.
Yapın:
x = 3;
x = 100 / 10;
x += 3 + 4;
x |= y && z;
Yapmayın:
x=3;
x = 100/10;
x += 3+4;
x |= y&&z;
Diğerlerinden daha yüksek önceliğe sahip operatörler, önceliği belirtmek için çevreleyen beyaz boşluğu kaldırabilir. Bunun amacı, karmaşık ifadeler için daha iyi okunabilirlik sağlamaktır. Bir operatörün her iki tarafında da her zaman aynı miktarda boşluk kullanmalısınız:
Yapın:
x = 2**3 + 5;
x = 2*y + 3*z;
x = (a+b) * (a-b);
Yapmayın:
x = 2** 3 + 5;
x = y+z;
x +=1;
Yerleşim Sırası
Sözleşme unsurlarını aşağıdaki sıraya göre düzenleyin:
Pragma ifadeleri
Import ifadeleri
Interface’ler
Library’ler
Sözleşmeler
Her bir sözleşme, kütüphane veya arayüzün içinde aşağıdaki sıralamayı kullanın:
Type bildirimleri
Durum değişkenleri
Event’ler
Modifier’lar
Fonksiyonlar
Not
Türleri, event’lerde veya durum değişkenlerinde kullanımlarına yakın bir yerde bildirmek daha anlaşılır olabilir.
Adlandırma Kuralları
Adlandırma kuralları benimsendiğinde ve geniş çapta kullanıldığında güçlüdür. Farklı konvansiyonların kullanımı, aksi takdirde hemen elde edilemeyecek önemli meta bilgileri aktarabilir.
Burada verilen adlandırma önerileri okunabilirliği artırmayı amaçlamaktadır ve bu nedenle kural değil, daha ziyade nesnelerin adları aracılığıyla en fazla bilgiyi iletmeye yardımcı olacak kılavuzlardır.
Son olarak, bir kod tabanı içindeki tutarlılık her zaman bu belgede özetlenen kuralların yerine geçmelidir.
Adlandırma Stili
Karışıklığı önlemek için, farklı adlandırma stillerine atıfta bulunmak üzere aşağıdaki adlar kullanılacaktır.
b
(tek küçük harf)B
(tek büyük harf)lowercase
UPPERCASE
UPPER_CASE_WITH_UNDERSCORES
CapitalizedWords
(veya CapWords)mixedCase
(ilk küçük harf karakteri ile CapitalizedWords`den farklıdır!)
Not
CapWords’te baş harfleri kullanırken, baş harflerin tüm harflerini büyük yazın. Bu nedenle HTTPServerError, HttpServerError adlandırmasından daha iyidir. MixedCase’de baş harfleri kullanırken, baş harflerin tüm harflerini büyük yazın, ancak ismin başındaysa ilk harfi küçük tutun. Bu nedenle xmlHTTPRequest, XMLHTTPRequest adlandırmasından daha iyidir.
Uzak Durulması Gereken İsimler
l
- Küçük harf leO
- Büyük harf oI
- Büyük harf I
Bunlardan hiçbirini tek harfli değişken adları için kullanmayın. Bunlar genellikle bir ve sıfır rakamlarından ayırt edilemez.
Sözleşme ve Kütüphane Adları
Sözleşmeler ve kütüphaneler CapWords stili kullanılarak adlandırılmalıdır. Örnekler:
SimpleToken
,SmartBank
,CertificateHashRepository
,Player
,Congress
,Owned
.Sözleşme ve kütüphane adları da dosya adlarıyla eşleşmelidir.
Bir sözleşme dosyası birden fazla sözleşme ve/veya kütüphane içeriyorsa, dosya adı çekirdek sözleşme ile eşleşmelidir. Ancak kaçınılması mümkünse bu önerilmez.
Aşağıdaki örnekte gösterildiği gibi, sözleşme adı Congress
ve kütüphane adı Owned
ise, ilişkili dosya adları Congress.sol
ve Owned.sol
olmalıdır.
Yapın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
// Owned.sol
contract Owned {
address public owner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function transferOwnership(address newOwner) public onlyOwner {
owner = newOwner;
}
}
ve Congress.sol
içinde:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;
import "./Owned.sol";
contract Congress is Owned, TokenRecipient {
//...
}
Yapmayın:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
// owned.sol
contract owned {
address public owner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function transferOwnership(address newOwner) public onlyOwner {
owner = newOwner;
}
}
ve Congress.sol
içinde:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.7.0;
import "./owned.sol";
contract Congress is owned, tokenRecipient {
//...
}
Struct Adları
Struct’lar CapWords stili kullanılarak adlandırılmalıdır. Örnekler: MyCoin
, Position
, PositionXY
.
Event Adları
Event’ler CapWords stili kullanılarak adlandırılmalıdır. Örnekler: Deposit
, Transfer
, Approval
, BeforeTransfer
, AfterTransfer
.
Fonksiyon Adları
Fonksiyonlar mixedCase kullanmalıdır. Örnekler: getBalance
, transfer
, verifyOwner
, addMember
, changeOwner
.
Fonksiyon Argüman Adları
Fonksiyon argümanları mixedCase kullanmalıdır. Örnekler: initialSupply
, account
, recipientAddress
, senderAddress
, newOwner
.
Özel bir struct üzerinde çalışan kütüphane fonksiyonları yazarken, struct ilk argüman olmalı ve her zaman self
olarak adlandırılmalıdır.
Yerel ve Durum Değişkeni Adları
MixedCase kullanın. Örnekler: totalSupply
, remainingSupply
, balancesOf
, creatorAddress
, isPreSale
, tokenExchangeRate
.
Constant’lar (Sabitler)
Constantlar, sözcükleri ayıran alt çizgiler ile tüm büyük harflerle adlandırılmalıdır. Örnekler: MAX_BLOCKS
, TOKEN_NAME
, TOKEN_TICKER
, CONTRACT_VERSION
.
Modifier Adları
MixedCase kullanın. Örnekler: onlyBy
, onlyAfter
, onlyDuringThePreSale
.
Enumlar
Enumlar, basit tip bildirimleri tarzında, CapWords stili kullanılarak adlandırılmalıdır. Örnekler: TokenGroup
, Frame
, HashStyle
, CharacterLocation
.
Adlandırma Çakışmalarını Önleme
singleTrailingUnderscore_
Bu kural, istenen adın halihazırda varolan bir durum değişkeni, fonkisyon, ayrılmış veya yerleşik bir adla çakışması durumunda önerilir.
NatSpec
Solidity sözleşmeleri NatSpec yorumları da içerebilir. Bunlar üçlü eğik çizgi (///
) veya çift yıldız bloğu (/** ... */
) ile yazılır ve doğrudan fonksiyon bildirimlerinin veya ifadelerin üzerinde kullanılmalıdır.
Örneğin, a simple smart contract sözleşmesi yorumlar eklendiğinde aşağıdaki gibi görünür:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;
/// @author The Solidity Team
/// @title A simple storage example
contract SimpleStorage {
uint storedData;
/// Store `x`.
/// @param x the new value to store
/// @dev stores the number in the state variable `storedData`
function set(uint x) public {
storedData = x;
}
/// Return the stored value.
/// @dev retrieves the value of the state variable `storedData`
/// @return the stored value
function get() public view returns (uint) {
return storedData;
}
}
Solidity sözleşmelerinin tüm genel arayüzler (ABI’deki her şey) için NatSpec kullanılarak tam olarak açıklanması önerilir.
Ayrıntılı açıklama için lütfen NatSpec ile ilgili bölüme bakın.