Code documentation: Drawings VS Pseudo-Code VS Bulletpoints VS Mermaid
I'm frequently faced with the challenge of documenting an existing system. But I never figured out what tool is the most effective, so, most of the times, I randomly pick a tool and just go with it. This time, I decided to conduct a small competition.
This is what the competing tools were challenged to describe:
WithdrawalController
subscribed to RabbitMQ queueswithdraw.evm
,withdraw.btc
andwithdraw.trx
with methodsWithdrawEvm
,WithdrawBtc
,WithdrawTrx
. Each of these queues message contains single fieldtxId
.
WithdrawEvm
first readstx
from the database by thetxId
, then readssysWalletSecret
from the database bytx.TenantId
.tx
andsysWalletSecret
are then passed toEvmTxManager.SignAndSend
, which constructs signed evm tx and sends it viaJsonRpc eth_sendRawTransaction
request to evm node provided by theGetBlock
.
WithdrawBtc
reads from the database firsttx
by thetxId
, thenbtcId
bytx.TenantId
.tx
andbtcId
are then passed toBtcTxManager.Send
which constructs self-hosted btc node url using btcId and sends thereJsonRpc sendtoaddress
request build with data fromtx
WithdrawTrx
reads from the database firsttx
by thetxId
, thensysWalletSecret
bytx.TenantId
. Then based on whethertx.Type
is equal to "Native" calls eitherTrxTxManager.sendNative
orTrxTxManager.sendToken
withtx
andsysWalletSecret
. BothTrxTxManager
methods sendPOST wallet/broadcasttransaction
request with constructed signed trx tx to the trx node provided by theGetBlock
And here's what I got:
Hand Drawing
Preudo Code
WithdrawalController
withdrawEvm rabbitQueue("withdraw.evm")
tx = db.txBy @txId
sysWalletSecret = db.sysWalletSecretFor 'EVM' tx.TenantId
EvmTxManager.signAndSend tx sysWalletSecret
withdrawBtc rabbitQueue("withdraw.btc")
tx = db.transactionBy @txId
btcId = db.btcIdBy transaction.TenantId
BtcTxManager.send tx btcId
withdrawTrx rabbitQueue("withdraw.trx")
tx = db.txBy @txId
sysWalletSecret = db.sysWalletSecretFor 'TRX' tx.TenantId
if tx.Type == "Native"
TrxTxManager.sendNative
tx
sysWalletSecret
else
TrxTxManager.sendToken
tx
sysWalletSecret
EvmTxManager
signAndSend
signedEvmTx = signedTxFrom @tx @secret
sendJsonRpc getblock.evmNode "eth_sendRawTransaction" signedEvmTx
BtcTxManager
send
sendJsonRpc
selfhosted.btcNode
@btcId
"sendtoaddress"
@tx
TrxTxManager
sendNative
signedTrxTx = signedTxFrom @tx @secret
post getBlock.trxNode "/wallet/broadcasttransaction" signedTransaction
sendToken
signedTransaction = signedTxFrom @tx @secret
post getBlock.trxNode "/wallet/broadcasttransaction" signedTransaction
Bulletpoints
WithdrawController
handles messages fromRabbitMQ
withdraw.evm
(WithdrawEvm
)- SELECTS
tx
bytxId
- SELECTS
sysWalletSecret
bytransaction.TenantId
- Sends to
EvmTxManager.signAndSend
- Creates
signedEvmTx
- Sends a
JsonRpc
requesteth_sendRawTransacton
toevmNode
fromGetBlock
provider.
- Creates
- SELECTS
withdraw.btc
(WithdrawBtc
)- SELECTS
tx
bytxId
- SELECTS
sysWalletSecret
bytx.TenantId
- Sends to
BtcTxManager.send
- Constructs
self-hosted
btcNode
url usingbtcId
- Sends a
JsonRpc
requestsendtoaddress
to the url
- Constructs
- SELECTS
withdraw.trx
(WithdrawTrx
)- SELECTS
tx
bytxId
- SELECTS
sysWalletSecret
bytransaction.TenantId
- Calls
TrxTxManager
sendToken
andsendNative
based ontransaction.Type
- Creates
signedTrxTx
for both native and custom tokens. - Sends it via
POST wallet/broadcasttransaction
totrxNode
fromGetBlock
provider
- Creates
- SELECTS
Mermaid Flowchart
flowchart TB
rabbit((RabbitMQ))
db[(Database)]
evmNode(("EVM Node
GetBlock Provider"))
btcNode(("BTC Node
Self-Hosted"))
trxNode(("TRX Node
GetBlockProvider"))
rabbit ----> withdrawEvm -- signedEthTx --> evmNode
withdrawEvm <-. tx, sysWalletSecret .-> db
rabbit ----> withdrawBtc -- url by btcId, tx --> btcNode
withdrawBtc <-. tx, btcId.-> db
rabbit ----> withdrawTrx -- signedTrxTx --> trxNode
withdrawTrx <-.tx, sysWalletSecret.-> db
Mermaid Sequence Diagram
sequenceDiagram
autonumber
participant R as Rabbit
participant WC as WithdrawController
participant FS as FinanceService
participant DB
participant E as Executors (EvmTx, BtcTx, TrxTx)
participant N as Nodes (Evm-GetBlock, Btc-SelfHosted, Trx-GetBlocks)
R ->> WC: withdraw.evm (txId)
WC ->> DB: txId
DB ->> WC: tx
WC ->> DB: tx.tenantId EVM
DB ->> WC: sysWalletSecret
WC ->> E: evm.signAndSend
E ->> N: evmSignedTx
R ->> WC: withdraw.btc (txId)
WC ->> DB: txId
DB ->> WC: tx
WC ->> DB: tx.tenant
DB ->> WC: btcId
WC ->> E: btc.send
E ->> N: btcId, tx
R ->> WC: withdraw.trx (txId)
WC ->> DB: txId
DB ->> WC: tx
WC ->> DB: tx.tenant TRX
DB ->> WC: sysWalletSecret
WC ->> E: trx.sendNative
E ->> N: signedTrxTx
WC ->> E: trx.sendToken
E ->> N: signedTrxTx
Results
If I'd have to pick a solo winner that would be bullet points.
Writing bullet points was intuitive and fast. Any specialist can understand them. Their tree-like structure, perfectly match the flow of the process, allowing step-by-step investigation of each proccess branch. Finally, they are perfectly git-friendly: can be read with no additional tooling, easy to comment on, and so on.
Paradoxically enough, this is the least fancy tool. To glamorize that a bird-eye mermaid flow chart can be added to the mix. I assume a combination of those two would be the most beautiful and understandable way to create a documentation for an existing code.