رفتن به مطلب
جامعه‌ی برنامه‌نویسان مُدرن ایران

پرچمداران

  1. کامبیز اسدزاده

    کامبیز اسدزاده

    بنیـــان گذار


    • امتیاز

      3

    • تعداد ارسال ها

      350


  2. فرهاد شیری

    فرهاد شیری

    مدیران مرجع


    • امتیاز

      2

    • تعداد ارسال ها

      173


  3. نیما غراب

    نیما غراب

    کاربـــر رسمی


    • امتیاز

      2

    • تعداد ارسال ها

      8



مطالب محبوب

در حال نمایش مطالب دارای بیشترین امتیاز در جمعه, 10 آبان 1398 در همه بخش ها

  1. 2 امتیاز
    به نام خدا در این مطلب قصد داریم تا طریقه پیکربندی پایگاه داده MySQL را با استفاده از کامپایلر مایکروسافت بر روی سیستم عامل ویندوز، بررسی نماییم. در ابتدا می‌بایست پایگاه داده MySQL را بر روی سیستم خود نصب نماییم. بدین منظور به آدرس این آدرس رفته و سپس و نصاب آنلاین یا آفلاین آن را دریافت و بر روی سیستم خود نصب می‌نماییم. حال لازم است تا مسیر qmake مربوط به کیت مورد نظر واقع در محل نصب کتابخانه کیوت به متغیر محیطی Path سیستم عامل معرفی شود. در اینجا قصد داریم تا از MSVC 2017 64 bit استفاده کنیم که بر روی سیستم عامل 64 بیتی اجرا شده و خروجی دودویی برای سیستم عامل 64 بیتی تولید می‌کند. مطابق شکل زیر مسیر qmake مورد نظر را به Path سیستم عامل اضافه می‌کنیم: پس از این کار از منوی Start پوشه Visual Studio 2017 را انتخاب کرده و سپس x64 Native Tools Command Prompt for VS 2017 را انتخاب کرده تا کنسول باز شود. حال می‌بایست به آدرس محل درایور پایگاه داده کیوت برویم. بدین منظور دستور زیر را در کنسول وارد می‌کنیم: C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools>F: F:\>cd F:\Softwares\Qt\5.13.1\Src\qtbase\src\plugins\sqldrivers دستور اول به منظور تغییر درایو از C به F وارد شده و دستور دوم آدرس محل نصب کیوت روی سیستم نگارنده مطلب می‌باشد. حال دستور زیر را وارد می‌کنیم: qmake -- MYSQL_INCDIR="C:\Program Files\MySQL\MySQL Server 8.0\include" MYSQL_LIBDIR="C:\Program Files\MySQL\MySQL Server 8.0\lib" فراخوانی دستور qmake سبب ایجاد یک makefile شده که بعدا برای کامپایل درایور MySQL استفاده می‌شود. آدرس‌های بالا نیز محل نصب پایگاه داده MySQL در حالت پیشفرض را نشان میدهد. پس از اتمام عملیات نتیجه زیر می‌بایست حاصل شود: ملاحظه می‌شود که در مقابل MySql کلمه yes نوشته شده که این به معنی موفقیت آمیز بودن یافتن درایور MySQL می‌باشد. در نهایت با دستور زیر عملیات کامپایل آغاز می‌شود: nmake sub-mysql پس از اتمام این مرحله نیز در پایان دستور زیر را اجرا کرده تا فایل‌های کامپایل شده، نصب شوند: nmake install محل نصب این فایل‌های راه انداز درایور در مسیر زیر می‌باشد: F:\Softwares\Qt\5.13.1\Src\qtbase\src\plugins\sqldrivers\plugins\sqldrivers در مسیر بالا دو فایل به نام‌های qsqlmysql.dll و qsqlmysqld.dll وجود دارد که باید در کنار فایل اجرایی برنامه کامپایل شده قرار گیرد تا برنامه به درستی اجرا شود. همچنین در مسیر: C:\Program Files\MySQL\MySQL Server 8.0\lib فایل libmysql.dll وجود دارد که می‌بایست در مسیر فایل اجرایی برنامه قرار گیرد. در پایان نوبت به این رسیده تا با ایجاد یک پروژه آزمایشی در Qt Creator بررسی کنیم تا همه چیز به درستی پیکربندی شده باشد. قبل از آن می‌‎بایست یک پایگاه داده آزمایشی در MySQL ایجاد کرده و سپس با استفاده از کتابخانه کیوت به آن متصل شویم. ابتدا خط فرمان MySQL را باز کرده و دستور زیر را وارد می‌کنیم: CREATE DATABASE mydatabase; که mydatabase نام پایگاه داده ایجاد شده می‌باشد. حال پس از ایجاد یک پروژه ساده در Qt Creator محتویات فایل .pro را مطابق شکل زیر وارد می‌کنیم: QT += core sql TEMPLATE = app CONFIG += console c++11 CONFIG -= app_bundle SOURCES += \ main.cpp و در فایل main.cpp خواهیم داشت: #include <iostream> #include <QtSql/QSqlDatabase> #include <QtSql/QSqlError> #include <QDebug> using namespace std; int main() { QSqlDatabase db {QSqlDatabase::addDatabase ("QMYSQL")}; db.setHostName ("localhost"); db.setDatabaseName("mydatabase"); db.setUserName ("root"); db.setPassword ("Inception 2010"); if(db.open ()) { qDebug() << "Success!"; } else { qDebug() << db.lastError ().text (); } } با ساخت و اجرا پروژه باید پیام Success! در خروجی نمایش داده شود. این یعنی پایگاه داده MySQL با موفقیت نصب و پیکربندی شده است.
  2. 1 امتیاز
    معرفی نسخه‌بندی معنایی ویرایش ۲.۰ در دنیای مدیریت نرم‌افزار مکان مخوفی به نام «جهنم وابستگی» (dependency hell) وجود دارد. هر چه سیستم شما بزرگتر باشد و بسته‌های (package) بیشتری با نرم‌افزار شما یکپارچه شده باشند، احتمال بیشتری وجود دارد که روزی خود را دراین گودال ناامیدی بیابید. در سیستم‌هایی با وابستگی‌های زیاد، انتشار بسته‌ی جدید به زودی می‌تواند تبدیل به یک کابوس شود. اگر ویژگی‌های وابستگی‌ها بسیار جزئی‌نگرانه باشد، در خطر قفل نسخه (version lock) خواهید بود (ناتوانی برای بروزرسانی یک بسته، بدون اجبار جهت انتشار نسخه‌های جدید همه‌ی بسته‌های وابسته). اگر وابستگی‌ها بسیار ضعیف مشخص شده باشند، به ناچار زخم بی‌قاعدگی نسخه را خواهید خورد (به فرض سازگاری بیش از حد معقول با نسخه‌های آتی‌تر). جهنم وابستگی آنجایی است که قفل نسخه و یا بی‌قاعدگی نسخه از پیشرفت رو به جلوی آسان و امن پروژه‌ی شما جلوگیری می‌کند. برای پاسخگویی به این مشکل، من یکسری قوانین و پیش‌نیازهای ساده را پیشنهاد میدهم که نحوهٔ تخصیص و افزایش شماره‌های نسخه را دیکته می‌کند. این قوانین برپایه‌ی شیوه‌های موجود رایج و گسترده‌ی در حال استفاده، هم در نرم‌افزارهای متن‌باز و غیر متن‌باز است، اگرچه لزوماً محدود به آن نیست. برای آنکه این سیستم کار کند نخست لازم است یک API عمومی (public) تعریف کنید. این امر ممکن است شامل مستندسازی، یا بوسیله‌ی خود کد مقید شده باشد. صرف نظر از این موضوع، مهم است که این API دقیق و واضح باشد. زمانیکه API عمومی خود را مشخص کردید، تغییرات آن را با افزایش معین شماره‌ی نسخه‌ی خود مرتبط می‌سازید. قالب نسخهای به صورت X.Y.Z را در نظر بگیرید. خطاهایی که تاثیری بر API ندارند، نسخه‌ی وصله (Patch) را افزایش می‌دهند، افزایش یا تغییر API که با نسخه‌های قبلی سازگار است، نسخه‌ی جزئی (Minor) را افزایش می‌دهند، و تغییرات API که با نسخه‌های قبل ناسازگار هستند، نسخه‌ی اصلی (Major) را افزایش می‌دهند. این سیستم را «نسخه‌بندی معنایی» می‌نامیم. بر اساس این طرح، شماره‌های نسخه و روشی که تغییر می‌کنند، معنی و مفهومی را درباره‌ی کد تحت آن نسخه، و آنچه که از یک نسخه تا نسخه‌ای دیگر ویرایش شده است، انتقال می‌دهد. به فرض اینکه نسخه‌ی MAJOR.MINOR.PATCH یا اصلی.جزیی.وصله داده شده است: شماره‌ی نسخه‌ی اصلی (MAJOR) را زمانی افزایش دهید که تغییرات API ناسازگار اعمال کرده‌اید، شماره‌ی نسخه‌ی جزئی (MINOR) را زمانی افزایش دهید که قابلیت‌هایی اضافه کرده‌اید که با نسخه‌های قبل سازگار هستند، شماره‌ی نسخه‌ی وصله (PATCH) را زمانی افزایش دهید که تصحیح خطاهایی (bug) اعمال کرده‌اید که با نسخه‌های قبل سازگار هستند. برچسب‌های اضافی برای پیش‌نشر و ساختن فراداده به صورت پسوندهایی برای قالب MAJOR.MINOR.PATCH فراهم است. ویژگی‌های نسخه‌بندی معنایی (SemVer) کلمات کلیدی «باید»، «نباید»، «نیاز است»، «می‌بایست»، «نمی‌بایست»، «توصیه شده است»، «ممکن است» و «اختیاری» در این مستند می‌بایست بر مبنای آنچه در RFC 2119 تعریف شده است، معنا شوند. نرم‌افزارهایی که از نسخه‌بندی معنایی استفاده می‌کنند باید یک API عمومی اعلام کنند. این API می‌تواند در خود کد اعلام شود، یا به طور واضح در مستندسازی وجود داشته باشد. هر طور که انجام شود، می‌بایست دقیق و جامع باشد. یک شماره‌ی نسخه‌ی عادی باید قالب X.Y.Z را داشته باشه طوری که در آن X ،Y و Z اعداد صحیح غیرمنفی هستند و نباید صفر اضافه (leading zero) داشته باشند. X نسخه‌ی اصلی، Y نسخه جزیی، و Z نسخهٔ وصله است. هر عنصر باید به صورت شمارشی افزایش یابد. به عنوان مثال 1.9.0 -> 1.10.0 -> 1.11.0. زمانی‌که یک بسته‌ی نسخه‌بندی شده منتشر شد، محتوای آن نسخه نباید دستکاری شود. هرگونه تغییری باید به عنوان نسخه‌ی جدید منتشر شود. نسخه‌ی اصلی شمارهٔ صفر (0.y.z) برای توسعه‌های ابتدایی است. هرچیزی در هر زمانی ممکن است تغییر کند. API عمومی نمی‌بایست ماندگار در نظر گرفته شود. نسخهٔ 1.0.0 API عمومی را تعریف می‌کند. روشی که شمارهٔ نسخه‌ی بعد از این انتشار افزوده می‌شود، به این API عمومی و نحوهٔ تغییر آن وابسته است. نسخه‌ی وصله Z (x.y.Z | x > 0) باید در صورتی افزوده شود که تصحیح‌های خطای سازگار با نسخهٔ قبلی معرفی شده باشند. یک تصحیح خطا به عنوان یک تغییر داخلی تعریف می‌شود که رفتارهای نادرست را اصلاح می‌کند. نسخهٔ جزیی Y (x.Y.z | x > 0) باید در صورتی افزوده شود که عملکرد سازگار با نسخه‌های قبل جدیدی به API عمومی معرفی شده باشد. همچنین اگر هرگونه عملکرد API عمومی به عنوان منسوخ‌شده برچسب خورده باشد، این شماره باید افزوده شود. اگر عملکرد جدید یا بهبود قابل توجهی در کدهای داخلی معرفی شده باشد، ممکن است نسخهٔ جزیی افزوده شود. ممکن است که شامل تغییرات سطح وصله هم باشد. زمانیکه نسخه جزیی افزوده شود، نسخهٔ وصله باید به 0 بازنشانده شود. نسخه‌ی اصلی X (X.y.z | X > 0) باید در صورتی افزوده شود که هرگونه تغییرات ناسازگار با نسخه‌های قبل به API عمومی معرفی شده باشد. ممکن است این تغییرات شامل سطوح جزیی و وصله نیز باشد. نسخه‌ی جزئی و وصله زمانیکه نسخه‌ی اصلی افزوده می‌شود باید به 0 بازنشانی شوند. یک نسخه‌ی پیش‌انتشار ممکن است با اضافه کردن یک خط تیره و یک سری شناسه‌هایی که به وسیله‌ی نقطه از هم جدا ‌شده‌اند و بلافاصله به دنبال نسخه‌ی وصله می‌آیند، نشانه‌گذاری شود. شناسه‌ها باید تنها شامل اعداد و حروف الفبای اَسکی (ASCII) و خط تیره [A-Za-z0-9] باشند. شناسه‌ها نباید تهی باشند. شناسه‌های عددی نباید با صفر اضافه آغاز شوند. نسخه‌ی پیش‌انتشار از اولویت پایین‌تری نسبت به نسخه‌ی عادی مرتبط برخوردار است. یک نسخه‌ی پیش‌انتشار حاکی از آن است که نسخه‌ی ناپایدار است و ممکن است نیازمندی‌های سازگاری مورد نظر را آنگونه که در نسخه‌ی عادی مرتبط نشان داده شده است، برآورده نکند. مثال: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92. متادیتای ساخت (build metadata) ممکن است با افزودن یک علامت جمع (+) و یک سری شناسه‌هایی که به وسیلهٔ نقطه ازهم جدا شده‌اند، و بلافاصله به دنبال نسخه‌ی وصله یا پیش‌انتشار می‌آیند، نشانه‌گذاری شود. شناسه‌ها باید تنها شامل اعداد و حروف الفبای اَسکی (ASCII) و خط تیره [A-Za-z0-9] باشند. شناسه‌ها نباید تهی باشند. متادیتای ساخت می‌بایست در زمان تعیین اولویت نسخه درنظر گرفته نشود. بنابراین دو نسخه که تنها در متادیتای ساخت با یکدیگر متفاوت هستند، اولویت یکسان دارند. مثال: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f8 اولویت اشاره دارد به اینکه چگونه نسخه‌ها زمانی‌که مرتب شده‌اند با یکدیگر مقایسه می‌شوند. اولویت باید به وسیله‌ی جداسازی نسخه به اصلی، جزیی، وصله و شناسه‌های پیش‌انتشار به همین ترتیب، محاسبه شود (متادیتای ساخت در اولویت نمایان نمی‌شود). اولویت، به وسیلهٔ اولین تفاوت تعیین می‌شود هنگامی که این مشخصه‌ها از چپ به راست مقایسه شوند، بدین صورت: نسخه‌های اصلی، جزیی و وصله همیشه به صورت عددی مقایسه می‌شوند. مثال: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1. زمانی که اصلی و جزیی و وصله برابر هستند، یک نسخهٔ پیش‌انتشار از اولویت کمتری نسبت به نسخهٔ عادی برخوردار است. مثال: 1.0.0- alpha < 1.0.0 اولویت برای دو نسخه‌ی پیش‌انتشار با نسخه‌ی اصلی، جزیی و وصله‌ی مشابه باید به وسیله‌ی مقایسه‌ی هر مشخصه‌ای که با نقطه جدا شده، از چپ به راست مشخص شود تا زمانی که یک تفاوت به شرح زیر یافت شود: شناسه‌هایی که تنها شامل اعداد صحیح هستند به صورت عددی و شناسه‌هایی که با حروف یا خط‌های تیره به صورت الفبایی به ترتیب ASCII مقایسه می شوند. مشخصه‌های عددی همیشه از اولویت کمتری نسبت به مشخصه‌های غیرعددی برخوردار هستند. مجموعه‌های بزرگتری از بخشهای پیش‌انتشار اولویت بیشتری نسبت به مجموعه‌های کوچکتر دارند، اگر همه مشخصه‌های اولویت برابر باشند. مثال: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0. چرا از نسخه‌بندی معنایی استفاده شود؟ این ایده‌ای جدید یا انقلابی نیست. در واقع، احتمالاً شما چیزی مشابه به این را پیش از این انجام داده‌اید. مشکل اینجاست که «مشابه» به اندازه‌ی کافی خوب نیست. بدون انطباق با نوعی تعریف رسمی، شماره‌های نسخه ضرورتاً برای مدیریت وابستگی (dependency) بلااستفاده هستند. بوسیله‌ی اختصاص اعداد و تعاریف واضح به ایده‌های بالا، برقراری ارتباط میان کاربران نرم‌افزار شما و اهدافتان آسان‌تر می‌شود. به‌مجرد اینکه این اهداف واضح شود، مشخصات وابستگی انعطاف‌پذیر (نه آن‌چنان انعطاف‌پذیر) می‌تواند نهایتاً ایجاد شود. یک مثال ساده می‌تواند نشان دهد که چگونه نسخه‌بندی معنایی می‌تواند جهنم وابستگی را به خاطره‌ای از گذشته تبدیل کند. کتابخانه‌ای به نام «Firetruck» را در نظر بگیرید. این کتابخانه به یک بسته به نام «Ladder» که به صورت معنایی نسخه‌بندی شده، احتیاج دارد. در زمانی که firetruck ساخته شده، Ladder در نسخه‌ی 3.1.0 است، شما می‌توانید وابستگی Ladder را با آسودگی به عنوان بزرگتر یا برابر با 3.1.0 و نه کمتر از 4.0.0 تعیین کنید. شما می‌توانید آن‌ها را در سیستم مدیریت بستهٔ خود منتشر کنید و بدانید که آن‌ها با نرم‌افزار وابسته موجود سازگار هستند. بدون شک به عنوان یک توسعه‌دهنده‌ی مسئولیت‌پذیر شما خواهید خواست که هر بسته همان‌طورکه اعلان شده ارتقاء یابد. دنیای واقعی مکان به هم ریخته ایست، ما جز اینکه هشیار باشیم نمی‌توانیم کاری درباره‌ی آن انجام دهیم. آنچه شما می‌توانید انجام دهید این است که بگذارید نسخه‌بندی معنایی به شما یک راه عاقلانه ارائه دهد، تا بسته‌ها را منتشر کرده و ارتقاء دهد بدون آنکه نسخه‌های جدیدی از بسته‌های مستقل را راه اندازی کند و شما را عذاب نداده، در وقت شما صرفه‌جویی کند.. اگر همه‌ی این‌ها مطلوب به نظر می‌رسد، همه‌ی آنچه شما برای شروع استفاده از نسخه‌بندی معنایی احتیاج دارید این است که اعلام کنید که در حال انجام این کار هستید و از قوانین پیروی کنید. به این وب‌سایت از طریق صفحه README خود لینک بزنید، در نتیجه دیگران دربارهٔ قوانین خواهند دانست و از آن نفع خواهند برد. سوالات متداول چگونه باید با نسخه‌ها در فاز توسعه‌ی ابتدایی 0.y.z کنار بیایم؟ ساده‌ترین کار برای انجام دادن این است که توسعهٔ ابتدایی خود را از انتشار 0.1.0 آغاز کنید و سپس نسخهٔ جزیی را برای هر انتشار آتی افزایش دهید. چگونه بدانم چه زمانی باید 1.0.0 را منتشر کنم؟ اگر نرم‌افزار شما در طول تولید مورد استفاده قرار گرفته است، احتمالاً می‌بایست هم‌اکنون 1.0.0 باشد. اگر یک API ماندگار دارید که کاربران روی آن حساب می‌کنند، شما باید 1.0.0 باشید. اگر در مورد سازگاری با نسخه‌های قبل خیلی نگران هستید، احتمالاً می‌بایست هم‌اکنون 1.0.0 باشید. آیا این روش، توسعه و تکرار سریع را کند نمی کند؟ نسخه‌ی اصلی صفر تماماً در مورد توسعهٔ سریع است. اگر شما API را هر روز تغییر می‌دهید، یا باید هنوز در نسخه‌ی 0.y.z باشید یا در یک شاخه‌ی توسعه‌ی جداگانه که بر نسخه‌ی اصلی بعدی کار می‌کند هستید. اگر حتی کوچکترین تغییرات ناسازگار با نسخه‌های قبل در API عمومی نیازمند یک نسخهٔ اصلی باشد، آیا من خیلی سریع به نسخه 42.0.0 نخواهم رسید؟ این سوال یک توسعه‌دهنده‌ی مسئولیت‌پذیر و آینده‌نگر است. تغییرات ناسازگار نمی‌بایست به راحتی در نرم‌افزاری که کدهای وابسته‌ی زیادی دارد معرفی شود. هزینه‌ای که برای ارتقاء باید متحمل شد می‌تواند قابل توجه باشد. اجبار برای ایجاد نسخه‌های اصلی برای انتشار تغییرات ناسازگار، یعنی شما به تأثیر تغییراتتان فکر خواهید کرد و نرخ هزینه/سود مورد نظر را خواهید سنجید. مستندسازی تمامی API عمومی کار بسیار زیاد می‌برد! این مسئولیت شما به عنوان یک توسعه‌دهنده‌ی حرفه‌ای است تا به طور مناسب نرم‌افزار که می‌بایست توسط دیگران مورد استفاده قرار گیرد را مستندسازی کنید. مدیریت پیچیدگی نرم‌افزار یک بخش فوق‌العاده مهم ازکارآمد نگه‌داشتن پروژه است، و انجام آن سخت است اگر کسی نداند که چگونه نرم‌افزار شما را استفاده کند یا چه متدهایی برای صدا زدن امن است. در دراز مدت، نسخه‌بندی معنایی و پافشاری بر یک API عمومی خوش‌تعریف می‌تواند همه چیز و همه کس را در اجرا کردن راحت در موقعیت مناسبی نگه دارد. چه کار می‌توانم بکنم اگر تصادفاً یک تغییر ناسازگار با نسخه‌های قبل را به عنوان نسخه‌ی جزئی منتشر کردم؟ به مجرد اینکه متوجه این مورد بشوید، تنظیمات نسخه‌بندی معنایی را به هم زده‌اید، مشکل را حل کنید و یک نسخه‌ی جزیی جدید که مشکل را تصحیح کند و سازگاری با نسخه‌های قبل را بازگرداند، منتشر سازید. حتی تحت این شرایط، این پذیرفته شده نیست که انتشارهای نسخه‌بندی شده را دستکاری کنید. اگر مناسب است نسخه‌ی متخلف را مستند‌سازی کنید و کاربران خود را از مشکل مطلع سازید تا آن ها نیز از نسخه‌ی متخلف آگاه باشند. چه کار باید بکنم اگر وابستگی‌های خودم را بدون تغییر دادن API عمومی به‌روزرسانی کردم؟ این مورد تا زمانی که API عمومی را متأثر نسازد سازگار تلقی خواهد شد. نرم‌افزاری که صریحاً به همان وابستگی‌هایی که بسته‌ی شما وابسته است، وابسته باشد، باید مشخصات وابستگی خود را داشته باشد و نویسنده باید هرگونه مغایرت را ذکر کند. تشخیص اینکه آیا تغییر ازنوع دستکاری در سطح جزیی است یا سطح وصله، به این بستگی دارد که آیا شما وابستگی‌های خود را جهت تصحیح یک خطا یا برای یک کاربرد جدید به‌روزرسانی کرده‌اید. من معمولاً کد اضافی برای موارد آتی در نظر می‌گیرم، که بدون شک این موارد افزایش سطح جزیی می‌باشد. چه می شود اگر من بدون اعلام قبلی API عمومی را به صورتی تغییر دهم که با تغییر عدد نسخه سازگار نباشد؟ (یعنی کد به نادرست تغییر اصلی‌ای را در انتشار وصله معرفی می‌کند) از بهترین قضاوت خود استفاده کنید. اگر شما مخاطبان زیادی دارید که به شدت به وسیله‌ی تغییر رفتار به آنچه قبلاً برای API عمومی در نظر گرفته شده، متأثر خواهند شد، پس بهترین کار انجام یک انتشار نسخه‌ی اصلی است، حتی اگر اصلاح اعمال شده مؤکداً یک انتشار وصله محسوب شود. به یاد داشته باشید، نسخه‌بندی معنایی تماماً درباره‌ی انتقال معنا بوسیله چگونگی تغییر عدد نسخه می‌باشد. اگر این تغییرات برای کاربران شما مهم است، از عدد نسخه برای آگاه‌سازی آن‌ها استفاده کنید. چگونه باید با منسوخ کردن عملکرد (deprecating functionality) کنار بیایم؟ منسوخ کردن عملکرد موجود بخشی عادی از توسعه‌ی نرم‌افزار است و معمولاً برای این‌که پیشرفت رو به جلو حاصل شود مورد نیاز است. زمانی‌که بخشی از API عمومی خود را منسوخ می‌کنید، باید دو کار انجام دهید: ۱) مستندسازی خود را به‌روزرسانی کنید تا به کاربر اجازه دهید از تغییرات باخبر شود. ۲) یک انتشار جزیی که در آن قسمت منسوخ شده در جایگاه خود باشد منتشر کنید. قبل از آنکه عملکرد را به طورکامل در یک انتشار اصلی حذف کنید حتماً باید حداقل یک انتشار جزیی که شامل قسمت منسوخ شده است وجود داشته باشد تا کاربران به راحتی بتوانند به API جدید منتقل شوند. آیا SemVer محدودیت اندازه بر روی رشته‌ی نسخه دارد؟ خیر، اما از قضاوت مناسبی استفاده کنید. به عنوان مثال یک نسخه‌ی ۲۵۵ نویسه‌ای احتمالاً مفید نخواهد بود! همچنین، سیستم‌های خاص ممکن است محدودیت‌های خود برای اندازه‌ی رشته اعمال کنند. - منبع
  3. 1 امتیاز
    متشکرم! دقیقا همینطوره! به نکته ای درستی اشاره کردید. خیلی وقتها به علت وسعت نرم افزار و طبعا هرچه نرم افزار stable بشه در محل نصب مشتری همیشه یکی از چالش های بزرگ این هست که بخواهید تغییری در نرم افزار ایجاد کنید و تضمین کنید که تمام تست های رگرسیون هم بدرستی انجام شده باشه! والبته به همین سادگی هم نیست که بتوان تمام بخش های نرم افزار را تست رگرسیون انجام داد، حتی در صورتی که نرم افزار شما به صورت Test Domain Driven طراحی شده باشد به هرحال کار پر زحمت و پر چالشی هست بنابراین اغلب شرکتهای بزرگ تولید کننده نرم افزار همیشه از تغییرات حساس و بزرگ واهمه دارند و کمتر سمت اش میرن. البته منظور من بیشتر نرم افزارهای کاربردی و حیاتی هستش! بذارید سناریویی که برای خود من اتفاق افتاد را توضیح بدم! در یکی از لینوکس های ردهت که برای مشتری در سالهای قبل نصب کردیم، نیاز داشتیم که نرم افزارهای مشتری را به روز کنیم تا با برخی از سخت افزارهای جدیدتر شرکت بتونن ارتباط داشته باشند، ولی از آنجائیکه ردهت قدیمی بود تغییر در کتابخانه هایی که در پست اول هم اشاره کردم باعث از کار افتادن کرنل میشد بنابراین اومدم یک اسکریپت نوشتم که قبل از اینکه نرم افزار اصلی اجرا بشه مسیر بعضی از کتابخانه هایی که لازم داشتم را با استفاده از همین روش تغییر دادم و تونستم برنامه اصلی را اجرا کنم البته با استفاده از دستورات ld,ldconfig حتما باید لینک ها لازم را برای کتابخانه ها بسازید. بنابراین استفاده از تکنیک preloader library در لینوکس مربوط به یک محیط توسعه خاص نیست، کافی است که در زمان کد نویسی اصول پایه ای برنامه نویسی FURPS را رعایت کنید. پس اگر در کیوت هم که نرم افزار تولید میکنید، باید سعی کنید که به صورت ماژولار برنامه بنویسید و همیشه سعی داشته باشید که از کتابخانه های استاندارد زبان بیشترین بهره را ببرید و تا جایی که امکان داره هسته نرم افزار خودتون را با استانداردها توسعه بدید و از کتابخانه های غیر استاندارد در لایه منطق کمتر استفاده کنید تا وابستگی های کمتری داشته باشید و در زمان های لازم امکان استفاده از چنین تکنیک هایی را داشته باشید. البته به طور قطع به یقین امکان استفاده از چنین تکنیک هایی در لایه های دیگر نرم افزار هم وجود دارده! مثلا تصور کنید که یک کلاس خاص طراحی کرده باشید برای مدیریت ارتباطات بین لایه داده ها و لایه بیزینس نرم افزار تون، فرض کنید تا یک نسخه ای از برنامه شما ملزم به استفاده از پایگاه داده SQL SERVER بودید ولی در نسخ جدید نرم افزارتون نیاز دارید که فقط همین لایه ارتباط با پایگاه داده را توسعه بدید و به یک پایگاه داده دیگه مثل اوراکل متصل کنید و سایر قسمتهای دیگه برنامه به راحتی به کار خودشون ادامه بدهند خوب تحت این شرایط چند تا سناریو داریم... 1- آیا از اول امکانش هست که نیاز سنجی دقیقی داشته باشیم که تمامی این فیچرها را در نرم افزار عملیاتی کرده باشیم؟ خوب قطعا خیر تازه در صورتی هم که میشد کار عاقلانه ای نیست که در زمان حال فیچر ها را به نرم افزار تحمیل کنیم و ... 2- آیا امکانش هست که ما کلاس فوق را با تغییرات جدید به روز کنیم؟ شاید بله جواب این سوال باشه! ولی قطعا به نسبت بزرگی نرم افزار و پیچیدگی های اون درصد موفق بودن این کار خیلی کم میتونه باشه و ازهمه بدتر تست های رگرسیون هم زمان و هم انرژی وهم هزینه ای زیادی خواهد داشت پس بنابراین این کار هم شدنی نیست! تقریبا. 3- آیا امکانش هست که من فقط یک کتابخانه برای کاربر ارسال کنم و الباقی تنظیمات و نرم افزار اصلی بدون خللی به کارشون ادامه بدهند وتازه حلقه تست رگرسیون هم خیلی کوچکتر کنم فقط محدود به خود کتابخانه باشه؟ خوب قطعا با روضه هایی که تاحالا خوندم بله امکانش هست، خیلی راحت در آینده میام یک کتابخانه طراحی میکنم و روش های اتصالات جدید را هم به سیستم اضافه میکنم که هم بتونم به اس کیو ال سرور متصل باشم وهم به اوراکل (البته این پایگاه های داده فقط برای مثال بود) حالا شاید بپرسید که در ویندوز هم امکان چنین چیزی وجود داره! خوب من شخصا چنین چیزی در ویندوز ندیدم که بتوان مسیر کتابخانه های استاندارد زبان را تغییر داد اونهم به این علت که فلسفه وجودی لینوکس و ویندوز خیلی باهم متفاوت هستند و اصولا ویندوز کمتر اجازه میده که مسیر های کتابخانه های سیستمی را تغییر داد چون قطعا با این کار خود ویندوز هم آسیب پذیر میشه همانطور که لینوکس هم می تونه آسیب ببینه! ولی معمولا در ویندوز از DLL ها برای توسعه نرم افزارها استفاده میشود که نحوه ساختن و استفاده از اونها در ویندوز با کتابخانه های Shared , Static کمی متفاوت تر هستش! و اغلب نیازهای نرم افزار را برآورده میکنند. و در سیستم عامل مک او اس هم به علت اینکه unix base هستش قطعا نحوه استفاده از کتابخانه ها خیلی شبیه به لینوکس هستش البته اگر از clang استفاده کنید وبه زبان سی++ کد بزنید! برای اطلاعات بیشترهم این مستند Using Dynamic Libraries in Mac OS را مطالعه کنید.
  4. 1 امتیاز
    معرفی سیاهه‌ی تغییرات (Change Log) سیاهه‌ی تغییرات (changelog یا CHANGELOG) اشاره به یک سیاهه یا تاریخچه‌ی تغییراتی دارد که در یک پروژه همانند یک وب‌سایت اینترنتی یا یک پروژه نرم‌افزاری اعمال می‌شوند. یک پرونده‌ی سیاهه‌ی تغییرات شامل یک لیستی است از تغییرات قابل توجه برای هر نسخه از یک پروژه. این تغییرات عموماً به عنوان اصلاحات باگ‌ها، قابلیت‌های جدید و ... در این سیاهه نوشته می‌شوند. برخی از پروژه‌های متن‌باز فایل سیاهه‌ی تغییرات را در دایرکتوری سطح بالای کدهای منبع پروژه خود قرار می‌دهند. هرچند که قرارداد متعارف نام‌گذاری این فایل ChangeLog است، این فایل گاهی اوقات به صورت CHANGES یا HISTORY هم نام‌گذاری می‌شود (باید توجه داشت که NEWS فایل متفاوتی است که تغییرات بوقوع پیوسته از یک نسخه به نسخه دیگر در آن نوشته می‌شود، نه تغییراتی که از یک کامیت به کامیتی دیگر اتفاق افتاده‌اند). برخی از نگه‌دارنده‌های پروژه‌ها پسوند ‎.txt را هم به انتهای این فایل اضافه می‌کنند. برخی از سیستم‌های نسخه‌بندی قادر به تولید کردن اطلاعاتی هستند که مناسب قرارگرفتن در یک فایل سیاهه‌ی تغییرات است. چرا باید از سیاهه‌ی تغییرات جهت حفظ تغییرات استفاده شود؟ برای اینکه کاربران و مشارکت کنندگان به راحتی بدانند که دقیقاً چه تغییرات قابل توجهی بین هر نسخه‌ی انتشار یافته و دیگر نسخه‌ها ایجاد شده است، بهتر است از این اصول پیروی شود. چه کسانی به سیاهه‌ی تغییرات نیاز دارند؟ چه مصرف‌‌کنندگان و چه توسعه‌دهندگان، کاربران نهایی نرم‌افزار، انسان‌هایی هستند که به آنچه در نرم‌افزار تغییر پیدا می‌کند اهمیت می‌دهند؛ هنگامی که نرم‌افزار تغییر پیدا می‌کند، مردم می‌خواهند بدانند که چرا و چطور این تغییرات اعمال شده است. بنابراین استفاده از این قالب علاوه بر ارائه‌ی ارزشی در بحث تجربه‌کاربری، در روند توسعه اهمیت بسیاری دارد. چطور می‌توانم یک سیاهه‌ی تغییرات خوب ایجاد کنم؟ راهنمای اصول سیاهه‌ی تغییرات برای انسان‌ها هستند نه ماشین. برای هر کدام از نسخه‌ها باید یک مدخل وجود داشته باشد. انواع مشابه تغییرات باید دسته‌بندی شوند. نسخه‌ها و بخش‌ها باید پیوند پذیر باشند. آخرین نسخه اول می‌آید. تاریخ عرضه‌ی هر کدام از نسخه‌ها، نمایش داده می‌شود. از استاندارد و اصول نسخه‌بندی معنایی استفاده و آن را رعایت کنید. انواع تغییرات Added برای امکانات جدید. Changed برای تغییر در عملکرد موجود. Deprecated برای امکاناتی که به زودی حذف می‌شوند. Removed برای امکانات حذف شده. Fixed برای هر نوع رفع خطا. Security در صورت وجود هرگونه آسیب‌پذیری امنیتی. برای ردیابی تغییرات آتی یک بخش با عنوان Unreleased در بالا نگه‌دارید، این کار دو هدف دارد: مردم می‌توانند ببیند که در نسخه‌های آینده چه تغییراتی را می‌توان انتظار داشت. در زمان انتشار، می‌توانید تغییرات بخش Unreleased را به بخش نسخه‌ی جدید منتقل کنید. آیا استانداردی برای سیاهه‌ی تغییرات وجود دارد؟ حقیقتاً خیر، هرچند سبکی از گنو و همچنین بخشی از فایل خبر گنو به این مورد اشاره دارند، اما این‌ها ناکافی می‌باشند. نام فایل سیاهه‌ی تغییرات چه باید باشد؟ می‌توانید آن را CHANGELOG.md بنامید. برخی از پروژه‌ها از HISTORY، NEWS و یا RELEASES استفاده می‌کنند. هرچند مهم نیست که نام فایل نهایی این روند چه چیزی باشد، اما طوری باید باشد که کاربر متوجه هدف فایل تغییرات باشد. یک مثال از قالب صحیح از سیاهه‌ی تغییرات # Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [1.0.0] - 2017-06-20 ### Added - New visual identity by [@tylerfortune8](https://github.com/tylerfortune8). - Version navigation. - Links to latest released version in previous versions. - "Why keep a changelog?" section. - "Who needs a changelog?" section. - "How do I make a changelog?" section. - "Frequently Asked Questions" section. - New "Guiding Principles" sub-section to "How do I make a changelog?". - Simplified and Traditional Chinese translations from [@tianshuo](https://github.com/tianshuo). - German translation from [@mpbzh](https://github.com/mpbzh) & [@Art4](https://github.com/Art4). - Italian translation from [@azkidenz](https://github.com/azkidenz). - Swedish translation from [@magol](https://github.com/magol). - Turkish translation from [@karalamalar](https://github.com/karalamalar). - French translation from [@zapashcanon](https://github.com/zapashcanon). - Brazilian Portugese translation from [@Webysther](https://github.com/Webysther). - Polish translation from [@amielucha](https://github.com/amielucha) & [@m-aciek](https://github.com/m-aciek). - Russian translation from [@aishek](https://github.com/aishek). - Czech translation from [@h4vry](https://github.com/h4vry). - Slovak translation from [@jkostolansky](https://github.com/jkostolansky). - Korean translation from [@pierceh89](https://github.com/pierceh89). - Croatian translation from [@porx](https://github.com/porx). - Persian translation from [@Hameds](https://github.com/Hameds). - Ukrainian translation from [@osadchyi-s](https://github.com/osadchyi-s). ### Changed - Start using "changelog" over "change log" since it's the common usage. - Start versioning based on the current English version at 0.3.0 to help translation authors keep things up-to-date. - Rewrite "What makes unicorns cry?" section. - Rewrite "Ignoring Deprecations" sub-section to clarify the ideal scenario. - Improve "Commit log diffs" sub-section to further argument against them. - Merge "Why can’t people just use a git log diff?" with "Commit log diffs" - Fix typos in Simplified Chinese and Traditional Chinese translations. - Fix typos in Brazilian Portuguese translation. - Fix typos in Turkish translation. - Fix typos in Czech translation. - Fix typos in Swedish translation. - Improve phrasing in French translation. - Fix phrasing and spelling in German translation. ### Removed - Section about "changelog" vs "CHANGELOG". ## [0.3.0] - 2015-12-03 ### Added - RU translation from [@aishek](https://github.com/aishek). - pt-BR translation from [@tallesl](https://github.com/tallesl). - es-ES translation from [@ZeliosAriex](https://github.com/ZeliosAriex). ## [0.2.0] - 2015-10-06 ### Changed - Remove exclusionary mentions of "open source" since this project can benefit both "open" and "closed" source projects equally. ## [0.1.0] - 2015-10-06 ### Added - Answer "Should you ever rewrite a change log?". ### Changed - Improve argument against commit logs. - Start following [SemVer](https://semver.org) properly. ## [0.0.8] - 2015-02-17 ### Changed - Update year to match in every README example. - Reluctantly stop making fun of Brits only, since most of the world writes dates in a strange way. ### Fixed - Fix typos in recent README changes. - Update outdated unreleased diff link. ## [0.0.7] - 2015-02-16 ### Added - Link, and make it obvious that date format is ISO 8601. ### Changed - Clarified the section on "Is there a standard change log format?". ### Fixed - Fix Markdown links to tag comparison URL with footnote-style links. ## [0.0.6] - 2014-12-12 ### Added - README section on "yanked" releases. ## [0.0.5] - 2014-08-09 ### Added - Markdown links to version tags on release headings. - Unreleased section to gather unreleased changes and encourage note keeping prior to releases. ## [0.0.4] - 2014-08-09 ### Added - Better explanation of the difference between the file ("CHANGELOG") and its function "the change log". ### Changed - Refer to a "change log" instead of a "CHANGELOG" throughout the site to differentiate between the file and the purpose of the file — the logging of changes. ### Removed - Remove empty sections from CHANGELOG, they occupy too much space and create too much noise in the file. People will have to assume that the missing sections were intentionally left out because they contained no notable changes. ## [0.0.3] - 2014-08-09 ### Added - "Why should I care?" section mentioning The Changelog podcast. ## [0.0.2] - 2014-07-10 ### Added - Explanation of the recommended reverse chronological release ordering. ## [0.0.1] - 2014-05-31 ### Added - This CHANGELOG file to hopefully serve as an evolving example of a standardized open source project CHANGELOG. - CNAME file to enable GitHub Pages custom domain - README now contains answers to common questions about CHANGELOGs - Good examples and basic guidelines, including proper date formatting. - Counter-examples: "What makes unicorns cry?" [Unreleased]: https://github.com/olivierlacan/keep-a-changelog/compare/v1.0.0...HEAD [1.0.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.3.0...v1.0.0 [0.3.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.2.0...v0.3.0 [0.2.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.1.0...v0.2.0 [0.1.0]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.8...v0.1.0 [0.0.8]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.7...v0.0.8 [0.0.7]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.6...v0.0.7 [0.0.6]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.5...v0.0.6 [0.0.5]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.4...v0.0.5 [0.0.4]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.3...v0.0.4 [0.0.3]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.2...v0.0.3 [0.0.2]: https://github.com/olivierlacan/keep-a-changelog/compare/v0.0.1...v0.0.2 [0.0.1]: https://github.com/olivierlacan/keep-a-changelog/releases/tag/v0.0.1
  5. 1 امتیاز
    وب‌اسمبلی (WebAssembly) یا wasm یک فناوری برنامه‌نویسی سطح‌پایین برای استفاده در مرورگر است. هدف اولیه‌ی آن پشتیبانی از کامپایل کد‌ها به سی و سی++ است هرچند که قرار است از سایر زبان‌ها نیز حمایت شود. حال کتابخانه‌ی Qt این امکان را تحت ماژول Qt WebAssembly فراهم می‌کند تا برنامه‌‌ی نوشته شده توسط سی++ و کیوت در محیط مرورگر قابل اجرا باشند. این ویژگی در حال حاضر به عنوان پیش‌نمایش برای نسخه‌ی Qt 5.11 برنامه‌ریزی شده است. کیوت برای ساخت وب اسمبلی دستور‌العمل‌هایی را در اینجا آورده است. قبل از هرچیز شما نیاز دارید تا ابزار کامپایلر emsdk را آماده و نصب نمایید. بنابراین دستورات زیر را به ترتیب اجرا کنید. # Get the emsdk repo git clone https://github.com/juj/emsdk.git # Enter that directory cd emsdk # Fetch the latest registry of available tools. ./emsdk update # Download and install the latest SDK tools. ./emsdk install latest # Make the "latest" SDK "active" for the current user. (writes ~/.emscripten file) ./emsdk activate latest # Activate PATH and other environment variables in the current terminal source ./emsdk_env.sh در صورتی که در پیکربندی نیاز به راهنمایی دارید از راهنمای اصلی آن استفاده کنید و یا در همین مرجع در تالار‌های گفتمان از ما بپرسید. ما به این ابزار به عنوان ابزار کامپایل-چند‌منظوره استفاده خواهیم کرد. برخی از اسکرین شات‌ها از نتایج خروجی این ماژول به صورت زیر آمده‌اند: یک بازی ساده به نام Colliding mice ویژگی پنجره‌های گفتگو به نظر می‌رسد پنجره‌های ساخته شده توسط QOpenGLWindow با فریم ریت ۶۰ به خوبی عمل می‌کنند. البته به نظر می‌رسد QOpenGLWidget فعلاً شامل برخی از مشکلات است که حل خواهند شد. کامپایلر Emscripten که به عنوان یک کامپایلر منبع‌باز که بک اند آن بر روی LLVM اجرا می‌شود کُد‌های OpenGL را به WebGL ترجمه می‌کند. بنابراین محدودیت‌هایی در نسخه‌های دسکتاپ و اِمبد‌ها وجود خواهد داشت. نمونه مثال پنجره تحت OpenGL در کنار این‌ها QtBases و QtDeclarative که از شاخه‌ی Wip/Web Assembly استقاده می‌کنند، ماژول‌های شناخته شده‌ی کیوت به صورت زیر به کار گرفته می‌شوند: QtCharts QtGraphicalEffects QtQuickControls QtQuickControls2 QtWebSockets QtMqtt (با استفاده از وب سوکت) برای استفاده از QtMqtt، شما باید کلاس WebSocketIODevice از نمونه مثالی با نام (websocketsubscription) وارد برنامه‌ی خود کنید. نمونه مثال‌های ساعت در QML نکته: از آن‌جا که جاوا‌اسکریپت و وب‌اسمبلی تنها یک نخ (Thread) دارند، QtDeclarative تنها برای یک نَخ (ترد) کار خواهد کرد. در نظر داشته باشید که ماژول‌های QtCharts QtGraphicalEffects، QtQuickcontrols، QtQuickControls2 بدون هیچ تغییراتی کار می‌کنند. ماژول QtChart از نمونه مثال oscilloscope این پروژه به عنوان یک رویکرد جدید و ویژگی‌ای که در آینده می‌تواند مفید باشد در حال توسعه است. بخش ویکی رسمی آن در این لینک آورده شده است.
  6. 1 امتیاز
    با توجه به اهمیت امنیت نرم افزار، شرکت های بزرگ دنیا به ارائه راهکارهایی چون طراحی زبان ها و محیط های برنامه نویسی و مفسر و مترجم هایی با قابلیت های کنترل امنیتی بر روی سیستم عامل و بسیاری از راهکارهای دیگر پرداخته اند اما با توجه به عدم توانایی راهکارها در کنترل تمامی موارد امنیتی، عدم امکان پیاده سازی راهکارهای امنیتی بر روی برخی ساختارها، ایجاد محدودیت برای دسترسی به برخی منابع و امکانات و مشکلات کوچک و بزرگ دیگر برنامه نویسی یک برنامه به صورت ایمن بهترین راهکار برای محافظت از یک برنامه است. یکی از زبان هایی که در کنار محبوبیت در میان برنامه نویسان، همیشه یکی از زبان های پر بحث در برنامه نویسی ایمن بوده است، خانواده زبان های C به خصوص ++C است. در این زبان ها عمده مدیریت منابع به برنامه نویس واگذار شده که در صورت عدم مدیریت درست آن ها، آسیب پذیری های مختلفی رخ می دهد. بهترین راهکار برای جلوگیری از بروز آسیب پذیری نرم افزارها، برنامه نویسی پدافندی و ایمن آن نرم افزار از ابتداست. دراین مستندات، باتوجه به جامعیت و کاربرد فراوان زبان ++C درکنار محبوبیت، مباحث ونکات اساسی در برنامه نویسی پدافندی و ایمن این زبان مطرح شده و انواع آسیب پذیری و شیوه جلوگیری از بروز آن ها و رفع آن ها در صورت بروز، توضیح داده می شود. همچنین سعی می شود تا راهکارهای ارائه شده تا حد امکان قابل پیاده سازی در زبان C نیز باشند. با توجه به گستردگی ابزارهای برنامه نویسی این زبان و وجود کامپایلرهای مختلف، زبان معیاری برای این مستند مدنظر قرار گرفته شده است و ساختار ارائه شده مربوط به ابزار یا کامپایلر خاصی نیست اما بنا بر نیاز مثال هایی در کنار زبان معیار از ابزارهایی خاص نیز ارائه می گردد. رفتار تعریف نشده ممکن است شامل مختل شدن عملکرد برنامه(Crash) خروجی نامربوط و غلط، بروز آسیب پذیری های نرم افزاری و موارد دیگر می باشد. وجود رفتار نامتعارف در یک برنامه نه تنها امنیت خود آن برنامه ، بلکه ممکن است امنیت سیستم عامل، شبکه را نیز به خظر بیندازد. جلوگیری از بروز رفتارهای تعریف نشده و مقابله با آن ها از مباحث مهم برنامه نویسی تدافعی و ایمن است. توابع بدون آرگومان برای تعریف یک تابع بدون آرگومان باید از کلمه کلیدی void در زمان تعریف تابع استفاده نمایید.با این کار تزریق کد توسط هکرها را مختل می کنید. int getValue(void) { return 1; } اعداد تصادفی در صورت نیاز به اعداد تصادفی از تابع ()rand استفاده نکنید به این علت که خروجی این تابع در تکرارهای بالا دچار تکرار می شود. بهتراست از تابع ()srand استفاده کنید می توانید برای آن seed تعریف کنید تا احتمال تکرار را به حداقل برسانید. در ویندوز هم می توانید از تابع ()CryptGenRandom استفاده کنید و در لینوکس هم تابع ()random و تابع ()srandom استفاده نمایید. #include <windows.h> #include <wincrypt.h> #include <iostream> int main(void) { HCRYPTPROV hcp; CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0); long int li = 0; CryptGenRandom(hcp, sizeof(li), (BYTE *)&li); printf("Random number is -> %ld\n", li); return 0; } عدم استفاده از تابع بازگشتی جهت مقدار دهی اولیه به آرایه ای با کلاس حافظه استاتیک در مثال زیر زمان ساخته شدن و مقدار دهی اولیه آرایه cache تابع fact مجددا فراخوانی شده واین عمل به دلیل ایستا بودن آرایه باعث بروز رفتار تعریف نشده و خطا خواهد شد. #include <stdexcept> int fact(int i) noexcept(false) { if (i < 0) { throw std::domain_error("i must be >=0"); } static const int cache[] = { fact (0), fact(1), fact(2), fact(3), fact(4), fact (5), fact (6), fact(7), fact(8), fact(9), fact(10), fact (11), fact (12), fact(13), fact(14), fact(15), fact(16) }; if (i < (sizeof(cache) / sizeof(int))) { return cache[i]; } return i > 0 ? i * fact (i - 1) : 1; } حال برای رفع این اشکال طبق نمونه کد زیر آرایه را بدون استفاده initializer list با استفاده از یک متغیر ثابت که تعداد عضو های آرایه را معین میکند تعریف شده است و ازآنجا که کامپایلر آرایه های از جنس کلاس حافظه استاتیک را خود با عدد 0 مقداردهی میکند دیگر یک آرایه از قبل پر شده نخواهیم داشت و در مرحله با استفاده از تکنیک lazy به هر یک از عضوهای آرایه مقدار مناسب را با استفاده از تابع بازگشتی مقدار دهی خواهیم کرد. #include <stdexcept> const int arraySize = 17 int fact(int i) noexcept(false) { if (i < 0) { throw std::domain_error("i must be >=0"); } static int cache[arraySize]; if (i < (sizeof(cache) / sizeof(int))) { if (0 == cache[i]) { cache[i] = i > 0 ? i * fact(i - 1) : 1; } return cache[i]; } return i > 0 ? i * fact(i - 1) : 1; } الحاق مضاعف هدر فایل ها الحاق مضاعف زمانی رخ می دهد که یک هدر دو ویا چند بار به برنامه اضافه شوند. در مثال زیر در کلاس c هدرهای a , b الحاق می شوند در حالی که در کلاس b هم هدر a الحاق شده است که الحاق مضاعف رخ داده است. //a.h struct a { int membe }; //b.h #include "a.h" //c.c #include "a.h" #include "b.h" برای جلوگیری از این الحاق های مضاعف می توانید از روش زیر استفاده نمایید //a.h #ifdef A_H #define A_H struct a { int member; }; #endif ویا می توانید از دستور pragma استفاده کنید البته این دستور جز دستورات استاندارد ++c / c نمی باشد ولی اکثر کامپایلرها این دستور را اجرا میکنند. //a.h #pragma once struct a { int member; }; رمزنگاری اصولی جهت رمزنگاری داده های حساس در برنامه های خود می توانید از کتابخانه ++Crypto وهمچنین کتابخانه libcrypto از OpenSSL نیز استفاده نمایید. رمز نگاری به چند دسته اصلی تقسیم می شود: 1- رمزنگاری درهم سازHash که میتوان به الگوریتم های MD6 , MD5 , SHA-1,SHA-0 اشاره کرد. 2- رمزنگاری با کلید متقارن که می توان به الگوریتم های RC4 , AES , DES , 3DES اشاره کرد. 3- رمزنگاری با کلید عمومی نا متقارن که می توان به الگوریتم های RSA , DSA , DSS اشاره کرد. 4- کد گذاری دودویی به متن که می توان به الگوریتم های Base32 , Base58 , Base64 ,Base85 اشاره کرد. مدیریت مقدار و نوع داده ها و مقدار دهی اولیه در مثال زیر متغیر هایی تعریف شده اند که مقدار اولیه ندارند (البته درست است که در برخی از کامپایلرها این متغیرها را مقدار دهی خواهند کرد، ولی توجه داشته باشید که تکنیک های برنامه نویسی تدافعی جدای از امکانات کامپایلر می باشد) int main (void) { int a; float b; char c; bool d; return 0; } اکنون مشاهده میکنید که بعد از اجرای برنامه چه مقدار هایی در متغیرها ذخیره شده است. پس بنابراین مقدار دهی اولیه متغیرها یا باید برحسب نیاز در همان ابتدا تعریف صورت گیرد یا در صورت عدم نیاز به وجود مقدار اولیه خاص، مقدار دهی با استفاده از تابع همان نوع داده انجام خواهد شد. int main (void) { int a = int(); float b = float(); char c = char(); bool d = bool(); return 0; } و بعد از اجرا به این صورت خواهد بود مقدار دهی اولیه به آرایه ها int main (void) { int a[5]; float b[5]; char c[5]; bool d[5]; return 0; } که بعد از اجرا بدین صورت خواهد بود... و برای رفع این اشکال باید همیشه آرایه ها را مقدار دهی اولیه نمایید. int main (void) { int a[5] = {}; float b[5] = {}; char c[5] = {}; bool d[5] = {}; return 0; } وبعد از مقدار دهی اولیه به آرایه ها خواهیم داشت ... ادامه خواهد داشت این مقاله...
این صفحه از پرچمداران بر اساس منطقه زمانی تهران/GMT+03:30 می باشد
×
×
  • جدید...