
اگر کمی با زبانهای برنامهنویسی آشنایی داشته باشید، بدون شک به صورت کلی در مورد لایبرریها یا کتابخانههای موجود در بستر کدنویسی اطلاع دارید. به بیان ساده، یک لایبرری مجموعه قابل استفاده مجددی از ابزارها (توابع/رویکردها) است که میتوانید آن را در طول روند برنامه اصلی خود فراخوانی کنید. در ادامه این مقاله با میهن بلاکچین همراه باشید تا به بررسی کتابخانه های سالیدیتی و کاربرد آنها بپردازیم. توابع موجود در این کتابخانه در راستای دست یافتن و محاسبه آبجکتیو یا هدف مورد نظر شما کمک میکنند.
این امر به حفظ روان بودن، آسان بودن فهم، قابلیت استفاده مجدد و درک کد شما کمک میکند. ایده کلی حول محور کتابخانه های سالیدیتی (Solidity) با دانش پیشین برنامهنویسی شما در این رابطه تفاوت چندانی ندارد. ایده اولیه مورد استفاده در این بستر تا حد زیادی یکسان بوده و هدف ما، استفاده از لایبرریهای زبان برنامه نویسی سالیدیتی برای دست یافتن به کد روان و تمیز، قابل استفاده مجدد و مقرون به صرفه از نظر گس یا هزینه است. با ادامه این مطلب آموزشی همراه میهن بلاکچین باشید.
کتابخانههای سالیدیتی
کتابخانه موجود در بستر سالیدیتی یک ماهیت مستقل است که شباهت زیادی به یک قرارداد داشته اما به هیچ عنوان یک قرارداد هوشمند محسوب نمیشود. این لایبرری توابعی را شامل میشود که تنها میتوان آنها را به صورت صرف، مورد مشاهده (View-Only) قرار داد. ممکن است این توابع به صورت مشترک میان چندین قرارداد مصرفکننده مورد استفاده قرار بگیرند و به روند جلوگیری از تولید توابع اضافی کمک کنند.
جدا از مقوله توابع هجو یا مازاد، لازم است بدانید که دیپلوی یا پیادهسازی کردن یک قرارداد به گس یا همان هزینه نیاز دارد. بنابراین، به جای اینکه از کد تکراری در چندین قرارداد استفاده کنیم، میتوانیم این مجموعه کد را در یک کتابخانه اشتراکگذاری شده گرد هم آورده و تنها یک بار آن را مورد استفاده قرار دهیم. در نتیجه، در میزان کارمزد مورد نیاز صرفهجویی میشود.
برخلاف قراردادهای هوشمند، لایبرریها توان عملکرد آزادانه چندانی ندارند، بلکه مجموعهای از قوانین سرسختانه برای کتابخانهها در نظر گرفته شده و با آنها در هم تنیده شدهاند. بنابراین، کتابخانهها مجبور به پیروی از این قوانین و عمل کردن در حیطه آنها هستند.
بیایید کمی بیشتر به این قوانین/ملزومات بپردازیم.
- Stateless – کتابخانه های سالیدیتی در واقع هویتهای بدون حالت یا Stateless هستند. این امر به صورت کلی بدان معناست که برخلاف قراردادهای هوشمند، قادر به تعریف متغیرهای حالت در یک لایبرری نخواهیم بود. به بیان ساده، توابع کتابخانه این اجازه را ندارند تا وضعیت یا حالت قرارداد هوشمند را تغییر داده یا اصلاح کنند.
- توابع View Only – با توجه به اینکه فراخوانی تابع یک کتابخانه موجب تغییر حالت قرارداد نمیشود، انجام این کار نیازی به گس نخواهد داشت. به عبارت دیگر، یک لایبرری تنها میتواند توابع خالص یا قابل مشاهده صرف را پیادهسازی کند.
- توابع داخلی – به هیچ عنوان نمیتوانیم یک لایبرری را از خارج محدودی بومی Solidity فراخوانی کنیم. بدون شک قراردادهای دیگر میتوانند این کتابخانهها را فراخوانی کنند، اما امکان فراخوانی آنها از بیرون محدوده پیادهسازی وجود ندارد.
- عدم وجود قابلیت وراثتی – با توجه به اینکه لایبرری یک هویت مستقل است، امکان به ارث بردن کتابخانه یا قرارداد دیگری را ندارد.
- غیرقابل به ارث رسیدن – به دلایل مشابهی که در بخش قبل توضیح دادیم، امکان به ارث برده شدن یک کتابخانه توسط هیچ موجودیت، لایبرری یا قرارداد دیگری وجود ندارد.
- عدم وجود توابع جایگزین یا قابل پرداخت– کتابخانه های سالیدیتی امکان پیادهسازی توابع جایگزین (Fallback) یا قابل پرداخت (Payable) را ندارند.
شیوه ساخت یک لایبرری در زبان برنامه نویسی سالیدیتی
حالا که مفاهیم پایه مورد نیاز در مورد یک کتابخانه را یاد گرفتیم، بیایید به سراغ بخشهای مهمتری رویم.
در ابتدا لازم است تا شیوه تعریف کردن یک کتابخانه سالیدیتی را یاد بگیریم. در طول فرایند کدنویسی، شیوه تعریف یک کتابخانه با استفاده از کلیدواژه Library صورت میگیرد.
library MyLibrary { // some piece of code you want to make part of MyLibrary }
توجه داشته باشید که در این بخش عنوان MyLibrary همان نام کتابخانه مورد نظر ماست.
در این قسمت از Remix IDE استفاده کردهایم تا بتوانید مفاهیم مطرح شده را به آسانی فرا بگیرید.
در مرحله دوم به سراغ فولدر Contracts رفته و یک فایل جدید MathUtils.sol بسازید.
به محض ساخته شدن فایل مورد نظر، کتابخانه MathUtils را در بخش داخلی آن و مطابق با کاری که در بخش بالا انجام دادیم تعریف کنید.
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library MathUtils { // Library code here ... }
حالا بیایید در این کتابخانه MathUtils یک تابع ساده Add یا جمع بسازیم که با دریافت Unit یا واحد ارزشی به عنوان مولفهها، جمع آنها را به صورت خروجی به ما تحویل میدهد.
دلیل اینکه در این بخش از مثالها ساده استفاده میکنیم بدین صورت است که پیچیدهتر کردن مثالها و توابع مورد استفاده موجب عدم یادگیری دقیق شما و درک کامل ایده کلی میشود.
تعریف تابع Add بدین صورت است:
تا به اینجا و در طول این فرایند ساده موفق شدیم تا اولین لایبرری از مجموعه کتابخانه های سالیدیتی را بسازیم. با این حال میدانیم که تمام کار ما به این نقطه ختم نمیشود. حالا به شیوه استفاده از این لایبرری در یک قرارداد هوشمند میپردازیم.
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library MathUtils { function add(uint a, uint b) public pure returns(uint) { return a + b; } }
در بستر Remix به فولدر Contracts مراجعه کرده و فایل جدید Calculator.sol که شامل قرارداد Calculator یا محاسبهگر میشود را بسازید.
در این مقاله وارد جزئیات ساخت خود قرارداد نمیشویم و انجام چنین کاری به هیچ عنوان مد نظر ما نیست. به عنوان مرجع مورد استفاده شما، از قرارداد زیر استفاده کرده و تابع کتابخانه خود را در داخل آن فراخوانی میکنیم.
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./MathUtils.sol"; contract Calculator { function getSum(uint firstNumber, uint secondNumber) public pure returns(uint) { // Invoke and return the library function here ... } }
با یاد داشته باشید که پیش از این کتابخانه MathUtils را در فایل قرارداد خود وارد کردهایم. در این نقطه تنها چیزی که باقی میماند، استفاده از رویکرد یا متد Add از کتابخانه در بطن متد GetSUM قرارداد Calculator است.
شیوه استفاده از تابع لایبرری در داخل یک قرارداد
به منظور استفاده از یک لایبرری در داخل یک قرارداد لازم است تا در ابتدا کاربرد کتابخانه مورد نظر را اعلام کنیم. شاید کمی گیج شده باشید!
جای نگرانی نیست، در این بخش به درک کامل این موضوع در قرارداد مثالی خود میپردازیم.
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./MathUtils.sol"; contract Calculator { using MathUtils for uint; function getSum(uint firstNumber, uint secondNumber) public pure returns(uint) { return firstNumber.add(secondNumber); } }
در این قطعه کد اتفاقات جالب توجهی روی میدهند که عبارتند از:
- وارد کردن Statement که پیش از این در مورد آن صحبت کردهایم.
- استفاده از MathUtils برای Unit که یک اتفاق جدید است.
- و در نهایت، FirstNumber.add(SecondNumber)؛ که ممکن است برای شما کمی گیجکننده باشد.
به منظور استفاده از هر یک از کتابخانه های سالیدیتی در داخل یک قرارداد لازم است تا در ابتدا نوع دادهای که لایبرری مورد نظر بر اساس آن عمل میکند را مشخص کنیم. برای انجام این کار، از رشته کد <Using <LibraryName> for <Data Type> استفاده میکنیم.
به عنوان مثال، تابع Add در داخل کتابخانه MatUtils بر روی Unit کار خود را انجام میدهد زیرا واحد A یا همان Unit a را به عنوان مولفه اول خود دریافت میکند.
برای درک اهداف ما در این بخش، میتوانید اینطور فرض کنید که تابع لایبرری شما بخشی از نوع داده Unit شده و به راحتی در بستر آبجکتها یا اشیا این تابع در دسترس خواهد بود.
در نهایت، هنگامی که تابع لایبرری به بخشی از خود نوع داده تبدیل شود، میتوانیم متد مورد نظر مبتنی بر آبجکت نشان داده شده در بخش بالا را فراخوانی کنیم. به عنوان مثال به این شیوه فراخوانی میتوان اشاره کرد: FirstNumber.add (SecondNumber)
توجه داشته باشید که مولفه اول این تابع لایبرری، در واقع همان پارامتری محسوب میشود که تابع ما بر اساس آن فراخوانی شده است. مولفههای باقیمانده و بعدی همچنان در بطن فراخوانی تابع منتقل میشوند.
پیادهسازی قرارداد
در این بخش به صورت تمام کارهای مربوط به کتابخانه های سالیدیتی و توسعه قرارداد به پایان رسیده است. حالا میتوانیم به روند خود ادامه داده و به سراغ دیپلوی کردن قرارداد Calculator رفته بررسی کنیم که آیا همه چیز طبق انتظارات ما پیش میرود یا خیر.
پایانه موجود در Remix تمام بررسیهای سبز صورت گرفته بر اساس دستور Deploy را در این بخش به ما نشان میدهد. این بدان معناست که پیادهسازی ما با موفقیت به انجام رسیده است.
به محض اینکه قرارداد مورد نظر با موفقیت استقرار پیدا کند، تابع GetSum در اختیار ما خواهد بود و میتوانیم از آن استفاده کنیم.
فراخوانی تابع GetSum با استفاده از هر دو مقدار ارزش مورد نظر، بدون هیچگونه جای شکی جواب صحیح را به ما میدهد.
سخن پایانی
در این مقاله به شناخت و شیوه استفاده از کتابخانه های سالیدیتی پرداختیم. اکنون شما نیز ایده کلی مورد استفاده در بستر لایبرریها و نحوه استفاده از آنها در قراردادهای هوشمند را میدانید. به منظور استفاده از توابع موجود در بستر کتابخانهها لازم است تا بدانیم که به منظور اجتناب از تکرار کد در برنامههایمان از این مراجع استفاده میکنیم.
شما از چه کتابخانههایی در کدهای سالیدیتی خود استفاده میکنید؟ بهترین شیوه استفاده از این ساختار را چه میدانید؟ تجربیات خود در این خصوص را با ما و دیگر کاربران میهن بلاکچین به اشتراک بگذارید.