رفتن به مطلب
مرجع رسمی سی‌پلاس‌پلاس ایران

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

بنیـــان گذار
  • تعداد ارسال ها

    505
  • تاریخ عضویت

  • روز های برد

    266

تمامی مطالب نوشته شده توسط کامبیز اسدزاده

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

    مشکل به خاطر عدم به‌روز‌رسانی مخازن است. لطفاً با v-p-n وارد شوید و سعی کنید مخازن را به‌روز‌رسانی کنید. سپس در حین qmake و کامپایل gardle توسط خود کیوت کریتور دریافت و ادغام خواهد شد.
  2. کامبیز اسدزاده

    سلام، خطای لینکر مبنی بر این است که فایل ساخته شده‌ی کتابخانه قابل شناسایی نیست. قبل از هر چیز دستورات زیر را به ترتیب برای کامپایل (ساخت) کتابخانه‌ی tz اجرا کنید تا فایل‌ libtz.a ساخته شود. mkdir build cd build cmake ../ cmake -DENABLE_DATE_TESTING=ON --build . make در نهایت وارد یک پروژه‌ی جدید بشید تا برای افزودن کتابخانه به صورت زیر عمل کنید: فایل libtz.a را در یک پوشه‌‌ای با نام lib و محتوای کتابخانه را در پوشه‌ای با نام include در کنار پروژه‌ی خودتان قرار دهید. به دلیل اینکه این کتابخانه وابسته‌ی کتابخانه‌ی curl است، مطمئن شوید که آن نیز بر روی سیستم شما نصب باشد. دستورات زیر را در سی‌میک برای افزودن کتابخانه‌ی libtz بنویسید. add_library( date ${CMAKE_CURRENT_SOURCE_DIR}/include ) link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib) target_link_libraries(${PROJECT_NAME} PRIVATE tz) احتمالاً خطایی برای عدم توانایی لینک‌سازی با curl دریافت کنید، در این صورت دستورات زیر را در سی‌میک اضافه کنید: FIND_PACKAGE(CURL) IF(CURL_FOUND) INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR}) SET(requiredlibs ${requiredlibs} ${CURL_LIBRARIES} ) ELSE(CURL_FOUND) MESSAGE(FATAL_ERROR "Could not find the CURL library and development files.") ENDIF(CURL_FOUND) target_link_libraries(${PROJECT_NAME} PRIVATE curl) یک مثال از پروژه‌ای که من libtz را همراه کیوت ادغام کردم: cmake_minimum_required(VERSION 3.5) project(HelloCMake LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt5 COMPONENTS Widgets REQUIRED) FIND_PACKAGE(CURL) IF(CURL_FOUND) INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR}) SET(requiredlibs ${requiredlibs} ${CURL_LIBRARIES} ) ELSE(CURL_FOUND) MESSAGE(FATAL_ERROR "Could not find the CURL library and development files.") ENDIF(CURL_FOUND) add_library( date ${CMAKE_CURRENT_SOURCE_DIR}/include ) link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib) if(ANDROID) add_library(HelloCMake SHARED main.cpp mainwindow.cpp mainwindow.hpp mainwindow.ui ) else() add_executable(HelloCMake main.cpp mainwindow.cpp mainwindow.hpp mainwindow.ui ) endif() target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets) target_link_libraries(${PROJECT_NAME} PRIVATE tz) target_link_libraries(${PROJECT_NAME} PRIVATE curl) بعد از این نباید در زمان کامپایل خطایی رُخ دهد. موفق باشید!
  3. کامبیز اسدزاده

    از مشخصه‌ی setStyleSheet تحت CSS کار کن، مثال زیر رو ببین: QSlider::groove:horizontal { border: 1px solid #bbb; background: white; height: 10px; border-radius: 4px; } QSlider::sub-page:horizontal { background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #66e, stop: 1 #bbf); background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1, stop: 0 #bbf, stop: 1 #55f); border: 1px solid #777; height: 10px; border-radius: 4px; } QSlider::add-page:horizontal { background: #fff; border: 1px solid #777; height: 10px; border-radius: 4px; } QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #eee, stop:1 #ccc); border: 1px solid #777; width: 13px; margin-top: -2px; margin-bottom: -2px; border-radius: 4px; } QSlider::handle:horizontal:hover { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #fff, stop:1 #ddd); border: 1px solid #444; border-radius: 4px; } QSlider::sub-page:horizontal:disabled { background: #bbb; border-color: #999; } QSlider::add-page:horizontal:disabled { background: #eee; border-color: #999; } QSlider::handle:horizontal:disabled { background: #eee; border: 1px solid #aaa; border-radius: 4px; } البته ساختن چنین مواردی رو من در QML پیشنهاد می‌کنم.
  4. کامبیز اسدزاده

    خب فونت کل متن تغییر خواهد کرد! و این روش درستی هست. اما اگر می‌خواهید در بحث درون‌خط متنی که نوشتی یعنی «سلام بر World در زبان ++C» متن فارسی جدا و انگلیسی جدا تغییر کنند باید به فکر فونت فارسی باشی که داخلش از لاتین‌های سفارشی استفاده می‌کنه. مثل صمیم، ساحل و یا فونت‌های تجاری دیگر. در این صورت هم نیاز نیست دو تا فونت معرفی کنی، همون یک مدل کافی هست، به شرطی که از فونت لاتین استفاده کند.
  5. کامبیز اسدزاده

    سادست، کافیه یک دستور شرطی ساده براش در نظر بگیری، مثل نمونه‌ی زیر: property bool isLatin : false .. ... .... Text { font.family: isLatin ? fontSystem.getEnglishFont.name : fontSystem.getPersianFont.name .. .... }
  6. کامبیز اسدزاده

    پاسخ به این سوأل صرفاً از نظر نوع زبان کافی نیست و شاید منطقی نباشد. و چون ساختار و قوانین تحت چهارچوب مشخصی برای این موضوع نداریم، از نظر من دلایل بسیاری وجود دارد که بر روی قیمت‌گذاری می‌تواند تأثیرگذار باشد که به آن‌ها اشاره می‌کنم: تجربه و کیفیت خدماتِ قابل ارائه‌ی فرد یا شرکت توسعه‌دهنده جهت انجام آن اینکه شخص یا شرکت مربوطه بتواند تضمین کند یا آسودگی خاطر را به مشتری بدهد که پروژه‌ی آن در زمان مشخص با نتیجه‌ی قابل قبول ارائه خواهد شد بسیار مهم است، قطعاً اطمینان خاطر و جلوگیری از احتمالات دوباره‌کاری و نا رضایتی خودش ارزشمند خواهد بود که ممکن است در هزینه‌ی نهایی پروژه موثر باشد. تضامین و خدمات پس از فروش «پشتیبانی، به‌روز‌رسانی و غیره» هرچند پشتیبانی و به‌روزرسانی محصولات نرم‌افزاری یکی از مراحل توسعه و چرخه‌ی نرم‌افزار است، اما در دسترس بودن و تضمین پشتیبانی از سمت توسعه‌دهنده قطعاً در هزینه‌های آن نسبت به دیگر موارد متفاوت خواهد بود. نوع قرارداد و مذاکراتی که ممکن است طرفین در قبال تعهد به آن‌ها هزینه‌هایی را اضافه کند معمولاً در قرارداد‌های طرفین به نکاتی اشاره می‌شود، مانند: در دسترس بودن منبع‌کد «سورس‌کد» و یا مستند سازی غیر معمول و اختصاصی که حتماً در قیمت نهایی یک محصول و پروژه موثر خواهد بود. محدودیت‌ها و دلایل قانع کننده برای انتخاب یک ابزار و نیاز به دانش و مهارت‌های تخصصی ممکن است پروژه‌ای که به شما پیشنهاد می‌شود، با یک سری محدودیت‌های فنی بر اساس نوع زبان، مهارت و بستر‌های پیاده‌سازی مواجه باشد که با توجه به ارائه‌ی راه‌کار‌های مناسب توسط متخصص «توسعه‌دهنده» که واقعاً نیاز به تجربه و دانش در حل آن است وابسته خواهد بود. در چنین حالت‌های ارزش حل مسائل می‌تواند در خود پروژه تأثیر‌ بگذارد. در نهایت بعد از بررسی موارد این چنینی که من تنها به برخی از آن‌ها اشاره کردم، می‌توانید به خروجی‌ها و نتایج حاصل از خود ابزار که در اینجا «++C» است اشاره کرده و مشتری را نسبت به آن قانع کنید. برای مثال، ویژگیِ چند-سکویی خود به تنهایی یک مزیت بسیار بزرگ است که می‌تواند در حذف هزینه‌های احتمالی مانند بازنویسی در زمان توسعه و به‌روز رسانی در قالب سکو‌های مختلف موثر باشد. نوع مذاکره در ساخت و توسعه در قالب زمان مشخص برای ساده‌سازی مسئله و حل باید‌ها و نباید‌ها نیز مشخص سازی یک نرخ یا رنج قیمت برای کار بر روی پروژه می‌تواند موثر باشد. برای مثال، بر اساس تعداد ساعت و زمان مشخص در روز می‌توانید یک محاسبه‌ی مشخصی برای مشتری خود انتقال دهید تا هم زمان تحویل و هم مدت زمات مورد نیاز برای توسعه را بداند. درباره‌ی همین موضوع چند-سکویی که تنها یک ویژگی از مزایای سی‌پلاس‌پلاس است مثالی بزنم: فرض کنید قرار است مشتری یک نرم‌افزار تحت موبایل از شما درخواست کند، در این صورت اگر قرار باشد منطقی مذاکره کنید، بهتر است مشتری را متوجه این سازید که برای ساخت یک اپلیکیشن در سکو‌های مختلف مانند iOS، Android و غیره نیاز به تخصص، زمان و هزینه‌های جدا از هم است. اما اگر شما به عنوانی توسعه‌‌دهنده‌ی تمام عیار فول‌اِستک هستید، می‌توانید مشتری را قانع کنید که صرفاً با یکپارچه‌سازی کد‌های توسعه و ساختار بهینه‌ی برنامه‌های نوشته شده‌ی تحت سی++ از صرف هزینه‌های احتمالی جهت توسعه‌ جلوگیری می‌کنید و حتی در آینده نیازی نیست هزینه‌های اضافه بر مشتری تحمیل کنید. در این رابطه باید به یک هزینه‌ی قابل قبول همراه با حفظ ارزش‌های وارده را مطرح کنید. برای مثال، اگر قرار است یک اپلیکیشن برای دو پلتفرم مختلف توسعه یابد، اگر قیمتی بابت یک نرم‌افزار در دو سکوی مختلف استعلام و یا تخمین زده شده باشد، بهتر است شما با در نظر گرفتن نصف و یا حد‌اکثر دو سوم آن همان کارها را با حفظ ارزش‌های فنی و کاربری مشتری انجام دهید. بر اساس چنین مواردی نیازی به افزایش یا کاهش هزینه‌ها در یک پلتفرم وجود ندارد چرا که تنها کاری که انجام خواهید داد هم‌گردانی «کامپایل» کد‌ها بر روی پلتفرم دیگر خواهد بود.
  7. کامبیز اسدزاده

    چگونه با مشتریِ خود صحبت کنیم

    با سلام و درود، همهٔ ما می‌دانیم که امروزه کسب‌و‌کار‌های اینترنتی و وابسته به فناوری‌های مبتنی بر نرم‌افزار، یکی از حوزه‌هایی به شمار می‌رود که در چهارچوب خود می‌توانند پیشرفت بسیار چشم‌گیری داشته باشند. بنابراین، هر فردی که ایده‌ای در ذهن خود برای خلق یک کسب‌و‌کار دارد می‌تواند وارد این حوزهٔ «کسب‌و‌کار‌های» اینترنتی شود. در این مقاله من به عناوین زیر اشاره خواهم کرد: گفتگوی صمیمانه و آزاد «مشاوره و ارزیابی مسائل» واقعیت‌هایی که مشتریان از آن‌ها آگاه نیستند مشتری را برای مقایسه و دیدن نمونه‌های واقعی تشویق کنید معرفی و توصیف ابزار‌هایی که از آن‌ها برای تولید و توسعه استفاده می‌کنید صداقت شما و تضمین وفاداری مشتری قرارداد، ارزیابی هزینه‌ها و زمان توسعه مشاورهٔ رایگان یا پولی چگونه از دیگر برنامه‌نویسان و توسعه‌دهندگان متمایز و به یک برنامه‌نویس واقعی و حرفه‌ای تبدیل شویم؟ به‌روز باشید و از رفتار‌های تعصبی بپرهیزید محصولات با کیفیت در سطح جهانی تولید کنید خدمات پشتیبانی، تضمین پاسخگو بودن طبیعی است که راه‌اندازی چنین مواردی نیاز به دانش و مهارت‌های تخصصی در حوزهٔ مهندسی کامپیوتر، نرم‌افزار و شاخه‌های دیگر آن خواهد داشت. برای مثال: راه‌اندازی یک وب‌سایت برای معرفی کسب‌و‌کار مشتری نیازمند یک فرآیند ارزیابی، استعلام، ثبت، تخصیص فضای میزبانی، طراحی، برنامه‌نویسی، توسعه و پشتیبانی است. در این حالت مشتری می‌بایست با مراجعه به یکی از شرکت‌ها و یا متخصص‌های این حوزه خواستهٔ خود را به آن ارائه کند تا مطابق با آن کسب‌و‌کار ارزیابی و توسعه یابد. اگر شما به دنبال این هستید که سریعاً مشتری خود را قانع و پروژه‌ای را برای انجام بپذیرید، شک نکنید که احتمال شکست و نارضایتی در هر دو طرف بسیار بالا خواهد بود. ممکن است شما رزومهٔ بسیار قوی‌ با نمونه‌کار‌های بسیار جذاب در اختیار داشته باشید که مشتری در لحظهٔ اول به توانایی‌های شما مطمئن شود. اما این به تنهایی کافی نیست! گفتگوی صمیمانه و آزاد «مشاوره و ارزیابی مسائل» در این مقاله من به برخی از مشکلات مهمی که مشتریان در ابتدای کار با آن مواجه هستند می‌پردازم که عبارتند از: عدم شناخت کافی به ابزار‌ها، روش‌ها، الگو‌ها و حتی افراد و شرکت‌های انجام دهندهٔ این خدمات. جالب است بدانید که مشتری بر اساس دانسته‌ها، شنیده‌ها و همچنین دیده‌های خود از الگو‌های نه چندان ارزیابی شده تصویری را از کسب‌و‌کار خود ترسیم می‌کند که کاملاً خام است که اگر توسط متخصصین مورد بررسی قرار نگیرد ممکن است به مسیر نادرست و نا آگاهانه‌ای هدایت شوند که نتیجهٔ آن به جز ناامیدی و نا رضایت مشتری نخواهد بود. بنابراین اگرچه دنیای طراحی و توسعهٔ نرم‌افزار می‌تواند همه‌گیر باشد، اما واقعیت آن است که «باید کار را به کاردان سپرد» کاردان‌هایی که می‌توانند با مورد ارزیابی قرار دادن ایده‌های ذهنی مشتری آن را درک، هدایت و بهبود بخشد. من در بسیاری از جلسات کاری خودم برای شنیدن خواسته‌های مشتری نسبت به طرحی که در ذهن خود داشته این مشکلات را به خوبی دیده و درک می‌کنم. به عنوان مثال: مشتری در ابتدای کار مایل به بیان سریع تصویری از ایده یا راه‌کار خود برای توسعهٔ کسب‌و‌کاری است که شامل استراتژی کامل و نهایی شده‌ای نیست. البته من اطمینان می‌دهم این اشتباهات طبیعی بوده و یکی از وظایف برنامه‌نویسان حرفه‌ای این است که با متکی بودن به علم روان‌شناسی و هم‌دلی در شنیدن خواسته‌های مشتری سعی در تأیید همراه با اصلاح و هدایت آن به بهترین سمت ممکن باشد. در نظر داشته باشید که احتمال بسیار زیادی وجود دارد که ابتدای کار در همان دقایق اولیه جلسه مطالبی را از مشتری خود بشنوید که واقعاً در کسب‌و‌کار او نیاز نیست و یا حتی فراتر و متفاوت‌تر از آن چیزی است که در عمل باید به آن متکی بود. حتی در همان دقایق اول احتمال بسیار زیادی دارد که از مشتری چنین سوألاتی را بشنوید «شما بابت این کار چقدر هزینه می‌گیرید؟» البته این نوع سوألات حتی در پشت تلفن نیز پرسیده می‌شود، اما برای اینکه ارزش کار خودتان را حفظ کنید توصیه می‌شود هیچ‌گاه بدون ارزیابی و اصول حرفه‌ای در شنیدن خواستهٔ مشتری خود نه قیمت و نه زمانی برای انجام درخواست ارائه ندهید. این روشی ناشیانه است که معمولاً افراد غیر متخصص به کار می‌گیرند. بنابراین توصیه می‌شود صحبت‌ها و ایده‌های مشتری خود را با دقت گوش کنید. تأکید می‌کنم به هیچ عنوان ایدهٔ مشتری خود را سریعاً نکوبید و آن را رد نکنید «این امر موجب می‌شود مشتری نظرش در مورد شما تغییر کند» این روش در شأن متخصص حرفه‌ای نیست. چرا که یکی از وظایف مهم شما ارائهٔ یک راهکار و مشاورهٔ مفید قبل از اخذ قرارداد و انجام آن است. سعی کنید سوأل‌هایی را بپرسید که مشتری خود به آن‌ها فکر نکرده است و با شنیدن آن حتماً نظرش جلب و از بُعد دیگری به کسب‌و‌کار خود و توسعهٔ آن نگاه خواهد کرد. شما به عنوان مشاور فنی باید بتوانید مشتری را قانع کنید که چه موردی ارزشمند و کدام بخش از خواسته‌های آن ارزش آن‌چنانی ندارد! چرا که مشتری نیاز دارد به مشکلات و ارزش‌هایی که در طرح ذهنی خود وجود دارد آگاه باشد تا به راحتی بتواند یک تصمیم صحیح بگیرد. واقعیت‌هایی که مشتریان از آن‌ها آگاه نیستند قطعاً واقعیت‌هایی وجود دارد که مشتریان از آن‌ها آگاه نیستند، چرا که آن‌ها متخصص و افراد فنی نیستند. بنابراین احتمال بسیار زیاد دارد که مشتری ابتدا نمونه‌ای از خواسته‌های خود را برای شما معرفی کند. به عنوان مثال: معرفی یک نمونه وب‌سایت یا نرم‌افزار (اپلیکیشن) که در نظر او بسیار جذاب و قابل قبول است. تمامی این مسائل وجود خواهد داشت، شما باید در نظر داشته باشید که تفاوت یک نمونه با خواستهٔ مشتری را شفاف سازی کنید. اگر قرار است بر اساس سلیقهٔ مشتری با او همکاری کنید بهتر است بدانید شما متخصص نیستید و نتیجهٔ پروژه‌ای که بر روی آن کار خواهید کرد مطابق میل شما در بُعد تخصصی نخواهد بود. نمونه وب‌سایت مثال زده شده توسط مشتری را در مقابل خود مشتری ارزیابی کنید، اگر شما یک حرفه‌ای باشید قطعاً می‌توانید الگو‌های پیاده سازی شده، روش‌های برنامه‌نویسی، سیستم‌ نرم‌افزاری، بستر‌ها، تجربه‌‌کاربری و رابط‌کاربری آن را بررسی و نظر خود را برای مشتری ارائه دهید. در نظر داشته باشید زمانی که مشتری برای شما نمونه مثالی را ارائه می‌کند که شاید تا حدی با ایدهٔ ذهنی آن یکسان است، شما باید در نظر داشته باشید که اصول اساسی تولید محصولی که در نظر دارد را به او توضیح دهید. مشتری باید بداند که رفتار کاربر‌ها، تجربه‌کاربری، برندینگ و اصول چیده‌مان و همهٔ موارد دیگر در عین حال سادگی در کاربرد آن چقدر مهم است. تجربه‌کاربری هرچند برای خود یک تخصص کامل است، اما مشتری نیاز دارد تا شما در مورد این نکته‌ها به او یادآوری کنید. اگر شما فقط یک برنامه‌نویس هستید بهتر است مراجعی را برای مشتری و حتی خودتان در نظر بگیرید تا در بهتر شدن محصول مشارکت کند. مشتری را برای مقایسه و دیدن نمونه‌های واقعی تشویق کنید همهٔ مشتریان شما مانند هم رفتار نمی‌کنند، بعضی از آن‌ها قبل از شما با افراد دیگری صحبت کرده‌اند و بعضی از آن‌ها با شما به عنوان اولین نفر در رابطه با کسب‌و‌کارشان و خواستهٔ خود در ایجاد آن صحبت می‌کنند. بنابراین سعی کنید مشتری را به دیدن رقبا و نمونه‌هایی که مشابه کسب‌و‌کار آن است تشویق کنید تا بتواند آن‌ها را در واقعیت نیز ببیند. پیشنهاد می‌کنم دو نمونهٔ مشابه را در مقابل هم مقایسه کنید و برای مشتری توضیح دهید که چه تفاوتی بین ضعف‌ها و قدرت‌ها وجود دارد. معرفی و توصیف ابزار‌ها و فناوری‌هایی که از آن‌ها برای تولید و توسعه استفاده می‌کنید طبیعتاً همهٔ مشتریان شما با ابزار‌ها، زبان‌های برنامه‌نویسی و دیگر موارد آشنایی ندارند. اما برای جذب اعتماد و افزایش آگاهی مشتری لازم است به توصیف ابزار‌هایی که از آن‌ها استفاده می‌کنید بپردازید. قرار نیست همهٔ موارد را به صورت فنی توضیح دهید، اما تا جایی که ممکن است به نکته مزیت‌ها و مقایسهٔ تکنیک‌ها و ابزار‌هایی که قرار است محصول مشتری را با آن توسعه دهید بپردازید تا اون نیز در جریان ذاتِ اصلی محصول خود قرار بگیرد. صداقت شما و تضمین وفاداری مشتری اگر به دنبال جذب مشتری با وفا و مشارکت طولانی مدت هستید، سعی کنید از همان دقایق ابتدائی نظرات خود را بی‌طرف و با صداقت کامل در قالب مشاوره‌‌ی قانع کننده ارائه کنید. قرار نیست در همان جلسهٔ اول قرارداد اخذ کنید و یا هزینه‌ای بابت کارتان دریافت کنید! اگر احساس می‌کنید مشتری شما به مهارت‌ها و حضور شما ارزش قائل نشده است و به نظرات شما توجهی نمی‌کند خیلی محترمانه سعی کنید وارد این همکاری نشوید. چرا که حرف شنوی از یک متخصص یک ارزش اولیه برای ادامهٔ همکاری است. ناگفته نماند در مقابل ارزش‌هایی که مشتری به شما می‌دهد، مانند: شنیدن مشتاقانهٔ نظرات شما، به معنای آن است که این رابطهٔ کلامی در حل بسیاری از مسائل برای مشتری بسیار مهم بوده و شما از نتیجهٔ وقتی که بابتِ این مشاوره صرف می‌کنید مطمئن شوید. قرارداد، ارزیابی هزینه‌ها و زمان توسعه قبل از اینکه مشتری به شما بگوید شرایط قرادادی چگونه است، شما نمونه قراردادی را با توجه به نتایج ارزیابی شده از نیاز مشتری آماده کنید. بند‌ها و ماده‌های قرارداد را عادلانه مشخص کنید. تعهدات شما باید به گونه‌ای باشد که مشتری شما از کار مطمئن شود. این قرارداد است که مشخص می‌کند شما چقدر به توانایی‌های خودتان مطمئن هستید. متأسفانه بعضی از توسعه‌دهندگان به گونه‌ای تعهدات را یک‌طرفه و به نفع خود تنظیم می‌کنند که گویی مشتری هیچ حقی در پروژه ندارد! حتی بند‌هایی دیده می‌شود که گاهاً توسعه‌دهنده اعلام کرده است منبع‌کد - سورس‌کد برنامه را با هزینهٔ بسیار زیاد و جدا از پروژه به مشتری تحویل خواهد داد! به نظر من این یک بی انصافی به تمام معناست! چرا که مشتری پول می‌دهد تا محصول خریداری کند! منطقی‌ترین پیشنهاد از نظر من این است که بر اساس زمان و زحماتی که در ساخت و توسعهٔ پروژه صرف خواهد شد یک هزینه و زمانِ شفاف برای مشتری ارائه دهید. برای مثال: فاز‌بندی‌های ساخت پروژه در یک جدول استاندارد مانند WBS یا همان «ساختار شکست کار» استفاده کنید. مشاورهٔ رایگان یا پولی ممکن است با خود فکر کنید که من چرا باید دقیقه‌ها و یا ساعت‌ها وقت صرف مشاورهٔ کسانی صرف کنم که مشخص نیست مشتری من هستند یا خیر! برای تشخیص این موضوع که آیا مشاوره‌‌های شما در نهایت منجر به همکاری دو طرفه می‌شود یا خیر، کافی است به چند نکته توجه کنید. اول اینکه مشتری یا نماینده‌ای از مشتری به دفتر کسب‌و‌کار شما آمده است یا برعکس شما به دفتر کاری یا یک دیدار دوستانه رفته‌اید! قطعاً زمانی که شما یک دفتر یا شرکت منظمی دارید طبیعی‌ است که زمان خود را باید ارزشمند نگه‌دارید. بنابراین قبل از ورود به مشاورهٔ اصلی، اشکالی ندارد که بگویید برای ورود به آن هزینه‌ای را دریافت خواهید کرد. به این نکته توجه داشته باشید که، پیش‌مشاوره با مشاورهٔ اصلی بسیار متفاوت است. در پیش‌مشاوره شما اولین دیدار را با مشتری خود خواهید داشت که در آن قرار است صحبت‌های طرف مقابل را شنیده و از آن برای تجزیه تحلیل آن برای پاسخ در یک زمان مناسب نکته‌برداری کنید. در این نوع صحبت که معمولاً در دیدار اول و مقدماتی شکل می‌گیرد بهتر است هیچ صحبتی از هزینه‌هایی که در ذهن دارید به مشتری انتقال ندهید چرا که در این مرحله «واقعاً نیاز نیست» و شما صرفاً باید یک شنوندهٔ خوب باشید. در نهایت بعد از شنیدن صحبت‌های مشتری، لازم است از او بخواهید تا یک فرصت برای تجزیه تحلیل شنیده‌های او بدهید. همانطور که در ابتدای مقاله توضیح دادم، احتمال اینکه مشتری در همان ابتدای صحبت‌های خود درخواست میزانه هزینه و زمان برای انجام پروژه کند بسیار زیاد است. بنابراین اگر قبل از تجزیه تحلیل مسئله زمان و هزینه‌ای برای آن مشخص کنید، دیگر نخواهید توانست در صحبت‌ها و جلسات بعدی هزینه‌ها و زمان‌بندی مشخصی که بعد از تجزیه تحلیل واقعیت به دست آورده‌اید را به مشتری پیشنهاد و او را قانع کنید و هر چیزی که در سر داشته‌اید را از دست خواهید داد. نکتهٔ کلیدی در این مرحله برای حرفه‌ای برخورد کردن، این است که مشتری را متوجه این کنید که قرار است به او مشاوره و آموزش‌های قبل از ورود به مرحلهٔ ساخت و توسعهٔ ایدهٔ ذهنی او را بدهید. در واقع قرار است یک ارزش‌آفرینی از این صحبت‌ها برای مشتری ایجاد کنید تا به دانسته‌های خود اضافه کند «این کار برای مشتری شما ارزشمند و قابل قبول است» در این زمان است که شما می‌توانید وارد مذاکرهٔ جدی و حرفه‌ای شوید که شامل آموزش‌ها و توضیحات کامل برای قانع‌سازی مشتری است که قطعاً دارای هزینه و ارزش به خصوصی خواهد بود. بنابراین یک جلسهٔ دیگر برای مشاورهٔ جدی با مشتری خود هماهنگ کنید تا نکات کلیدی و اساسی را برای هدایت هر چه بهتر او به مسیر درست و موفقیت را ترسیم کنید. چگونه از دیگر برنامه‌نویسان و توسعه‌دهندگان متمایز و به یک برنامه‌نویس واقعی و حرفه‌ای تبدیل شویم؟ به احتمال بسیار زیاد هر یک از برنامه‌نویسان و طراحان در حوزهٔ کسب‌و‌کار‌های اینترنتی که در زمینه‌های طراحی، توسعه و تولید محصولات نرم‌افزاری فعالیت می‌کنند، نظر بر این دارند که چون مهارت کار با زبان‌های برنامه‌نویسی را در اختیار دارند و یا رزومه یا نمونه‌کار‌های خوبی را دارند، پس بهترین هستند! متأسفانه من بارها شاهد غرور نابه‌‌جای بسیاری از برنامه‌نویسان بوده‌ام که به شدت این رفتار را در شأن حرفه‌ای ها نمی‌دانم. توصیه می‌کنم به دانسته‌های خود مغرور نباشید و از آنچه که در اختیار دارید به نحو عالی استفاده کنید تا از شما یک حرفه‌ای واقعی بسازد. شرایطی که یک برنامه‌نویس حرفه‌ای می‌تواند داشته باشد به صورت زیر است: تجربهٔ کافی و پُخته در زمینه‌های تخصصی تحصیلات مرتبط و مطالعات بسیار در حوزهٔ تخصصی و مرتبط با آن آشنا به اصول مشتری مداری برندینگ، معرفی فردی و تخصصی آشنا به اصول تجربه‌کاربری و سیستم روان‌شناسی مناسب با آن رزومهٔ خوب و واقعی نمونه کار‌های واقعی و اصولی عدم وابستگی به ابزار‌های محدود در توسعه مدارک و مجوز‌های لازم در حوزهٔ فعالیتی چهارچوب مشخص و کاتالوگ معرفی خدمات و ارزش‌ها توجه کنید که داشتن مجوز و گواهی‌های فعالیتی در این حوزه بسیار مهم است. اگر شما به عنوان یک متخصص در این رشته فعالیت می‌کنید باید بدانید داشتن مدارک و گواهی‌هایی ملی و بین‌المللی در این حوزه اعتبار خوبی در اختیار شما قرار می‌دهد که مشتری را بیشتر قانع خواهد کرد. پیشنهاد می‌کنم بهتر است خودتان را با یک رزومهٔ خوب و مجوز‌های لازم از سمت «سازمان نظام صنفی رایانه‌ای کشور» و «مرکز فناوری اطلاعات و رسانه‌های دیجیتال» معرفی کنید. اخذ این گواهی‌ها در صورتی که شما واقعاً یک متخصص هستید در قالب شرکتی یا خصوصی، می‌تواند یک اعتبار لازم در قبال دانسته‌های شما و شرکت شما را در اختیار سازمان‌ها و ارگان‌های دولتی، خصوصی و نیمه‌خصوصی بدهد که اولویت انتخاب در زمان مزایده‌ها نیز با کسانی است که اعتبار لازم را دارند. واقعیت آن است، دریافت پروژه‌های بزرگ نه تنها نیاز به دانش و رزومهٔ بسیار خوب دارد، بلکه گواهی‌هایی که ثابت می‌کند شما یک متخصص هستید مهم است. این تنها گزینه‌ای است که شما را با افرادی که غیر متخصص هستند متمایز می‌کند. به‌روز باشید و از رفتار‌های تعصبی پرهیز کنید همهٔ ما این واقعیت را می‌دانیم که در حوزهٔ صنعت علوم کامپیوتری، فناوری با سرعت بسیار چشم‌گیری در حال تغییر و تحولات بسیار زیادی است. این دلیل موجب می‌شود که در صورت عدم به‌روز‌رسانی اطلاعات و دانش تکنیکی شرکت یا شخص برنامه‌نویس، از دیگر رقبا فاصله بگیرد. متأسفانه در کشور ما شرکت‌ها و برنامه‌نویسان بسیاری هستند که به سبک‌ها و اصولی که در نمونه‌های جهانی از آن‌ها به خوبی یاد نمی‌شوند وابستگی نشان می‌دهند و بر بهترین بودن آن تأکید متعصبانه‌ای دارند. شاید این تأکید‌ها در دید اولیه از جانب مشتری قابل درک باشد، اما واقعیت آن است که نباید خود را محدود به ابزار‌ها و فناوری‌هایی کنید که از آیندهٔ آن بی خیر هستید! به عنوان مثال بررسی آینده‌ای از یک فناوری مانند IoT می‌تواند بسیاری از مسائل را برای شما یادآوری کند که چه ابزار و چهارچوبی می‌تواند برای پیشرفت روز افزون با حداقل محدودیت‌ها مناسب است. در بسیاری از جوامع، وب‌سایت‌ها، گروه‌ها وکانال‌های اینترنتی دیده می‌شود که افراد به ابزار و دانشی که فقط به آن محدود و مسلط هستند شدیداً تعصبی برخورد کرده و آن را بهترین انتخاب می‌دانند. لازم است یادآوری کنیم تعصب بر دانسته‌ها تنها تأیید بر کم دانستن دارد و نه بیشتر! اگر منطقی باشیم یادگیری استاندارد‌های تضمین شده و پایدار، فناوری‌ها، ابزار‌ها و زبان‌های برنامه‌نویسی قدرتمند و آینده‌دار همیشه در پایداری و توسعهٔ سریع کسب‌و‌کار‌ها موثر هستند. چرا که فناوری در زمان تغییر محیط را نیز تغییر می‌دهد. بنابراین توصیه من در این بخش آن است که در یادگیری ابزار‌ها و زبان‌های برنامه‌نویسی، تکنیک‌ها و آشنایی با استاندارد‌های روز جهانی مصمم باشید و به هیچ عنوان به ابزار‌های محدود به دانسته‌های خود تأکید شدید نکنید مگر با دلیل منطقی و علمی که تضمین کند انتخاب شما دقیقاً هم سو با پیشرفت است. محصولات با کیفیت در سطح جهانی تولید کنید با توجه به توضیحاتی که داده شد، شرکت‌ها و توسعه‌دهندگانی که در حوزهٔ تولید نرم‌افزار فعالیت می‌کنند، معمولاً محصولاتی را توسعه می‌دهند که در مدیریت کسب‌و‌کار‌های خود و دیگران موثر است. محصولات نرم‌افزاری هرچقدر هم قدرتمند باشند و هرچقدر شما کد‌های منظم و قدرتمندی در تولید آن‌ها نوشته باشید، کد‌های شما از نظر مشتری یا کاربرانی که از آن‌ها استفاده می‌کنند مخفی است. لازم به ذکر است که، یکی از رایج‌ترین اشتباهاتی که نا خواسته در اکثر محصولات ایرانی دیده می‌شود عدم به کار گیری مباحث تجربه‌کاربری و رابط‌کاربری و استاندارد‌های توسعهٔ مناسب است. حقیقت این است که نمونه محصولات خارجیِ موفق فاقد این ایرادات هستند و در این صورت است که در نظر کاربر بسیار محبوب می‌شوند. هرچند بحث تجاری و تبلیغات رسانه‌ای و جهانی در محبوبیت آن‌ها بسیار مهم است، اما در نهایت این کاربر است که تصمیم می‌گیرد آن را بپذیرد یا خیر. منظور از کاربری صرفاً در زیبایی محیط نرم‌افزاری نیست، بلکه در دسترس بودن امکانات و ویژگی‌هایی که می‌تواند در برقراری ارتباط و وفاداری مشتری شما مفید باشد هم اشاره دارد. بنابراین، اگر شما دید کاربری نداشته باشید و صرفاً با توجه به سلیقه‌های خودتان محصولی را تولید کنید که فاقد اصول کاربری باشد در این صورت است که محصول شما تنها برای خودتان مهم و با ارزش خواهد بود. نکته: اصول استاندارد نسخه‌نگاری نرم‌افزار (محصول) را رعایت کنید و سعی کنید مشتری را در جریان تغییر تحولات و ویژگی‌های اعمال شده در محصول قرار دهید. برای این کار می‌توانید از استاندارد‌هایی مانند نسخه‌نگاری معنایی استفاده کنید. خدمات پشتیبانی، تضمین پاسخگو بودن با توجه به نکاتی که اشاره شد، پشتیبانی و پاسخگو بودن در مراحل بعد از عقد قرارداد، طراحی و تولید محصول، یکی از مهمترین مواردی که در طولانی مدت وفاداری کاربران (مشتریان) شما را تضمین می‌کند، پاسخگو بودن و پشتیبانی است. حتی این موضوع می‌تواند به صورت یک قرارداد جداگانه با شرایط مخصوص خودش برای مشتری بیان شود تا در جریان شرایط و نحوهٔ پشتیبانی قرار بگیرد. علاوه بر قواعد و قوانین مشتری مداری و توسعهٔ کسب‌و‌کار، در چرخهٔ تولید نرم‌افزار نیز مهم است که بازخورد‌های کاربری دریافت و مشکلات احتمالی محصول (نرم‌افزار) را بررسی و حل نمایید. این خود نوعی پشتیبانی و پاسخگویی و ارزش قائل شدن به مشتریان است که در عمل حتی به روش‌های بسیار هوشمندانه می‌توان آن را انجام داد. مشتریان شما در هر زمان که با مشکلی مواجه شوند حق دارند مشکلی که با آن مواجه شده‌اند را به توسعه‌دهندهٔ محصول انتقال دهند. توسعه‌دهنده با بررسی بازخورد ارائه شده موظف است مشکل مربوطه را بررسی و آن را حل کند. این نکته در جمله‌های مشابه می‌تواند در بخشی از بند‌های قراردادِ بین مشتری و توسعه‌دهنده یادآوری شود. شاید با خود فکر کنید که با چه روش‌هایی می‌توان ارتباط بین مشتری و توسعه‌دهنده را برای حل مشکلی در محصول بررسی و مدیریت کرد، حتی بدون آنکه نیاز باشد به صورت حضوری وقت صرف آن کرد. در این باره پیشنهاد می‌کنم به توضیحات قبلی من در رابطه با ساختن محصول با کیفیت عمیقاً توجه کنید. منظور از توسعهٔ محصولات با کیفیت آن است که مشتری باید بتواند حتی در بازهٔ ۲۴ ساعته نظر خود را نسبت به مشکل، انتقاد یا پیشنهادی در رابطه با محصول ارائه کند تا در فرصت مناسب توسعه‌دهنده آن را بررسی کند. معمولاً این فرآیند به صورت سنتی با تلفن و مراجعهٔ حضوری صورت می‌گیرد، اما توصیهٔ من برای حفظ زمان و کارآیی بهتر این است که نرم‌افزار (محصول) خود را مجهز به خدمات پشتیبانی آنلاین در قالب سیستم هوشمند مجهز کنید. علاوه بر آن، استاندارد‌های سیاههٔ تغییرات (change log) و مشکلات گزارش شده را در محیط نرم‌افزار شفاف سازی کنید تا مشتری هم متوجه اعمال نظرات و انجام آن شود.
  8. کامبیز اسدزاده

    سمت سی‌پلاس‌پلاس کدی تدارک ببینید که وضعیت لایه‌ی زبانی روی صفحه‌کلید رو بررسی و به سمت کیو‌ام‌ال پاس بده. در آخرین تغییراتِ کیوت، از کدی مشابه زیر می‌تونید استفاده و روش مورد نظر خودتون رو پیاده کنید: QGuiApplication app(argc, argv); QLocale locale; app.inputMethod()->locale().setDefault(QLocale::English); qDebug() << app.inputMethod()->locale().language(); مقداری که چاپ می‌شه رو در یک روش بهتر در قالب کلاس و تابعی مشتق شده از QObject به سمت QML پاس بدین.
  9. کامبیز اسدزاده

    درود، دو تا سیستم فونت تعریف کنید، یکیش لاتین برای انگلیسی و دیگری فونت مورد نظر برای فارسی. برای مثال، همچین چیزی رو در نظر داشته باشید: FontLoader { id: fontEnglish source: "english-font.ttf" } FontLoader { id: fontPersian source: "persian-font.ttf" } در نهایت در یک دستور شرطی با توجه به واکنش بر اساس مشخصه‌ی فکوس و یا هر چیزی که نیاز هست فونت‌ها رو اعمال کنید. برای مثال به صورت زیر: TextField { //Todo... property bool isLatin : false font.family: isLatin ? fontEnglish.name : fontPersian.name onPlaceholderTextChanged: { //ToDo... } }
  10. کامبیز اسدزاده

    در نسخه‌ی ۵.۱۲ نمی‌تونید پشتیبانی از همه‌ی معماری‌ها رو در یک فایل ارائه کنید. برای پشتیبانی کامل اپلیکیشن شما از این قابلیت بهتره اون رو در قالب aab منتشرش کنید. در کیوت ۵.۱۳ این امکان هم وجود داره، در بخش تنظیمات زبانه‌ی Advanced Action گزینه‌ی Build .aab (Android App Bounlde) رو تیک بزنید.
  11. روشی که توضیح داده شده بود به همین مدل اشاره داشت. باید توجه داشته باشید که فایل‌هایی با پسوند .a برای کتابخانه‌های ایستا و .so برای نوع داینامیک یا همون Shared هستند. البته باید توجه کنید حتماً روی کیت اندروید و لینوکس کتابخانه‌های مربوطه را کامپایل و به پروژه اضافه کنید.
  12. کامبیز اسدزاده

    از تکنیک جستجو در گوگل استفاده کنید. برای مثال عنوان برنامه + Github نتایجی که به دست میاد رو بررسی کنید. یا اینکه عنوان برنامه‌ی مورد نظرتون رو در داخل گیت‌هاب جستجو کنید.
  13. کامبیز اسدزاده

    آیندهٔ توسعهٔ وب تحت فناوری WebAssembly

    با توجه به محبوبیت صنعت وِب، سال‌هاست زبان‌های برنامه‌نویسی در این زمینه پیشرفت‌ها و کاربرد‌های چشم‌گیری را داشته‌اند، از جمله جاوا‌اسکریپت (JS) به عنوان یک زبان قابل اجرا در داخل مرورگر شناخته می‌شود. هرچند بسیار محبوب و کاربردی است، اما این زبان قطعاً مشکلات خودش را دارد که برخی از آن‌ها عدم انعطاف‌پذیر بودن، سرعت پایین اجرا و همچنین انواع غیر ایمن آن است که این باعث می‌شود برای محاسبات و کارهای پیچیده جوابگو نباشد. هرچند گزینه‌هایی مانند CoffeeScript و TypeScript وجود دارند و نسبتاً ایرادات خام جاوا‌اسکریپتی را پوشش می‌دهند، اما در نهایت کد‌های نوشته شده به جاوا‌اسکریپت تبدیل می‌شود. در این میان می‌توان گفت وب‌اسمبلی (WebAssembly) برای حل و مرتب سازی مشکلات جاوا‌اسکریپت معرفی شده است و شدیداً در حال اثبات آن است که یک انقلاب در صنعت وِب را رقم می‌زند. با این تفاسیر، آیا وب‌اسمبلی زبان برنامه‌نویسی است؟ این فناوری به خودی خود، یک زبان برنامه‌نویسی نیست، در واقع برنامه‌نویسان برنامه‌های خود را توسط زبان‌های سطح‌بالا مانند C یا ++C و حتی Rust می‌نویسند و آن را کامپایل و در قالب باینری با پسوند فایل .wasm وارد می‌کنند. توجه داشته باشید که وب‌اسمبلی جایگزینی برای جاوا‌اسکریپت نیست، درواقع قرار است در کنار جاوا‌اسکریپت اجرا شود. به عنوان مثال شما می‌توانید فقط یک کد محاسباتی بالا را در WebAssembly بسازید و آن را در کنار سایر کد‌های جاوا‌اسکریپت با وزن سبک‌تر استفاده کنید. همچنین شما برای بارگذاری ماژول wasm در مرورگر به جاوا‌اسکریپت نیاز دارید. فناوری وب‌اسمبلی (WebAssembly) و یا WA چیست؟ وب‌اسمبلی یا وَسم (Wasm، اغلب به طور مخفف) استانداردی باز است که یک قالب جدید دستورالعمل‌های باینری را معرفی می‌کند. این فناوری نوید این را می‌دهد که برنامه‌ها با کارآیی (پرفرمنس) بومیِ خود در بستر وِب اجرا شوند. به عبارت ساده‌تر می‌توان گفت، این فناوری امکان این را می‌دهد که کد‌های نوشته شده با زبان‌های سطح بالا‌تر مانند C و ++C یا Rust به ماژول Wasm کامپایل شوند که مستقیماً در مرورگر‌های مدرن قابل اجرا هستند. معماری وب‌اسمبلی وب‌اسمبلی به گونه‌ای طراحی شده است که بر روی دستگاه‌های مجازی مبتنی بر پشته (stack-based) اجرا شود. بر خلاف ماشین‌های رجیستری که عملوند‌های آن‌ها بر روی پردازندهٔ مرکزی قرار دارند و محاسبات در آن بخش اتفاق می‌افتد، در یک ماشین مبتنی بر پشته، بیشتر دستورالعمل‌ها به جای اینکه بر روی رجیستر اعمال شوند، بر روی پشته می‌نشینند. برای افزودن دو عدد بر روی ماشین مبتنی بر پشته، شماره‌های مربوطه را در پشته ارسال می‌کنید. سپس دستور ADD را فشار می‌دهید. سپس دو عملگر و دستورالعمل از بالای صفحه ظاهر می‌شود و نتیجهٔ اضافی در جای خود قرار می‌گیرد. برخی از این نوع ماشین‌ها عبارتند از .Net، JVM Runtime و غیره. وب‌اسمبلی به معنای سنتی، پشته‌ای ندارد. درواقع هیچ مفهومی از اپراتور‌های جدید ندارد. حتی خبری از GC در آن وجود ندارد. در عوض وب‌اسمبلی دارای یک حافظهٔ خطی است، یعنی حافظه به عنوان طیف پیوسته از بایت‌های بدون نوع نمایش داده می‌شود. در صورت نیاز به فضای بیشتر، ماژول وب‌اسمبلیِ شما می‌تواند بلوک حافظهٔ خطی را افزایش دهد. نکته: WebAssemble فقط چهار نوع داده دارد: i32، i64، f32، f64 برای اعداد صحیح 32 و 64 بیتی و انواع شماره‌های شناور آیندهٔ توسعهٔ وب چگونه می‌شود؟ اگرچه ممکن است وب‌اسمبلی، جاوا اسکریپت را از بین نبرد، اما قطعاً قصد این را دارد که چهرهٔ front-end توسعهٔ وب را تغییر دهد. البته راه بسیاری در پیش است تا همهٔ تغییرات را تجربه کنیم. اما به اندازهٔ کافی می‌توان آیندهٔ وب را پیش‌بینی کنیم: تنوع از نظر زبانی خیلی سریع موازی تنوع زبانی این فناوری به طور چشم‌گیری تنوع در استفاده از زبان‌های برنامه‌نویسی را برای ساخت برنامه‌های تحت وب افزایش می‌دهد. در حال حاضر لیست زیر زبان‌هایی است که وب‌اسمبلی از آن‌ها پشتیبانی می‌کند: C/C++ Rust C#/.Net Java Python Elixir Go سرعت و کارآیی بسیار بالا فناوری WASM باعث می‌شود عملکرد برنامه‌ها شگفت‌انگیز شود. در این زمینه مستنداتی وجود دارد که فایرفاکس در یک سری از نمونه‌های اولیه آن را ثابت می‌کند. همچنین طبق تجزیه و تحلیل برنامه‌های کاربردی توسط فیگما منتشر شده است که نشان می‌دهد پیاده‌سازی‌های صورت گرفت در قالب asm.js که خود از سرعت بسیاربالای به خاطر پشتیبانی از سی++ دارد، با این وجود با فعال بودن ماژول WebAssembly چیزی حدود ۳ برابر بهبود زمان اجرا گرفته است. در این موارد ثابت شده است که با استفاده از ++C و کامپایلر کلنگ (LLVM) سرعت اجرای برنامه‌ها با فعال بودن وب‌اسمبلی بسیار چشم‌گیر است. موازی سازی طبیعتاً این مورد بسیار قابل بررسی و توجه است، چرا که این مبحث به طور کامل در وِب پیاده‌سازی نشده است. از آنجایی که تغییر به سمت پردازنده‌های چند هسته‌ای حدوداً از سال ۲۰۰۵ آغاز شد، این امر به طور فزاینده‌ای اتفاق می‌افتد که برای دستیابی به عملکرد بیشتر، نرم‌افزار‌ها به موازی سازی نیاز دارند. با توجه به اینکه جاوا‌اسکریپت از سیستم موازی پشتیبانی نمی‌کند، تصور کنید که با فعال‌سازی WASM امکان استفاده از تمامی هسته‌های پردازنده فراهم شود. من به عنوان نویسندهٔ این مقاله، تصور شما را از این فناوری نمی‌دانم. اما قطعاً با این تفاسیر این فناوری به عنوان یک انقلاب بزرگ در حوزهٔ وِب محسوب می‌شود. با توجه به ساختار برنامه‌های نوشته شده توسط زبان‌های قدرتمندی چون ++C می‌توان تصور کرد که برنامه‌های بسیار بهینه و قدرتمندی را در حوزهٔ اجرایی مرورگر‌ها پشتیبانی کند. در حال حاضر ممکن استد شما فکر کنید که چرا کسی باید زبان ساده‌ای مثل جاوا‌اسکریپت را خدشه‌دار کند و یا به سمت زبان‌های پیچیده‌ای مانند Rust، C و ++C برود. اکنون وب‌اسمبلی کاملاً جدید است و جامعهٔ کافی در اطراف خود ندارد. اما باید توجه داشت وقتی از طریق این فناوری می‌توان به ویدئو‌ها، تصاویر و کتابخانه‌های رمزنگاری، یا استفاده از موتور‌های گرافیکی و فیزیکی که از OpenGL استفاده می‌کنند، و یا حتی کتابخانه‌‌ها و فریم‌ورک‌های قدرتمندی مانند Qt و غیره را می‌توان در حوزهٔ وب مورد استفاده قرار داد. بنابراین فناوری وب‌اسمبلی می‌تواند مسیری را برای رشد صنایع مختلف به خصوص شرکت‌های بازی‌سازی و غیره باز کند. افزایش کارآیی (پرفرمنس) بسیار شدید که توسط وب‌اسمبلی فراهم می‌شود، همانند اجرای برنامه‌های دسکتاپی است که می‌توان آن را بر روی وب نیز مشاهده کرد. با این روال ممکن است وب‌اسمبلی در سال‌های آینده، با نرم‌افزار‌های رومیزیِ بومی برابری کند.
  14. کامبیز اسدزاده

    شما باید نسخه‌ی اندروید رو دریافت کنید که مختصِ بستر اندروید ساخته شده است. برای اضافه کردن به پروژه‌ هم به همین روشی که قبلاً توضیح داده شده ازش استفاده کنید. اگر مشکلی بود خطا و جزئیات رو بنویسید تا بررسی شود.
  15. کامبیز اسدزاده

    درود، از Github استفاده کنید.
  16. کامبیز اسدزاده

    در کتابخانه‌ی SFML کلاس Http این امکان را فراهم می‌کند تا به راحتی بتوانید تحت روش‌های Post، Get و Head درخواست‌های مورد نظر را دریافت و ارسال کنید. توجه داشته باشید این کتابخانه تنها از مباحث ابتدائی پروتکل Http پشتیبانی می‌کند. برای دسترسی و استفاده از این ویژگی کافی است سرآیند زیر را وارد کنید: #include <SFML/Network.hpp> سپس با فراخوانی فضای نام به صورت زیر، از کلاس مربوطه یک نمونه خواهیم ساخت: sf::Http http; به عنوان مثال کد زیر جهت آماده سازی برای ارسال به سمت سرور کافی است: #include <SFML/Network.hpp> sf::Http http; http.setHost("http://www.iostream.ir/"); با توجه به نیاز‌های مربوط به این مبحث، ارسال مقادیر به یک صفحه و آدرس اینترنتی توسط Request و Response صورت می‌گیرد که جهت دسترسی به این ویژگی‌ها کافی است از کلاس‌ مربوطه به صورت زیر نمونه گرفته شود. sf::Http::Request request; request.setMethod(sf::Http::Request::Post); request.setUri("/page.html"); request.setHttpVersion(1, 1); // HTTP 1.1 request.setField("From", "me"); request.setField("Content-Type", "application/x-www-form-urlencoded"); request.setBody("para1=value1&param2=value2"); sf::Http::Response response = http.sendRequest(request); در کد فوق، روش درخواست از نوع Post و یا Get مشخص می‌شود که از متد setMethod جهت اعمال آن استفاده شده است. در ادامه مشخصه‌ی setUri صفحه و یا‌آدرسی را که قرار است اطلاعات به آن ارسال یا دریافت شود را مشخص می‌کند. نسخه‌ی پروتکل http با مشخصه‌ی setHttpVersion با مقادیر صحیح مقدار دهی می‌شود که در این مثال مقدار ۱ به عنوان پشتیبانی از پروتکل نسخه‌ی Http 1.1 تعیین شده است. با توجه به ماهیت روش Post مقادیری که برای ارسال نیاز است را باید ارسال کنید، برخی از اطلاعات ارسالی مانند Content-Type و غیره توسط مشخصه‌ی setField مشخص می‌شود و همچنین مشخصه‌ی setBody پارامتر‌ها (ورودی‌هایی) که از طرف کاربر ارسال می‌شود را فراهم می‌کند. در نهایت کلاس Response جهت دریافت و مدیریت داده‌های ارسالی از سمت سرور را مدیریت می‌کند که برای دسترسی و چاپ اطلاعات تحت آن به صورت زیر خواهد بود: sf::Http::Response response = http.sendRequest(request); std::cout << "status: " << response.getStatus() << std::endl; std::cout << "HTTP version: " << response.getMajorHttpVersion() << "." << response.getMinorHttpVersion() << std::endl; std::cout << "Content-Type header:" << response.getField("Content-Type") << std::endl; std::cout << "body: " << response.getBody() << std::endl; مثال فوق وضعیت، نسخه‌ی مرتبط با پروتکل مربوطه، مقدار Content-Type و همچنین اطلاعات ارسال شده در مشخصه‌ی body را چاپ خواهد کرد. در ادامه مثال مشخصی را برای ارسال یک نظر را آورده‌ایم که به صورت زیر خواهد بود: #include <SFML/Network.hpp> #include <sstream> void sendComment(const std::string &message, const std::string &username) { // Prepare the request sf::Http::Request request("/comment.php", sf::Http::Request::Post); // Encode the parameters in the request body std::ostringstream stream; stream << "username=" << username << "&message=" << score; request.setBody(stream.str()); // Send the request sf::Http http("http://www.iostream.ir/"); sf::Http::Response response = http.sendRequest(request); // Check the status if (response.getStatus() == sf::Http::Response::Ok) { // Check the contents of the response std::cout << response.getBody() << std::endl; } else { std::cout << "Request failed" << std::endl; } } توجه داشته باشید که جهت بررسی وضعیت ارسالی از نمونه‌ی response متد getStatus را می‌توان با شمارنده‌های موجود در کلاس Response مورد ارزیابی قرار داد. در نهایت در سمت سرور کد زیر می‌تواند مقادیر ارسال شده را دریافت و پاسخ دهد: <?php $username = $_POST['username']; $message = $_POST['message']; if (write_to_database($username, $message)) { echo "Your comment has been added!"; } else { echo "failed to write your message to database..."; } ?> نکته: مثال‌های فوق صرفاً برای آشنایی با نحوه‌ی استفاده از ویژگی مربوطه در این کتابخانه است، بنابراین بسیار ساده و فاقد کد‌های امنیتی و سفارشی است.
  17. سلام و درود، مدتی است از سرویس‌های کاوه‌نگار جهت استفاده در پروژه‌‌های خودم استفاده می‌کنم و مطمئنم یکی از بهترین سرویس‌دهنده‌های ایرانی در زمینهٔ پیام کوتاه است. متأسفانه همانطور که می‌دانید بسیاری از سرویس‌دهنده‌ها در ایران به خاطر عدم شناخت دقیق از اهمیت و کاربرد سی++ هیچ حرکتی در توسعهٔ سرویس‌های خود در رابطه با سی++ را نمی‌کنند. بنابراین، جدیداً تصمیم گرفتم کیت‌های توسعه در قالب رابط‌های برنامه‌نویسی مورد نیاز رو برای این چنین شرکت و سرویس‌ها آن ارائه کنم. معرفی سرویس پیام کوتاه کاوه‌نگار کاوه نگار با ارائه وب‌سرویس پیامک و تماس صوتی پیشرفته برای توسعه دهندگان ،امکان ارسال و دریافت پیامک و برقراری تماس اینترنتی را در اغلب سرویس های نرم افزاری مهیا می کند. اهمیت وجود این سرویس در زبان‌هایی مانند C و ++C همانطور که می‌دانید با توجه به اهمیت این زبان‌ها و به خصوص پشتیبانی از کتابخانه‌های بسیار مدرن در توسعهٔ اپلیکیشن‌ها و وب‌ها کاربرد بسیاری دارند که شاید در کشور ما آن‌چنان با آن‌ها آشنا نیستیم. بنابراین وجود سرویس‌های ارسال پیامک در قالب زبان‌ سی‌پلاس‌پلاس می‌تواند کمک بسیار بزرگی به توسعه‌دهندگان و علاقه‌مندان آن در حوزه‌های توسعهٔ نرم‌افزار و انواع برنامه‌های موبایل و وب کمک کند. ساختار اولیه خروجی سرویس کاوه‌نگار به صورت زیر است: { "return": { "status":404, "message":"متد تعریف نشده است" }, "entries": { null } } در صورتی که مقادیر ارسالی صحیح و مطابق با اطلاعات کاربری موجود در کاوه‌نگار باشد نتیجهٔ برگشتی آن به صورت زیر خواهد بود: { "return": { "status": 200, "message": "تایید شد" }, "entries": [ { "messageid": 8792343, "message": "خدمات پیام کوتاه کاوه نگار", "status": 1, "statustext": "در صف ارسال", "sender": "10004346", "receptor": "0914XXXXXXX", "date": 1356619709, "cost": 120 } ] } نمونهٔ اولیه که توسعه داده شده، با مفهوم اولیه جهت ارسال پیام کوتاه بر اساس کلید و شماره‌های ارسالی آماده شده که کد نمونهٔ آن به صورت زیر خواهد بود. #include <iostream> #include <Kavenegar> int main() { //! Your Api Key std::string apiKey {"Your Api-Key"}; //! Kavenegar Default Sender Number std::string senderLine {"10004346"}; Kavenegar::KavenegarApi api(MethodType ,"10004346",apiKey); //ToDo.. try catch exception handling. api.send("09140000000","Hi!"); std::cout << "Result : " << api.getResult(); //JSon Output return 0; } نکته: نمونهٔ ساخته شده کامل و با تمام جزئیات موجود در کاوه‌نگار تکمیل و توسعه داده خواهد شد. لینک مربوط به کیت توسعه در گیت‌هاب. جهت استفاده از این نمونه توجه داشته باشید که جهت اجرای وب‌سرویس آن نیاز به نصب Curl و RapidJson خواهید داشت.
  18. با سلام و درود، همانطور که می‌دانید ویژگی‌های اخیر در استاندارد‌های ۱۷ و ۲۰ بسیار عظیم و کاربردی هستند. هدف ما در مرجع آی‌او‌استریم این است که با توجه به به‌روز‌رسانی‌های زبان سی‌پلاس‌پلاس مهمترین مواردی که نیاز است معرفی کنیم. بنابراین در این بخش به یکی از کاربردی‌ترین موارد مرتبط در استاندارد ۱۷ با عنوان صفت‌های ویژه اشاره می‌شود که در ادامه به تعریف هر یک از آن‌ها می‌پردازیم. با توجه به استاندارد‌های ۱۱ و ۱۴ که در آن صفت‌هایی همچون [[deprecated]] و [[noreturn]] معرفی شده‌اند که وظیفهٔ آن به ترتیب نمایش وضعیت منسوخ شدن یک عملکرد و یا وضعیت بازگشتی یک تابع از نوع void است. چنین صفاتی می‌توانند در زمان اعلان و تعریف متغیر‌ها و یا توابع مورد استفاده قرار گیرند. به عنوان مثال اگر کدی به صورت زیر داشته باشیم: [[deprecated]] void print(const std::string &message) { std::cout << message << std::endl; } در صورتی که تابع print در بخشی از برنامه مورد استفاده قرار بگیرد، پیغامی از سمت کامپایلر از نوع اخطار (warning) ساطع می‌شود، مبنی بر آن که تابع مربوطه به عنوان منسوخ شده یاد شده است. warning: 'print' is deprecated این ویژگی می‌تواند در ساخت و توسعهٔ کتابخانه‌ها، موتور‌ها، چهارچوب (فریم‌ورک‌) و برنامه‌هایی که قرار است دیگر برنامه‌نویسان از آن‌ها استفاده کنند بسیار می‌تواند کاربردی باشد؛ چرا که با اعمال چنین خاصیت‌هایی در کد‌های شما برای توسعه‌دهندگان یادآوری خواهد شد که کد مربوطه در نسخهٔ جدید یا نسخه‌های بعدی امکان حذف و یا تغییر را خواهد داشت. #include <iostream> #include <string> [[deprecated]] void print(const std::string &message) { std::cout << message << std::endl; } int main() { print("Hello, World!"); return 0; } در مثال بالا اخطار پیش‌فرض از سمت کامپایلر ساطع می‌شود، اما در بعضی از مواقع لازم است پیغام سفارشی جهت راهنمایی بیشتر کاربر اعمال شود که در این صورت صفت می‌تواند پیغام از نوع رشته را دریافت و در هنگام ساطع شدن، آن را نمایش دهد. برای این کار کافی است متن مورد نظر را به صورت زیر در صفت خود تعیین کنیم. [[deprecated("Use printView with print instead, this function will be removed in the next release")]] برای مثال یک تابع جایگزین و بهینه شده را به صورت زیر در نظر بگیرید، کامپالر اخطار مروبطه و سفارشی شده را نسبت به آن ساطع خواهد کرد. #include <iostream> #include <string> [[deprecated]] void print(const std::string &message) { std::cout << message << std::endl; } void printView(std::string_view message) { std::cout << message << std::endl; } int main() { printView("Hello, World!"); return 0; } همچنین در رابطه با صفت [[noreturn]] که در استاندارد ۱۱ معرفی شده است، باید در نظر داشت این صفت جهت بهینه‌سازی کامپایلر در رابطه با تولید هشدار‌های بهتر و همچنین اعلام اینکه تابع مربوطه قابل دسترسی نیست مورد استفاده قرار می‌گیرد. مثال: #include <iostream> [[noreturn]] void myFunction() { std::cout << "Hello, World!" << std::endl; throw "error"; } void print() { std::cout << "Print Now!"; } int main() { myFunction(); print(); return 0; } در کد فوق، در زمان هم‌گردانی (کامپایل) پیغام‌ زیر ساطع می‌شود: warning: code will never be executed بنابراین در زمان اجرا تابع print(); اجرا نخواهد شد، زیرا به عنوان یک کد غیر قابل دسترس بعد از myFunction توسط کامپایلر یاد می‌شود. چرا که این امر اجازه می‌دهد تا کامپایلر بهینه‌سازی‌های مختلفی را انجام دهد - نیازی به ذخیره‌سازی‌ و بازیابی هرگونه حالت‌های ناپایدار در اطراف صدا زننده (Caller) نیست. بنابراین می‌تواند کد‌های غیر قابل دسترس را از بین ببرد. با توجه به نیاز‌های این چنینی، در استاندارد ۱۷ صفت‌های جدید‌تر و کاربردی‌تری نیز ارائه شده است که به معرفی هر یک از آن‌ها در بخش اول از این مقاله می‌پردازیم. صفت‌های معرفی شده در استاندارد 1z یا همان ۱۷ به صورت زیر هستند: [[fallthrough]] [[maybe_unused]] [[nodiscard]] معرفی صفت [[fallthrough]] به طور معمول در برنامه‌نویسی، هر وقت که مرحلهٔ مربوط به case در دستور switch به انتهای خود می‌رسد، کد مربوطِ به دستورِ case بعدی اجرا خواهد شد. طبیعتاً عبارت break می‌تواند از این امر جلوگیری کند. اما از آن‌جایی که این رفتار را به اصطلاح fall-through می‌شناسیم، ممکن است در صورت عدم معرفی اشکالاتی را فراهم کند، در این حالت چندین کامپایلر و ابزار‌های آنالیز کننده خطای مرتبط به آن را هشدار می‌دهند تا کاربر در جریان قرار بگیرد. با توجه به این موضوع که ممکن است بعضاً این مورد چشم‌ پوشی شود، در سی‌پلاس‌پلاس ۱۷ به بعد یک صفت استاندارد معرفی شد تا توسعه‌دهنده بتواند با قرار دادن آن در مکان سقوط (fall-through) به کامپایلر اعلام کند که هشداری در آن بخش لازم نیست. کامپایلر‌ها می‌توانند هشدارهای مطمئنی را در زمانی که یک عبارت case بدون اجرای دستور break به انتهای خود می‌رسند و یا سقوط (fall-through) می‌کند، حداقل با یک جملهٔ مربوطِ به آن را ساطع کند. برای مثال به کد زیر توجه کنید: #include <iostream> int main() { int number { 2017 }; int standard = {0}; switch(number) { case 2011: case 2014: case 2017: std::cout << "Using modern C++" << std::endl; case 1998: case 2003: standard = number; } return 0; } در کد فوق، در زمان اجرای دستور case سوم با مقدار ۲۰۱۷، کامپایلر هشداری به صورت زیر را اعمال خواهد کرد. warning: unannotated fall-through between switch labels در این حالت برای از بین بردن (چشم‌پوشی کردن) از این خطا در صورتی که نیاز نباشد موارد دیگر مورد بررسی قرار بگیرد قرار دادن دستور break بعد از آن می‌تواند منطقی باشد. اما با توجه به انتظاری که می‌رود تا دستورات بدون توقف بین آن‌ها اجرا شود، قراردادن دستور [[fallthrough]]; بعد از آن می‌تواند راه حل بسیار مناسبی باشد. #include <iostream> int main() { int number { 2017 }; int standard = {0}; switch(number) { case 2011: case 2014: case 2017: std::cout << "Using modern C++" << std::endl; [[fallthrough]]; // > No warning case 1998: case 2003: standard = number; } return 0; } در این حالت، کامپایلر بدون ساطع کردن خطا آن را هم‌گردانی خواهد کرد. معرفی صفت [[maybe_unused]] صفت [[maybe_unused]] برای نشان دادن کد ایجاد شده‌ای است که ممکن است از منطق قطعی استفاده نکند. این مورد ممکن است اغلب در لینک شدن با پیش‌پردازنده‌ها مورد استفاده قرار بگیرد یا نگیرد. از آن‌جایی که کامپایلر (هم‌گردان‌ها) می‌توانند نسبت به متغیر‌های بلا استفاده هشدار ساطع کنند، این صفت روش بسیار خوبی برای سرکوب آن‌ها خواهد بود. استفاده از این ویژگی می‌تواند در بخش‌های مهمی مفید باشد، فرض کنید کتابخانه‌ای نوشته‌ایم که قرار است به صورت چند-سکویی دارای ویژگی‌های یکسان در بستر‌های مختلف باشد. برای مثال ساخت یک فایل در مسیر مشخصی از سیستم‌عامل مورد نظر جهت اعمال تنظیمات نرم‌افزار. namespace FileSystem::Configuration { [[maybe_unused]] std::string createWindowsConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createMacOSConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createLinuxConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createiOSConfigFilePath(const std::string &relativePath); [[maybe_unused]] std::string createAndroidConfigFilePath(const std::string &relativePath); } به کد بالا توجه کنید، در صورتی که شما در محیط کد‌نویسی در حال استفاده از یک دستور مورد نظر از بین دستورات بالا هستید، طبیعتاً کامپایلر به بقیهٔ دستوراتی که از آن‌ها استفاده نمی‌کنید پیغامی مبنی بر آن‌ که دستور مربوطه بلا‌استفاده مانده است را ساطع می‌کند. جهت جلو‌گیری از این هشدار‌ها کافی است صفت [[maybe_unused]] را قبل از آن‌ها اعمال کنید. معرفی صفت [[nodiscard]] در صورتی که از [[nodiscard]] استفاده شود، کامپایلر می‌تواند درک کند توابعی که مقدار بازگشتی دارند نمی‌توانند مقدار بازگشت داده شدهٔ آن‌ها را دور انداخت و یا از آن‌ها در زمان صدا زدن صرف نظر کرد. بنابراین با تعریف این صفت در توابع از نوع بازگشتی می‌توان پیغامی به صورت زیر را ساطع کند. مثال: #include <iostream> [[nodiscard]] int myFunction() { return 17; } int main() { myFunction(); return 0; } در مثال فوق تابع myFunction در زمان فراخوانی که مقدار بازگشتی آن بی نتیجه مانده است از سمت کامپایلر هشدار مورد نظر را دریافت خواهد کرد. این پیغام در صورتی که مقدار بازگشتی تابع به متغیری از هم نوعِ خودش ارسال شود، ساطع نخواهد شد. #include <iostream> [[nodiscard]] int myFunction() { return 17; } int main() { int func; func = myFunction(); return 0; }
  19. سلام، منظور از دیوانگی این هست که اکثراً در دنیای وِب با وجود زبان‌هایی مثل php و غیره اینطور در نظر داشته باشند که خب مگه می‌شه با سی++ چنین برنامه‌هایی رو هم طراحی کرد؟ خب این برمی‌گرده به اطلاعات کمی که داریم! برای مثال ما از ابتدای شروع یادگیری سی++ اینطور فکر می‌کنیم که سی++ فقط یک زبان دانشگاهی برای پاس کردن چهارتا نمره‌ی درسی هست! برای اینکه حقایق پنهان این زبان رو بشناسیم این پست رو قبلاً آماده کردم. برای مثال کافیه یک تحقیق صورت بگیره که سایت‌های بزرگی مثل فیسبوک، آمازون، گوگل و غیره اساسشون با سی++ هست. این کار منطقی و دلایل خودش رو داره ( جاوا اسکریپت همیشه به عنوان یک ابزار خوب در سمت فرانت‌اند مطرح هست. منظور از سی++ این نیست که فرانتش رو هم با سی++ بنویسیم! طبیعتاً شما وقتی با Php یا موارد دیگر وب‌سایتی رو طراحی می‌کنید بخش فرانت و بک‌اندش رو جدا از هم ترکیب خواهید کرد. در این روش هم سمت رابط‌کاربری با HTML5, CSS3, JavaScript, Angular.JS و غیره امکان پذیر است. تمامی کد‌های منطقی سمت سی++ نوشته میشه که طبیعتاً نسبت به دیگر زبان‌ها مزایا و کیفیت خودش رو داره. بستگی داره منظورتون از سیستم کامل چی باشه! برای مثال یک وب‌سرور رو کامل می‌شه پیاده سازی کرد! اما طبیعتاً یک وب‌سایتی که شامل یک ظاهر از طراحی قالب شیک و یا گزینه‌های سمت کاربری هست (این دیوانگیه که با سی++ پیادش کنی) چون JS و HTML برای این کار ساخته شده! بنابراین شما می‌تونی با سی++ بک‌اند وب رو توسعه بدی و بقیه موارد رو با فناوری‌های مرتبط با خودش. نود‌جی‌اِس ذاتاً در جاهایی که کم میاره با سی++ قابل توسعه هست. اما خب وقتی شما می‌تونی با سی++ مستقیم وارد بحث توسعه‌ی وب بشی دیگه نگرانی کارایی نخواهی دات. البته اشاره کنم ماهیت سرعت در برنامه‌های تحت وب ذاتاً فقط بحث زبان نیست! برای مثال بحث‌های چند‌نخی، پردازش‌های موازی و غیره همه مهم هستند. حتی ممکنه شما با سی++ بهترین کد و سریع‌ترین نوعِش رو بنویسی اما با وجود یک کد خیلی ساده اما بد در سمت JS یا HTML از کارایی برنامه به شدت بکاهی! این مقاله صرفاً یک مقاله‌ی آزمایشی بود، در مورد فریم‌ورک‌های قدرتمند سی++ به زودی به معرفی انواع آن‌ها و روش‌های توسعه‌ی وب اشاره خواهد شد که طبیعتاً می‌توان به این نتیجه رسید که نه تنها دیوانگی نیست، بلکه ما با یک روند توسعه و فناوری‌های جدیدی مواجه هستیم.
  20. کامبیز اسدزاده

    خواهش می‌شود.
  21. کامبیز اسدزاده

    خواهش می‌کنم، این سری مقالات اصولاً برای افراد مبتدی تا حرفه‌ای نیاز هست، شخصاً من هم با بعضی از قسمت‌ها و اصول استانداردش مواجه نشده بودم و می‌تونم بگم با در نظر گرفتن چنین اصول و استاندارد از یک قانونی پیروی می‌کنیم که حرفه‌ای ها بهش توجه و بها می‌دهند.
  22. کامبیز اسدزاده

    منظور محدود کردن نیست، در واقع شما عمل تأیید یا امضاء برای یک شیء را جهت استفاده در یک کتابخانه یا برنامه‌ی دیگر اعمال می‌کنید. این واژه‌ی کلیدی به شما اجازه می‌دهد اطلاعات کلاس ذخیره شده را در مراحل کامپایل به لینکر مشخص کنید، با توجه به مثال مربوطه استفاده از این دستور اساساً با توجه به صِفتِ dllexport به لینکر می‌گوید که شیء مورد نظر برای استفاده صادر می‌شود که توسط سایر کتابخانه‌ها (DLL) یا برنامه‌ها قابل استفاده خواهد بود. در این حالت تعاریف مربوط به اعلان‌های موجود باید در برنامه‌ی مشابه پیاده سازی شود، در غیر اینصورت خطای لینکر ساطع می‌شود. زمانی از این روش استفاده می‌شود که بخواهید DLL ای را ساخته و دیگر موارد را به آن لینک (پیوند) کنید. در صورتی که صفت dllimport مشخص شود عمل عکسِ آن صورت می‌گیرد؛ پیاده‌سازی‌های (implementation) مربوطه به آن برای استفاده در برنامه‌ی شما وارد می‌شوند. استفاده از dllimport نیز یک گزینه‌ی اختیاری است. در صورت استفاده از این کلیدواژه، کامپایلر کد کارآمد‌تری را تولید می‌کند. با این حال بهتر است شما برای دسترسی به نماد‌ها و اشیاء داده‌های عمومی از آن استفاده کنید. به مثال‌های زیر توجه کنید: __declspec(dllexport) void messageBox (std::string_view msg); __declspec(dllimport) void messageBox (std::string_view msg); معمولاً پیشنهاد می‌شود برای داشتن یک API خوب به صورت زیر پیاده سازی شود. #ifdef LIBRARY_API #define LIBRARY_API __declspec(dllexport) #else #define LIBRARY_API __declspec(dllimport) #endif نمونه مثال از فایل سرآیند: #ifndef MESSAGELIB_HPP #define MESSAGELIB_HPP #pragma once #include <iostream> #include <string_view> #include <string> #ifdef LIBRARY_API #define LIBRARY_API __declspec(dllexport) #else #define LIBRARY_API __declspec(dllimport) #endif class LIBRARY_API MessageBox { public: MessageBox(); ~MessageBox(); std::string_view message(std::string_view msg); }; #endif // MESSAGELIB_HPP تعاریف مربوطه: #include "messagelib.hpp" MessageBox::MessageBox() { } MessageBox::~MessageBox() { } std::string_view MessageBox::message(std::string_view msg) { return msg; } استفاده از کتابخانه در برنامه‌ها یا کتابخانه‌های دیگر: #include <iostream> #include "messagelib.hpp" using namespace std; int main() { MessageBox msg; cout << msg.message("Hello Boy!") << endl; std::cin.get(); return 0; }
  23. کامبیز اسدزاده

    درود، واژه‌ی کلیدی__decspec با صفتِ dllexport به شما اجازه می‌دهد تا توابع و متغیر‌ها را برای اعلان در مرحله‌ی ورود و خروج کنترل کنید. زمانی که بخواهید داده‌ها، توابع، کلاس‌ها و یا توابع عضو کلاس را از طرف DLL مورد استفاده قرار دهید از این کلمه‌ی کلیدی استفاده می‌شود.
  24. کامبیز اسدزاده

    معرفی و راهنمای استفاده از نسخه‌بندی معنایی

    معرفی نسخه‌بندی معنایی ویرایش ۲.۰ در دنیای مدیریت نرم‌افزار مکان مخوفی به نام «جهنم وابستگی» (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 محدودیت اندازه بر روی رشته‌ی نسخه دارد؟ خیر، اما از قضاوت مناسبی استفاده کنید. به عنوان مثال یک نسخه‌ی ۲۵۵ نویسه‌ای احتمالاً مفید نخواهد بود! همچنین، سیستم‌های خاص ممکن است محدودیت‌های خود برای اندازه‌ی رشته اعمال کنند. - منبع
  25. کامبیز اسدزاده

    معرفی سیاهه تغییرات و راهنمای استفاده از آن

    معرفی سیاهه‌ی تغییرات (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
×
×
  • جدید...