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

آی‌او‌استریم

نوشته‌های ویژه

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

    چشم‌انداز فنی برای کیوت ۶

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

    این چشم‌انداز احتمالاً برای دوست‌‌داران کتابخانهٔ قدرتمند Qt و طرفدارانش جذاب باشد! بنابراین من سعی کرده‌ام تا نتایج پست رسمی کیوت را در رابطه با چشم‌انداز فنی برای آیندهٔ کیوت نسخهٔ ۶ است در اختیار شما قرار دهم. تقریباً ۷ سال پیش کیوت نسخهٔ ۵.۰ منتشر شد! از آن زمان بسیاری از چیز‌ها در دنیای اطراف ما تغییر پیدا کرده است. و اکنون وقت آن رسیده است که چشم‌انداز جدیدی را از نسخهٔ جدید‌تر تعریف کنیم. بنابراین در این پست ما به معرفی مهمترین مواردی که به کیوت ۶ مرتبط است را می‌پردازیم. به نق
    • 6 دیدگاه
    • 3,074 مشاهده
  • کامبیز اسدزاده

    پشت پردهٔ تحریم‌های اپل و وضعیت کنونی اپلیکیشن‌های ایرانی

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

    مدتی است در مورد مسدود شدن اپلیکیشن‌های ایرانی برای iOS از طرف شرکت اپل خبر‌هایی به گوش می‌رسد که در سایت‌ها و پایگاه‌های خبری از سمت نویسندگان و افراد غیرفنی تجزیه تحلیل و روش‌های دور زدن آن‌ها ارائه می‌شود. واقعیت بر دلیل نوشتن این مقاله این است که این فرصت و مشکلات کنونی آبی گل‌آلود برای سود‌جویانی شده است که کاربران از آن بی‌خبرند! هر روز یک توسعه‌دهنده یک سایت جدید راه‌اندازی می‌کند و با ادعای ارائه بستری نامحدود اقدام به تبلیغات می‌کند. بنده نیز به عنوان توسعه‌دهنده وظیفهٔ خودم می‌دانم که
    • 0 دیدگاه
    • 1,527 مشاهده
  • کامبیز اسدزاده

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

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

    با توجه به محبوبیت صنعت وِب، سال‌هاست زبان‌های برنامه‌نویسی در این زمینه پیشرفت‌ها و کاربرد‌های چشم‌گیری را داشته‌اند، از جمله جاوا‌اسکریپت (JS) به عنوان یک زبان قابل اجرا در داخل مرورگر شناخته می‌شود. هرچند بسیار محبوب و کاربردی است، اما این زبان قطعاً مشکلات خودش را دارد که برخی از آن‌ها عدم انعطاف‌پذیر بودن، سرعت پایین اجرا و همچنین انواع غیر ایمن آن است که این باعث می‌شود برای محاسبات و کارهای پیچیده جوابگو نباشد. هرچند گزینه‌هایی مانند CoffeeScript و TypeScript وجود دارند و نسبتا
    • 2 دیدگاه
    • 2,655 مشاهده
  • کامبیز اسدزاده

    فرق بین کامپایل استاتیک و داینامیک

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

    فرق بین کامپایل استاتیک و داینامیک قبل از اینکه فرق بین ایستا (استاتیک) - Static و پویا (داینامیک) - Dynamic را بدانیم لازم است در رابطه با چرخهٔ زندگی نوشتن یک برنامه و اجرای آن آشنا شویم. هر برنامه برای اولین بار توسط یک محیط توسعه (Editor) یا IDE توسط برنامه‌نویسان انتخاب و به صورت فایل متنی قابل ویرایش می‌باشد. سپس فایل متنی که شامل کد‌های نوشته شده توسط برنامه‌نویس تحت زبان برنامه‌نویسی مانند C، C++ و غیره... می‌باشد توسط کامپایلر به کد شیء ای تبدیل می‌شود که ماشین بتواند آن را درک کرد
    • 0 دیدگاه
    • 3,827 مشاهده
  • Max Base

    از تلفن همراه تا سکوی گیت هاب!

    توسط Max Base

    سلام. عدم دسترسی به یک سیستم مناسب و با خبر نبودن از حساب کاربری گیت هاب خود یکی از مشکلاتی بود که در این چند ساله برنامه نویسان با آن روبرو بودند. چک کردن حساب ایمیل در تلفن همراه می توانست تا حدودی به این موضوع کمک کند. اما یک اپلیکیشن اختصاصی برای این مورد می تواند این امر را به بهترین شکل پوشش دهد. بعد از کارهایی که برروی اپلیکیشن رسمی شرکت گیت هاب برای پلتفرم iOS انجام شد و خوشبختانه بدون هیچ مشکلی در بزرگ رویداد و کنفرانس شرکت و مایکروسافت - GitHub Universe 2019 در تاریخ Nov
    • 1 دیدگاه
    • 825 مشاهده

وبلاگ‌های سایت ما

  1. شرکت اینتل یک کیت توسعه نرم‌افزار آزمایشی کوانتومی با نام Quantum SDK را منتشر کرد!

     این کیت یک سری ابزار و روش‌های برنامه‌نویسی را در اختیار توسعه‌دهندگان قرار می‌دهد که امکان برنامه‌نویسی الگوریتم‌های کوانتومی را در یک شبیه‌سازی ممکن می‌کند. این کیت از زبان برنامه‌نویسی ++C و کامپایلر LLVM برای برنامه‌نویسی الگوریتم‌های کوانتومی استفاده می‌کند و به سادگی می‌تواند با برنامه‌های C و ++C و پایتون به کار برده شود. این کیت، به نوعی باعث بزرگ شدن جامعه‌ٔ توسعه‌دهندگانی می‌شود که در زمینه‌ٔ کامپیوترهای کوانتومی فعالیت می‌کنند.

     

    photo_2023-04-21_04-58-29.jpg

    این عکس نشان می‌دهد که شرکت اینتل، و افرادی که در آن کار می‌کنند، با استفاده از یک دستگاه پردازشی ۳۰۰ میلی‌متری، وافرین بر روی یک وافر کیوبیتی (بخشی از یک صفحه اتصال کوانتومی) سیلیسیوم بر روی یک ورقه کوچک انجام داده‌اند.

    نقل قول

    این نقل‌قول بیان می‌کند که کیت توسعه نرم‌افزاری کوانتومی اینتل، به برنامه‌نویسان کمک می‌کند تا برای کامپیوترهای کوانتومی گسترده مقیاس آینده آماده شوند. این کیت نه تنها به توسعه‌دهندگان کمک می‌کند تا در شبیه‌سازی الگوریتم‌های کوانتومی و برنامه‌ها مسلط شوند بلکه با ایجاد یک جامعه از توسعه‌دهندگان به پیشرفت صنعت کوانتومی کمک می‌کند که باعث تسریع در توسعه‌ی برنامه‌هایی می‌شود که آمادگی آن‌ها در هنگام قرار گرفتن سخت‌افزار کوانتومی اینتل را دارند.

    – آن ماتسورا، مدیر برنامه‌های کاربردی و معماری کوانتومی، آزمایشگاه‌های اینتل

    درباره‌ی Intel Quantum SDK 1.0: نسخه‌ٔ 1.0 این SDK، شامل یک رابط برنامه‌نویسی مبتنی بر سی‌پلاس‌پلاس است که به برنامه‌نویسان کلاسیکی، زبان برنامه‌نویسی که با آن آشنایی دارند، را ارائه می‌دهد و امکان همکاری بین آن‌ها و برنامه‌نویسان کوانتومی را فراهم می‌کند. این کیت نیز، یک محیط اجرایی کوانتومی بهینه‌سازی شده برای اجرای الگوریتم‌های کوانتومی-کلاسیکی هیبریدی دارد. توسعه‌دهندگان می‌توانند از دو محیط مختلف برای شبیه‌سازی کیوبیت‌ها استفاده کنند، یکی برای نمایش بیشتر تعدادی کیوبیت‌های عمومی و دیگری، برای شبیه‌سازی سخت‌افزار کیوبیتی اینتل. محیط اولیه، یک شبیه‌ساز  کیوبیت عمومی بسیار عالی با کد منبع باز به نام Intel® Quantum Simulator (IQS) می‌باشد که برای 32 کیوبیت در یک گره و بیش از 40 کیوبیت در چندین گره، توانایی دارد. محیط دوم نیز با شبیه‌سازی سخت‌افزار کیوبیتی اینتل، شبیه‌سازی کوچک مدل کیوبیت‌های گرداننده اسپین سیلیکونی اینتل را فراهم می‌کند. کیوبیت‌های اینتل، از تخصص شرکت در تولید ترانزیستور سیلیکونی برای ساخت کامپیوترهای کوانتومی مقیاس گسترده استفاده می‌کنند.

    photo_2023-04-21_04-58-20.jpg 

    تحقیقات کوانتومی اینتل از دستگاه‌های کیوبیتی تا معماری سخت‌افزار کلی، معماری نرم‌افزار و برنامه‌ها را پوشش می‌دهد. Intel Quantum SDK یک کامپیوتر کوانتومی کامل در شبیه‌سازی است که همچنین قادر به اتصال به سخت‌افزار کوانتومی اینتل، از جمله چیپ کنترل Horse Ridge II و چیپ کیوبیت گرداننده اسپین اینتل است که بزودی در اختیار عموم قرار خواهد گرفت.

    photo_2023-04-21_04-58-23.jpg

    کیت توسعه‌ٔ کوانتومی اینتل، به توسعه‌دهندگان این امکان را می‌دهد که انتخاب کنند کدام یک از دو محیط موردنیاز برای شبیه‌سازی کیوبیت‌ها استفاده شود:

    1. شبیه‌ساز بسیار عالی و با کد منبع باز کیوبیت عمومی، شبیه‌ساز کوانتومی اینتل (Intel Quantum Simulator)
    2. محیط هدف که سخت‌افزار کیوبیتی اینتل را شبیه‌سازی می‌کند و به شبیه‌سازی مدل کوچک کیوبیت‌های گرداننده اسپین سیلیکون اینتل امکان می‌دهد.

    photo_2023-04-21_04-58-26.jpg

    اعلام شده که شرکت اینتل، متعهد به پیشروی در حوزه‌ٔ کامپیوترهای کوانتومی است و از جمله اینترنت از همه جا به عنوان یک روش برای جذب جامعه‌ٔ توسعه‌دهندگان می‌باشد. کاربران بتا این کیت، در حال بررسی انواع موارد مثل دینامیک سیالات، فیزیک نجوم وطراحی مواد هستند.

    photo_2023-04-21_04-58-32.jpg

    تحقیقات کوانتومی اینتل از دستگاه‌های کیوبیتی تا معماری سخت‌افزار کلی، کنترل و معماری نرم‌افزار و برنامه‌ها را پوشش می‌دهد.

  2. یکی از مواردی که در مباحث شیء‌گرایی مهم هستن با عنوان اصول SOLID شناخته می‌شه که شاید خیلی‌ها شنیده باشند.

    واژهٔ SOLID برگرفته شده از پنج اصلِ زیر است:

    1. S - Single-responsiblity Principle
    2. O - Open-closed Principle
    3. L - Liskov Substitution Principle
    4. I - Interface Segregation Principle
    5. D - Dependency Inversion Principle

    68747470733a2f2f6d69726f2e6d656469756d2e636f6d2f6d61782f313139312f312a4f7a774152627648556731526c5a374c59794c4372672e706e67.png

     

    برای پیاده‌سازی SOLID در C++20، می‌توانید از ویژگی‌های زبان استفاده کنید. برای مثال:

    •  برای پیاده‌سازی SRP، می‌توانید از کلاس‌های ساختاری (Structs) و کلاس‌ها و متد‌ها که فقط یک وظیفه دارند، استفاده کنید.
    •  برای پیاده‌سازی OCP، می‌توانید از الگوی Visitor و Strategy استفاده کنید. این باعث می‌شود که کلاس‌های شما قابلیت بسته‌بودن (Close) و در عین حال قابلیت گسترش ‌(Open) را داشته باشند.
    •  برای پیاده‌سازی LSP، می‌توانید از وراثت، کلاس‌های پایه (Base classes) و کلاس‌های مشتق (Derived classes) استفاده کنید و مطمئن شوید که اصول وراثت رعایت شده است.
    •  برای پیاده‌سازی ISP، می‌توانید از الگوی Interface استفاده کنید که به شما امکان می‌دهد که کلاس‌ها فقط به آن قسمت‌هایی از یک Interface نیاز دارند که به آن‌ها لازم است و از بقیه صرف نظر کنند.
    •  برای پیاده‌سازی DIP، می‌توانید از Dependency Injection استفاده کنید که به شما این امکان را می‌دهد که از تمام وابستگی‌های بین کلاس‌ها جدا شده و به‌صورت جداگانه به هم پیوندید، به‌طوری‌که تغییر در یک کلاس اثرات اصلی بر سایر کلاس‌ها نداشته باشد.

    اصلِ اول مربوط به اصل Single-Responsibility Principle یا همان SRP است. این اصل مشخص می‌کند که کلاس‌های شما باید هر کدامشان فقط و فقط باید یک وظیفهٔ مشخص داشته باشند و نه بیشتر!

     

    برای پیاده‌سازی SRP

    بنابراین، اصلِ SRP در شیء‌گرایی به معنی این است که هر کلاس و متد باید فقط یک مسئولیت یا وظیفه را برعهده داشته باشد. این یعنی که هر کلاس فقط باید یک مورد از نرم‌افزار را انجام دهد و تغییر در آن، صرفا برای اعمال تغییرات در آن مورد خاص یا در راستای بهبود مسئولیتش باشد.

    با رعایت اصل SRP، کدها به راحتی قابل نگهداری، توسعه و آزمایش خواهند بود؛ زیرا هر قطعه از کد فقط برای انجام کار خاص خود طراحی شده است و هیچ گونه وظیفه‌ای به کلاس اضافه نشده است. این نه تنها باعث بهبود خوانایی و قابلیتِ پیش‌بینیِ کد می‌شود، بلکه باعث کاهش پیچیدگی و احتمال خطا نیز می‌شود.

    برای پیاده‌سازی SRP در سی‌پلاس‌پلاس مثالی خواهم زد؛ ابتدا باید کلاس را به شکلی طراحی کنید که فقط یک مسئولیت را در بر داشته باشد. به عنوان مثال، فرض کنید یک کلاس برای محاسبه‌ٔ مساحت یک شکل هندسی طراحی می‌کنید. با توجه به SRP، این کلاس فقط باید مسئول محاسبه‌ٔ مساحت باشد و هیچ وظیفه‌ای دیگر را نباید برعهده بگیرد.

    class Shape {
    public:
        virtual double area() const = 0;
    };
    
    class Rectangle : public Shape {
    public:
        Rectangle(double h, double w) : height(h), width(w) {}
        double area() const override {
            return height * width;
        }
    private:
        double height;
        double width;
    };
    
    class Circle : public Shape {
    public:
        Circle(double r) : radius(r) {}
        double area() const override {
            return 3.1415 * radius * radius;
        }
    private:
        double radius;
    };

    در این مثال، کلاس Shape یک مسئولیت واحد دارد که محاسبه‌ٔ مساحت شکل هندسی است. همینطور کلاس‌های Rectangle و Circle نیز فقط مسئول محاسبه‌ٔ مساحت هر یک از شکل‌های هندسی خود هستند.

    به این ترتیب، هر یک از این کلاس‌ها فقط یک مسئولیت دارند و تغییراتی که در آینده رخ می‌دهد، مربوط به تابعی است که این مسئولیت را پوشش می‌دهد و هرگونه تغییرات دیگری نباید شامل کلاس شود.

     

    برای پیاده‌سازی OCP

    اصلِ Open/Closed Principle (اصل OCP) در شیء‌گرایی به معنی ایجاد کلاس‌ها به گونه‌ای است که برای اضافه کردن ویژگی جدید به یک برنامه، نیاز به تغییر کد قبلی نباشد. به عبارت دیگر، کلاس‌ها باید برای توسعه باز باشند (Open)، اما برای تغییر نباشند (Closed). برای پیاده‌سازی OCP، می‌توانید از ارث‌بری، پلی‌مورفیسم، استفاده از ابستراکت کلاس‌ها (کلاس‌های انتزاعی)، الگوی تزریق وابستگی و ... استفاده کنید. این اصل بهبود پذیری (extensibility) و بهره‌وری کد را بهبود می‌بخشد. همچنین برای پیاده‌سازی OCP، می‌توانید از الگوی Visitor و Strategy استفاده کنید. این باعث می‌شود که کلاس‌های شما قابلیت بسته‌بودن (Close) و در عین حال قابلیت گسترش ‌(Open) را داشته باشند.

    به عنوان مثال، فرض کنید یک برنامه داریم که می‌تواند اشکال هندسی مختلف را رسم کند. برای پیاده‌سازی OCP، می‌توانید کلاس اشکال هندسی را به گونه‌ای طراحی کنید که بتوانید به راحتی از آن‌ها ارث‌بری کنید و اشکال جدیدی را به سیستم اضافه کنید بدون ایجاد تغییرات بیشتر در کد قبلی. به عنوان مثال، اینجا یک کد ساده برای این کار نوشته شده است:

    #include <iostream>
    #include <vector>
    
    class Shape {
    public:
        virtual void draw() = 0;
    };
    
    class Rectangle : public Shape {
    public:
        void draw() override {
            std::cout << "Drawing a rectangle\n";
        }
    };
    
    class Circle : public Shape {
    public:
        void draw() override {
            std::cout << "Drawing a circle\n";
        }
    };
    
    class GraphicEditor {
    public:
        void drawAllShapes(std::vector<Shape*> shapes) {
            for (auto shape : shapes) {
                shape->draw();
            }
        }
    };
    
    int main() {
        GraphicEditor editor;
        std::vector<Shape*> shapes = { new Rectangle(), new Circle() };
        editor.drawAllShapes(shapes);
        for (auto shape : shapes) {
            delete shape;
        }
        return 0;
    }
    

    در این مثال، کلاس Shape در واقع یک واسط برای هر یک از شکل‌های هندسی است. کلاس Rectangle و کلاس Circle از کلاس Shape ارث‌بری کرده‌اند و تابع draw آن را پیاده‌سازی کرده‌اند. به این ترتیب، می‌توانید در آینده اشکال هندسی جدیدی را به کد اضافه کنید بدون نیاز به تغییر کد اصلی.

     

    برای پیاده‌سازی LSP

    اصل LSP به معنی اصل جایگزینی قابل توجه لیسکوف (Liskov Substitution Principle) در شیء‌گرایی به این مفهوم است که باید بتوان اشیاء موروثی از یک کلاس را با اشیاء کلاس والد جایگزین کرد. به عبارت دیگر، هر جایگزین یا زیرکلاس باید بتواند عملکرد و ویژگی‌های کلاس والد را حفظ کند و بدون هیچ تغییری، به جای کلاس والد استفاده شود. در واقع، هدف این اصل این است که به جای ایجاد جایگزین‌هایی که منجر به عملکرد غیرقابل پیش‌بینی می‌شوند، جایگزین‌هایی باشند که با انجام کارهایی مانند جایگزینی هنوز هم به نحو شایسته عمل کنند.

    فرض کنید که گربه و سگ، از یک کلاس حیوان وارثی هستند. برای همه‌ٔ حیوانات منطقی است که بتوانند صدای حیوان را تولید کنند. در اینجا با توجه به اصل LSP، باید بتوانیم به جای یک شیء گربه، یک شیء سگ یا شیء کلاس والدِ حیوان را به عنوان جایگزین استفاده کنیم و همچنین از آن‌ها بخواهیم که قابلیت تولید صدا را داشته باشند. به عبارت دیگر، صدای گربه و صدای سگ برای ما دقیقاً در یک رده‌بندی هستند و در همان حیطه معنایی قرار دارند، بنابراین باید بتوانیم هر یک از آن‌ها را به عنوان جایگزین برای دیگری استفاده کنیم.

    یک مثال ساده از اصل LSP در C++20، می‌تواند مربوط به کلاس‌های Shape و Rectangle باشد. فرض کنید کلاس Rectangle از کلاس Shape و از آن ارث‌بری کرده باشد. برای رعایت اصل LSP، کلاس Rectangle باید تمام روش‌های کلاس Shape را پیاده‌سازی کند، به گونه‌ای که در هر جایی که در کد از کلاس Shape استفاده می‌شود، می‌توانیم جایگزین آن را با کلاس Rectangle استفاده کنیم.

    کلاس Shape می‌تواند به صورت زیر باشد:

    class Shape {
    public:
        virtual double area() = 0;
        virtual double perimeter() = 0;
    };

    و کلاس Rectangle از شکل یک مستطیل با طول و عرض دلخواه پیاده‌سازی شده است:

    class Rectangle : public Shape {
    private:
        double length;
        double width;
    public:
        Rectangle(double l, double w) : length(l), width(w) {}
        double area() override {
            return length * width;
        }
        double perimeter() override {
            return 2 * (length + width);
        }
    };

    حال، با استفاده از این کلاس‌ها، می‌توانیم مستطیلی با طول و عرض دلخواه ایجاد کنیم و روش‌های کلاس Shape را روی آن صدا بزنیم:

    Shape* shapePtr = new Rectangle(4, 6);
    double area = shapePtr->area();
    double perimeter = shapePtr->perimeter();

    در اینجا، کلاس Rectangle با کلاس Shape جایگزین شده و اصل LSP رعایت شده است، به این معنی که هر جایی که از کلاس Shape استفاده شده، می‌توانیم جایگزین آن را با کلاس Rectangle استفاده کنیم، بدون هیچ تغییری در کد قبلی.

     

    برای پیاده‌سازی ISP

    اصل ISP به معنی اصل جداسازی رابط (Interface Segregation Principle) در شیء‌گرایی به این مفهوم است که باید رابط‌ها را به گونه‌ای طراحی کرد که اشیاء فقط به آنچه برایشان لازم است دسترسی داشته باشند و به سایر اجزای رابط دسترسی نداشته باشند. به عبارت دیگر، باید یک رابط یکتا و بزرگ به چندین رابط کوچک و مجزا تفکیک شود تا برای هر کلاس، فقط تعداد کم و لازمی از ویژگی‌ها و روش‌ها در دسترس باشد. 

    برای پیاده‌سازی ISP، می‌توانید از الگوهای طراحی مانند واسط‌ها (Interfaces) و کلاس‌های واسط (Abstract Classes) استفاده کنید. با استفاده از این الگوها، می‌توانید پیچیدگی‌های شناور در برنامه خود را کاهش داده و تغییرات را در کد خود به راحتی انجام دهید.

    در واقع، هدف این اصل این است که کلاینت‌ها باید بتوانند با استفاده از رابط‌های ساده تر و متعارف، با سیستم تعامل داشته باشند. این روش منجر به افزایش قابلیت توسعه و خودکارسازی کد، بهره‌وری بالا و حتی صرفه‌جویی در زمان و هزینه خواهد شد. برای مثال نمونهٔ زیر به عنوان بخشی از پردازش تصویر می‌باشد:

    ابتدا واسط ImageTransformer را تعریف می‌کنیم که حاوی متدهای تبدیل تصویر به سیاه و سفید و برعکس آن است:

    class ImageTransformer {
    public:
       virtual void transformToBlackAndWhite() = 0;
       virtual void transformToColor() = 0;
    };

    سپس دو کلاس ImageToBlackAndWhiteTransformer و ImageToColorTransformer را برای پیاده‌سازی واسط ImageTransformer تعریف می‌کنیم:

    class ImageToBlackAndWhiteTransformer: public ImageTransformer {
    public:
        void transformToBlackAndWhite() override {
            // Implement the transformation to black and white
        }
    };
    
    class ImageToColorTransformer: public ImageTransformer {
    public:
        void transformToColor() override {
            // Implement the transformation to color
        }
    };

    حال می‌توانیم از هر یک از کلاس‌های ImageToBlackAndWhiteTransformer و ImageToColorTransformer برای پردازش تصویر استفاده کنیم.

    در نهایت، به عنوان مثالی از استفاده از متد‌های رابط ImageTransformer، کد زیر را در نظر بگیرید:

    void processImage(ImageTransformer& transformer) {
        transformer.transformToBlackAndWhite();
        transformer.transformToColor();
    }

    در این کد، با گرفتن یک شیء از کلاسی که از واسط ImageTransformer ارث‌بری کرده است، می‌توانیم تصویر را به سیاه و سفید و برعکس آن تبدیل کنیم که بر اساس اصل ISP طراحی شده‌است.

    برای پیاده‌سازی اصل ISP در C++20 به‌طور کلی، می‌توان از این ویژگی بهره برد که به نام concepts شناخته می‌شود. این ویژگی به برنامه نویسان امکان می‌دهد که شرایط و محدودیت‌هایی را برای قالب‌ها، ورودی‌ها و خروجی‌ها تعریف کنند و باعث شود که کد بهتری با پایداری بیشتری نوشته شود.

    برای استفاده از این ویژگی در پیاده‌سازی اصل ISP در C++20، می‌توانید از مفهومی استفاده کنید که برای اطمینان از قابلیت اجرا و خطاهای برنامه سازی موجود است. برای مثال، در کد زیر، الگوهای واسط که برای پردازش تصویر استفاده می‌شوند، با نام‌های ImageTransformer و GrayscaleTransformer (با استفاده از template) تعریف شده‌اند. هر کدام از این الگوهای واسط، تعدادی عملیات مشخص شده را تعریف می کنند. سپس با استفاده از این الگوها، کلاس ImageProcessor (نیز با استفاده از template) برای پردازش تصویر طراحی شده است.

    template<typename T>
    concept ImageTransformer = requires(T t, cv::Mat image) {
        { t.transform_to_grayscale(image) } -> cv::Mat;
        { t.transform_to_rgb(image) } -> cv::Mat;
    };
    
    template<typename T>
    concept GrayscaleTransformer = requires(T t, cv::Mat image) {
        { t.transform_to_grayscale(image) } -> cv::Mat;
    };
    
    template <typename T>
    class ImageProcessor {
    public:
        ImageProcessor(T* transformerPtr) : transformerPtr_{ transformerPtr } { }
        
        cv::Mat transform_to_grayscale(cv::Mat image) {
            return transformerPtr_->transform_to_grayscale(image);
        }
        
        cv::Mat transform_to_rgb(cv::Mat image) {
            return transformerPtr_->transform_to_rgb(image);
        }
        
    private:
        T* transformerPtr_;
    };

    همچنین، می‌توانید کلاس‌های مربوط به پردازش تصویر یعنی GrayscaleImageTransformer و RGBImageTransformer را به این الگوها منطبق کنید. در کد زیر، چک کردن اینکه یک کلاس منطبق بر پیشنیازهای ImageTransformer است یا نه، انجام شده است.

    class GrayscaleImageTransformer : public GrayscaleTransformer {
    public:
        cv::Mat transform_to_grayscale(cv::Mat image) override {
            cv::Mat grayscaleImage;
            cv::cvtColor(image, grayscaleImage, cv::COLOR_BGR2GRAY);
            return grayscaleImage;
        }
    };
    
    class RGBImageTransformer : public ImageTransformer {
    public:
        cv::Mat transform_to_grayscale(cv::Mat image) override {
            cv::Mat grayscaleImage;
            cv::cvtColor(image, grayscaleImage, cv::COLOR_BGR2GRAY);
            return grayscaleImage;
        }
        
        cv::Mat transform_to_rgb(cv::Mat image) override {
            cv::Mat rgbImage;
            cv::cvtColor(image, rgbImage, cv::COLOR_GRAY2BGR);
            return rgbImage;
        }
    };
    
    int main() {
        GrayscaleImageTransformer grayscaleTransformer;
        RGBImageTransformer rgbTransformer;
        
        ImageProcessor grayscaleProcessor{ &grayscaleTransformer };
    
        cv::Mat image; 
        image = cv::imread("image.jpg");
    
        auto grayscaleResult = grayscaleProcessor.transform_to_grayscale(image);
        
        ImageProcessor rgbProcessor{ &rgbTransformer };
        auto rgbResult = rgbProcessor.transform_to_rgb(grayscaleResult);
    
        cv::imwrite("grey.jpg", grayscaleResult);
        cv::imwrite("rgb.jpg", rgbResult);
    
        return 0;
    }

     

    برای پیاده‌سازی DIP

    DIP یا Dependency Inversion Principle (اصل وابستگی معکوس) یکی از اصول SOLID در شیء‌گرایی است که به مفهوم وابستگی به جایی یا Inversion of Control (IOC) هم معروف است. اصل DIP بیان می‌کند که برنامه باید به گونه‌ای طراحی شود که وابستگی به جزئیات پیاده‌سازی برنامه کاهش یابد و به جای آن، برنامه باید بر اساس واسط‌ها (interface) ارتباط برقرار کند، به گونه‌ای که خود وابستگی به جزئیات پیاده‌سازی به صورت بالادستی بر اساس واسط‌ها مدیریت شود.

    با استفاده از اصل DIP، کد قابلیت بازگشت و تغییر بهتر را دارد. این بدان معناست که تغییر در پیاده‌سازی یک کد، تنها روی کد فعلی تأثیر نمی‌گذارد و به خاطر استفاده از واسط‌ها، به صورت گسترده‌تر در برنامه تأثیر می‌گذارد. با رعایت اصل DIP، کدها با استفاده از واسط‌ها باید طراحی شوند و نباید به کد پیاده‌سازی جزئیات برچسب تمایل یا وابستگی داشته باشند. به عبارت دیگر، برنامه باید بر اساس قرارداد کار کند نه کد پیاده‌سازی.

    یک مثال ساده از پیاده‌سازی DIP در C++ به صورت زیر است:

    فرض کنید یک برنامه ساده را برای محاسبه جدول ضرب در نظر بگیرید. برای پیاده‌سازی این برنامه، یک کلاس MatrixCalculator وجود دارد که دارای دو متد است که برای محاسبه جدول ضرب به کار می‌روند: multiply و print.

    ابتدا یک واسط مشترک بین MatrixCalculator و کلاس‌های مختلف جدول تعریف می‌کنیم:

    class IMatrix {
    public:
        virtual void multiply() = 0;
        virtual void print() = 0;
    };

    سپس دو کلاس Matrix2x2 و Matrix3x3 را برای پیاده‌سازی واسط IMatrix تعریف می‌کنیم:

    class Matrix2x2 : public IMatrix {
    public:
        void multiply() {
            // implementation for 2x2 matrix multiplication
        }
    
        void print() {
            // implementation for 2x2 matrix printing
        }
    };
    
    class Matrix3x3 : public IMatrix {
    public:
        void multiply() {
            // implementation for 3x3 matrix multiplication
        }
    
        void print() {
            // implementation for 3x3 matrix printing
        }
    };

    حالا کلاس MatrixCalculator را به گونه‌ای تغییر می‌دهیم که به جای استفاده از پیاده‌سازی خاص هر کلاس، از واسط IMatrix استفاده کند:

    class MatrixCalculator {
    private:
        IMatrix* matrix;
    public:
        MatrixCalculator(IMatrix* m) : matrix(m) {}
    
        void multiply() {
            matrix->multiply();
        }
    
        void print() {
            matrix->print();
        }
    };

    بنابراین حالا می‌توانیم کلاس MatrixCalculator را به صورت زیر استفاده کنیم:

    IMatrix* m2x2 = new Matrix2x2();
    MatrixCalculator calculator2x2(m2x2);
    calculator2x2.multiply();
    calculator2x2.print();
    
    IMatrix* m3x3 = new Matrix3x3();
    MatrixCalculator calculator3x3(m3x3);
    calculator3x3.multiply();
    calculator3x3.print();

    با این رویکرد، هر زمان که یک کلاس جدید با پیاده‌سازی واسط IMatrix ایجاد شود، می‌توانیم آن را به کلاس MatrixCalculator اضافه کرده و آن را بدون تغییر در کد MatrixCalculator استفاده کنیم. همچنین وابستگی MatrixCalculator به کلاس‌های Matrix2x2 و Matrix3x3 برای انجام کارش کاهش یافته است.

    در C++20 می‌توان از ویژگی concepts برای پیاده‌سازی DIP استفاده کرد. در اینجا مثال ساده‌ای از پیاده‌سازی DIP با ویژگی concepts در C++20 آورده شده است:

    #include <iostream>
    #include <concepts>
    
    template <typename T>
    concept Comparable = requires(T a, T b) {
        { a == b } -> std::convertible_to<bool>;
        { a != b } -> std::convertible_to<bool>;
    };
    
    template <typename T>
    class Calculator {
    public:
        Calculator(T num1, T num2) : num1_(num1), num2_(num2) {}
    
        T add() requires Comparable<T> {
            return num1_ + num2_;
        }
        
    private:
        T num1_;
        T num2_;
    };
    
    int main() {
        Calculator<int> intCalc(5, 10);
        std::cout << intCalc.add() << std::endl;
    
        Calculator<float> floatCalc(5.5, 10.5);
        std::cout << floatCalc.add() << std::endl;
    
        // Calculator<std::string> strCalc("hello", "world");   // Compile-time error
        return 0;
    }

    در این مثال، ما از ویژگی concepts برای تعریف واسط Comparable استفاده کرده‌ایم. همچنین، کلاس Calculator از واسط Comparable به عنوان یک شرط برای تعریف تابع add استفاده شده است. با این رویکرد، ما به سادگی می‌توانیم به جای وابستگی به یک نوع دقیق، وابستگی به یک واسط را ایجاد کنیم.

  3.  با سلام و درود،

    پیرو مقالهٔ قبلی در رابطه با بخشی از نهایی‌سازی‌های استاندارد ۲۳

     

    در این مقاله قصد داریم در رابطه با استاندارد ۲۶ و نهایی‌سازی‌های ۲۳ یک جمع‌بندی داشته باشیم که بسیار در شناخت و به‌روز رسانی سریع از پیشرفت این زبان را به ما نشان می‌دهد.

    cpp26.png

    طبق جلسات اخیر از کمیتهٔ استاندارد‌سازی، در اولین جلسه، کمیته بر اصلاح ویژگی‌های C++23 متمرکز شد که عبارتند از:

    • عملگرstatic operator[]
    • ویژگی static constexpr در توابع constexpr 
    • محدودهٔ ایمن range-based در for
    • تعامل std::print با سایر خروجی های کنسول
    • رابط الگوی مونادیک برای std::expected
    • خاصیتstatic_assert (false) و سایر ویژگی‌ها

    در جلسهٔ دوم، کمیته بر روی توسعه ویژگی‌های جدید برای C++26 کار کرد، از جمله:

    • ویژگی‌های std::get و std::tuple_size
    • ماکروی #embed
    • بدست آوردن std::stacktrace از استثناء‌ها
    • کرووتین‌های (coroutines) پشته‌ای

    در ویژگی‌های سی‌پلاس‌پلاس ۲۳ (static operator[])

    تابستان گذشته، کمیته ویژگی static operator() را به استاندارد C++23 اضافه کرد و امکان تعریف operator[] را برای چندین آرگومان فراهم کرد. مرحلهٔ منطقی بعدی دادن فرصت‌های برابر به این عملگرها بود، یعنی اضافه کردن توانایی نوشتنِ static operator[].

    enum class Color { red, green, blue };
    
    struct kEnumToStringViewBimap {
      static constexpr std::string_view operator[](Color color) noexcept {
        switch(color) {
        case Color::red: return "red";
        case Color::green: return "green";
        case Color::blue: return "blue";
        }
      }
    
      static constexpr Color operator[](std::string_view color) noexcept {
        if (color == "red") {
          return Color::red;
        } else if (color == "green") {
          return Color::green;
        } else if (color == "blue") {
          return Color::blue;
        }
      }
    };
    
    // ...
    assert(kEnumToStringViewBimap{}["red"] == Color::red);

    آیا این کد واقعاً کارآمد برای تبدیل رشته به enum است؟

    ممکن است تعجب آور باشد، اما کد فوق در واقع بسیار کارآمد است. توسعه‌دهندگانِ کامپایلر از رویکردهای مشابهی استفاده می‌کنند و ما نیز تکنیک مشابهی را در چارچوب userver پیاده‌سازی کرده‌ایم. ما یک کلاس جداگانه به نام utils::TrivialBiMap با رابط‌کاربری راحت‌تر ایجاد کرده‌ایم.

    constexpr utils::TrivialBiMap kEnumToStringViewBimap = [](auto selector) {
      return selector()
          .Case("red", Color::red)
          .Case("green", Color::green)
          .Case("blue", Color::blue);
    };

    راندمان بالا به لطف ویژگی‌ کامپایلرهای بهینه‌سازی مدرن به دست می‌آید (اما هنگام نوشتن یک راه حل کلی باید بسیار مراقب بود). پیشنهاد در سند P2589R1 تمام جزئیات لازم را شرح می‌دهد.

    ویژگی static constexpr در توابع constexpr

    استاندارد C++23 عملکرد خود را با افزودن constexpr به_chars/from_chars گسترش داده است. اما برخی از اجرا کننده‌گان با مشکل مواجه شدند. چندین کتابخانهٔ استاندارد حاوی آرایه‌های ثابتی برای تبدیل سریع string<>number بودند که به عنوان متغیرهای ثابت در توابع اعلام شدند. متأسفانه، این مانع استفاده از آنها در توابع constexpr شد. این مسئله قابل حل است، اما راه حل ها واقعاً ناشیانه به نظر می‌رسید. در نهایت، کمیته با اجازه دادن به استفاده از متغیرهای static constexpr در توابع constexpr، همانطور که در سند P2647R1 مشخص شد که مشکل را حل کرده‌ است. یک پیشرفت کوچک، اما خوشایند.

     

    محدودهٔ ایمن range-based در حلقهٔ for

    این احتمالاً هیجان انگیزترین خبری است که از دو نشست جلسهٔ استاندارد‌سازی‌های گذشته منتشر می‌شود! در مورد آن، اجازه دهید با یک معمای سرگرم کننده شروع کنیم: آیا می‌توانید اشکال موجود در کد را شناسایی کنید؟

    class SomeData {
     public:
      // ...
      const std::vector<int>& Get() const { return data_; }
     private:
      std::vector<int> data_;
    };
    
    SomeData Foo();
    
    int main() {
      for (int v: Foo().Get()) {
        std::cout << v << ',';
      }
    }

    هرچند پاسخ آن در این‌جا آمده است:

    The Foo() function returns a temporary object, and when the Get() method is called on this object, it returns a reference to the data inside the temporary object. The range-based for loop is then transformed into a code close to this one:
    
        auto && __range = Foo().Get() ;
        for (auto __begin = __range.begin(), __end = __range.end(); __begin != __end; ++__begin)
        {
            int v = *__begin;
            std::cout << v << ',';
        }
    
    Here, the first string is equivalent to this:
    
        const std::vector<int>& __range = Foo().Get() ;
    
    The result is a dangling reference.

    حلقه‌های مبتنی بر محدوده (Range-based for) شامل فرآیندهای زیربنایی زیادی هستند و در نتیجه، این نوع باگ‌ها ممکن است همیشه آشکار نباشند. در حالی که می‌توان این مشکلات را از طریق آزمایش‌های مربوط به sanitizers‌ها به طور مؤثر تشخیص داد، پروژه‌های نوین معمولاً آنها را به‌عنوان روش استاندارد شامل می‌شوند (پروژه‌های مطرحی مانند Yandex، از این قاعده مستثنی نیستند). با این حال، ایده‌آل است که در صورت امکان از چنین اشکالاتی به طور کامل اجتناب کنید. در RG21، ما اولین تلاش خود را برای بهبود این وضعیت چهار سال پیش با سند D0890R0 انجام دادیم. متأسفانه، این روند در مرحله بحث متوقف شد. خوشبختانه، Nicolai Josuttis ابتکار عمل را انتخاب کرد و در C++23، کدهای مشابه دیگر مرجع معلق (dangling reference) ایجاد نمی‌کنند. تمام اشیایی که در سمت راست : در یک حلقه for مبتنی بر محدوده (ranges) ایجاد می‌شوند، اکنون فقط هنگام خروج از حلقه از بین می‌روند. برای جزئیات فنیِ بیشتر، لطفاً به سند P2718R0 مراجعه کنید.

    ویژگی std::print

    در C++23، یک به‌روزرسانی کوچک اما قابل توجه برایstd::print وجود دارد: خروجی آن برای «همگام‌سازی» با سایر خروجی‌های داده تنظیم شده است. در حالی که بعید است کتابخانه‌های استاندارد در سیستم‌عامل‌های نوین تغییرات قابل توجهی را تجربه کنند، استاندارد به‌روز شده اکنون تضمین می‌کند که پیام‌ها به ترتیبی که در کد منبع ظاهر می‌شوند به کنسول خروجی ساطع می‌شوند:

    printf("first");
    std::print("second");

     

    رابط الگوی مونادیک برای std::expected

    یک ویژگی نسبتاً مهم در آخرین لحظه به C++23 اضافه شد: یک رابط مونادیک برای std::expected، مشابه رابط مونادیک که قبلاً برای std::optional موجود بود، اضافه شده است.

    using std::chrono::system_clock;
    std::expected<system_clock, std::string> from_iso_str(std::string_view time);
    std::expected<formats::bson::Timestamp, std::string> to_bson(system_clock time);
    std::expected<int, std::string> insert_into_db(formats::bson::Timestamp time);
    
    // Somewhere in the application code...
    from_iso_str(input_data)
        .and_then(&to_bson)
        .and_then(&insert_into_db)
        // Throws “Exception” if any of the previous steps resulted in an error
        .transform_error([](std::string_view error) -> std::string_view {
            throw Exception(error);
        })
    ;

    می‌توانید شرح کاملی از تمام رابط‌های مونادیک برای std::expected  را در سند P2505R5 بیابید.

     

    خاصیتstatic_assert (false) و سایر ویژگی‌ها

    علاوه بر تغییرات قابل توجهی که در بالا ذکر شد، تعداد زیادی بازنگری برای حذف لبه‌های ناهموار جزئی و بهبود توسعه روزمره انجام شده است. به عنوان مثال، فرمت‌کننده‌ها برای std::thread::id و std::stacktrace (P2693 سند) تا بتوان از آنها با std::print و std::format استفاده کرد. به ویژه std::start_lifetime_a بررسی‌های زمان کامپایل اضافی را در سند P2679 دریافت کرده است. قابل توجه است که خاصیت static_assert(false) در توابع الگو (template function) دیگر بدون نمونه‌سازی تابع فعال نمی‌شود، به این معنی که کدی مانند زیر فقط در صورت ارسال نوع داده اشتباه، عیب‌یابی را کامپایل و صادر می‌کند:

    template <class T>
    int foo() {
        if constexpr (std::is_same_v<T, int>) {
          return 42;
        } else if constexpr (std::is_same_v<T, float>) {
          return 24;
        } else {
          static_assert(false, "T should be an int or a float");
        }
    }

    علاوه بر تغییراتی که قبلاً ذکر شد، بهبودهای بیشماری در خاصیت (ranges) از C++23 انجام شده است. مهمترین آنها گنجاندن std::views::enumerate در سند P2164 است:

    #include <ranges>
    
    constexpr std::string_view days[] = {
        "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun",
    };
    
    for(const auto & [index, value]: std::views::enumerate(days)) {
        print("{} {} \n", index, value);
    }

     

    ویژگی‌های سی‌پلاس‌پلاس ۲۶

    ویژگی‌های std::get و std::tuple_size برای (aggregates) تجمیع

    یک ایدهٔ جدید و هیجان انگیز برای بهبود ++C وجود دارد که در حال حاضر به طور فعال در Yandex Go و چارچوب userver استفاده می‌شود و به لطف Boost.PFR برای هر کسی که آن را می‌خواهد در دسترس است.

    اگر در حال نوشتن یک کتابخانهٔ مبتنی بر الگو (template) و عمومی هستید، به احتمال زیاد باید از std::tuple و std::pair استفاده کنید. با این حال، برخی از مشکلات در این نوع وجود دارد. اولاً، آنها خواندن و درک کد را دشوار می‌کنند زیرا ورودی‌های نامِ واضحی ندارند، و تشخیص معنای چیزی مانندstd::get<0>(tuple) می‌تواند چالش برانگیز باشد. علاوه بر این، کاربران کتابخانهٔ شما ممکن است نخواهند مستقیماً با این انواع کار کنند و درست قبل از فراخوانیِ روش‌های شما، اشیاء‌ای از این نوع ایجاد می‌کنند که به دلیل کپی کردن داده‌ها می‌تواند ناکارآمد باشد. ثانیاً، std::tuple و std::pair بی‌اهمیت بودن انواعی را که ذخیره می کنند، «تبلیغ نمی کنند». در نتیجه، هنگام ارسال و برگرداندن std::tuple و std::pair از توابع، کامپایلر ممکن است کدی را با کارآیی پایین‌تر تولید کند. با این حال، aggregates (تجمیع‌ها) - ساختارهایی (struct) با میدان‌های عمومی و بدون عملکرد خاص - عاری از اشکالات ذکر شده هستند.

    ایده‌ای که پشت سند P2141R0 وجود دارد، این است که با کار کردن std::get و std::tuple_size آنها، امکان استفاده از تجمیع‌ها در کدهای عمومی را فراهم می‌کند. این به کاربران امکان می‌دهد تا ساختارهای خود را مستقیماً بدون کپی برداری غیر ضروری به کتابخانهٔ عمومی شما منتقل کنند. این ایده به خوبی توسط کمیته مورد استقبال قرار گرفت، و ما در آینده روی آزمایش و رسیدگی به هرگونه لبهٔ ناهموار و بالقوه در این زمینه کار خواهیم کرد.

     

    ماکروی #embed

    در حال حاضر، توسعهٔ فعالی روی یک استاندارد زبان C جدید (یک استاندارد بدون کلاس، بدون ++) وجود دارد که شامل بسیاری از ویژگی‌های مفیدی است که مدت‌هاست در ++C وجود داشته است (مانند: nullptr، auto، constexpr، static_assert، thread_local، [[noreturn]).])، و همچنین ویژگی‌های کاملاً جدید برای ++C. خبر خوب این است که برخی از ویژگی‌های جدید از استاندارد جدید C به C++26 منتقل می‌شوند. یکی از این موارد جدید، #embed است - یک دستورالعمل پیش پردازنده برای جایگزینی محتویات یک فایل به عنوان یک آرایه در زمان کامپایل:

    const std::byte icon_display_data[] = {
        #embed "art.png"
    };
    

    شرح کامل این ایده در سند P1967 موجود است.

    بدست آوردن std::stacktrace از استثناء‌ها

    در اینجا، ایدهٔ سند P2370 در WG21 با یک شکست غیرمنتظره روبرو شده است. توانایی به دست آوردن ردیابی پشته از یک استثناء در اکثر زبان‌های برنامه‌نویسی وجود دارد. این ویژگی فوق‌العاده مفید است و به جای پیام‌های خطای غیر اطلاعاتی مانند Caught exception: map::at تشخیص‌های آموزنده‌تر و قابل فهم‌تر را امکان‌پذیر می‌کند که نمونه مثال آن به صورت زیر است:

    Caught exception: map::at, trace:
    0# get_data_from_config(std::string_view) at /home/axolm/basic.cpp:600
    1# bar(std::string_view) at /home/axolm/basic.cpp:6
    2# main at /home/axolm/basic.cpp:17

    هنگامی که در محیط یکپارچه سازی پیوسته (CI) استفاده می‌شود، این ویژگی می‌تواند فوق‌العاده مفید باشد. این به شما امکان می‌دهد تا به سرعت مسائل را در آزمون شناسایی کنید و از دردسر بازتولید مشکل به صورت محلی اجتناب کنید، که ممکن است همیشه امکان‌پذیر نباشد. متأسفانه کمیتهٔ بین‌المللی به طور کامل از این ایده استقبال نکرد. اما تیم توسعه نگرانی‌ها را بررسی می‌کند و روی اصلاح این ایده کار خواهد کرد تا بتواند حمایت بیشتری را کسب کند.

    کسانی که معمولاً می‌پرسند چه تفاوتی بین زبان‌های دیگر و استاندارد‌های سی‌++ وجود دارد، در این‌جا می‌توانند به این موضوع دقت کنند که زبانی مانند سی‌پلاس‌پلاس دارای کمیتهٔ استاندارد‌سازی بین‌المللی است و هر تغییری باید قابل توجیه باشد.

     

    کروتین‌های (coroutines) پشته

    سرانجام، پس از سال‌ها کار، استاندارد سی‌پلاس‌دلاس به افزودن پشتیبانی اولیه برای برنامه‌های پشته‌ای در C++26 نزدیک شده است (به سند P0876 مراجعه کنید). ارزش آن را دارد که بیشتر در مورد روال‌های پشته‌ای یا بدون پشته بررسی کنیم. برنامه‌های بدون پشته به پشتیبانی کامپایلر نیاز دارند و نمی‌توانند به تنهایی به عنوان یک کتابخانه پیاده‌سازی شوند. از سوی دیگر، کروتین‌های پشته‌ای را می‌توان به تنهایی پیاده‌سازی کرد - برای مثال، با Boost.Context.

    در حالت‌های قبلی، تخصیص حافظه کارآمدتر، بهینه‌سازی بالقوه بهتر کامپایلر و توانایی تخریب سریع آنها را ارائه می‌دهد. آنها همچنین در حال حاضر در C++20 در دسترس هستند. ادغام نمونه‌های اخیر در پروژه‌های موجود بسیار آسان‌تر است، زیرا نیازی به بازنویسی کامل در یک اصطلاح جدید مانند برنامه‌های بدون پشته ندارند. در واقع، آنها جزئیات پیاده‌سازی را به طور کامل از کاربر مخفی می‌کنند و آنها را قادر می‌سازند تا کد خطی ساده‌ای را که در لایه‌های زیرینِ ناهمزمانی هستند بنویسند.

    بدون پشته (Stackless)

    auto data = co_await socket.receive();
    process(data);
    co_await socket.send(data);
    co_return; // requires function to return a special data type

    پشته‌ای (Stackfull)

    auto data = socket.receive();
    process(data);
    socket.send(data);

    سند  P0876  قبلاً در زیرگروه اصلی قرار داشته است. پس از بحث و گفتگو، تصمیم گرفته شد که مهاجرت این گونه برنامه‌ها (coroutines) بین رشته‌‌های اجرایی ممنوع شود. دلیل اصلی این ممنوعیت این است که کامپایلرها دسترسی به TLS را بهینه کرده و مقادیر متغیرهای TLS را در حافظه پنهان ذخیره می‌کنند:

    thread_local int i = 0;
    // ...
    ++i;
    foo();  // Stackful coroutines can switch execution threads
    assert(i > 0);  // The compiler saved the address in a register; we’re working with the TLS of another thread

    جمع‌بندی

    در نهایت استاندارد C++23 رسماً به مقامات بالاتر از کمیتهٔ ISO ارسال شده است و به زودی به عنوان یک استاندارد کامل منتشر خواهد شد. در همین حال، توسعه C++26 در نوسان کامل است و چشم‌اندازهای هیجان‌انگیزی برای خاصیت‌های متنوع وجود دارد. اگر ایده‌های نوآورانه‌ای برای بهبود ++C دارید، با خیال راحت آنها را به اشتراک بگذارید. یا - حتی بهتر - ارسال یک پیشنهاد را در نظر بگیرید.

  4. دو هفته پیش، نشست ۲۰۱۸ سی‌پلاس‌پلاس آغاز شد. شرکت کننده‌ها مدال‌های خودشان را دریافت کردند چرا که همه‌ چیز با هماهنگی بسیار خوبی به پایان رسید. این رویداد به عنوان یکی از چندین رویداد مهمC++ بشمار می‌رود که هرساله توسط حامیان و علاقه‌مندانش برگزار می‌شود.

     

    سخنان کلیدی

    امسال در این رویداد سه یادداشت کلیدی وجود داشت، که با حضور Andrei Alexandrescu ،Lisa Lippincott و Nicolai Josuttis ارائه شد.

    IMG_0399_600.JPG

    اولین سخنران Andrei Alexandrescu بود، او این کنفرانس را با افکار و اندیشه‌های خودش برای شروع آغاز کرد عنوان موضوع آن به بَد بودنِ کپی constexpr از static if اشاره می‌کرد. او یک سخنران سرگرم کننده است، بنابراین سخنرانی او بسیار طبیعی در مورد یادداشت‌های خودش منعکس می‌شد. همچنین او به عنوان یک توسعه‌دهندهٔ ++C به نقاط بسیاری اشاره کرد که کمیتهٔ استاندارد سازی زبان حرف‌های او را تایید می‌کرد.

    IMG_0620_600.JPG

    سخنران دوم Lisa Lippincott روز دوم را با یک سخنرانی آغاز کرد که دیدگاه‌های مختلفی در مورد محاسبات و منطق که در آن به کار می‌رود ارائه داد. زمانی که مُجری لیزا را دعوت کرد، می‌دانست که این موضوع به عنوان یک نکته مهم برای فکر کردن است، چیزی که همه نمی‌توانند به طور مستقیم آن را درک کنند و به آن دسترسی پیدا کنند. اما این تلنگری برای نحوهٔ درک کُد از دیدگاه ریاضی و دیدگاه جدیدی بود.

    IMG_1000_600.JPG

    سخنران سوم و آخر Nicolai Josuttis بود که در مورد، او اولین سخنران در نشست Hartmut Kaiser در سال ۲۰۱۴ بود. در آن سخنرانی بسیار خوب درخشیده، بنابراین در قسمت سوم نقص‌هایی را با جزئیات در مورد نقاط خشن ++C نشان داد. این سخنرانی بسیار صادقانه بود! چرا که بسیاری از جزئیات خشن بودن سی‌پلاس‌پلاس را عنوان کرد که همگی با آن موافق بودند.

     

    مذاکرات، مسابقه و گفتگوها‌ی چند دقیقه‌ای

    جلسات و رویداد‌های مرتبط با ++C همیشه گفتگو‌های بسیار خوبی دارد، و با یک مسیر مشخص که هدفش آوردن سخنرانان جدید با دیدگاه‌های جدید است برگزار می‌شود. بازخورد سخنران‌ها در این رویداد خوب بود چرا که به برخی از نکات در مورد چگونگی بهبود‌ها اشاره کردند.

    IMG_0728._600.JPG

    IMG_0871_600.JPG

    تصویر بالا مربوط به Hana Dusíková است که می‌توان به آن بهترین نمره را داد. بهترین سخنرانی هم مربوط به  Andrei Alexandrescu بود که دنبال شد. در اولین عصر این رویداد، امتحان (Quiz) برجسته‌ترین مورد رویداد در آن روز بود. سازماندهی آن توسط Diego  و اسپانسری آن توسط Conan است که برای چند سال اخیر حمایت شده است. به نظر می‌رسید که سوالات امتحانی این سال سخت‌تر از سوالات رویداد قبلی در سال گذشته بوده است. اما بار دیگر این سرگرمی ترکیب بسیار خوبی با ترس از سی‌++ را داشت.

    هر یک از سوالات امتحانی یک خروجی از کُد را تولید می‌کردند، که هر گروه باید برای کسب امتیاز آن را می‌نوشتند. ده نوع کُد امتحانی وجود داشت که تهیه کنندهٔ گزارش برای به تصویر کشیدن آن‌ها زیاد خوب عمل نکرده است. بنابراین تصویر زیر مربوط به سوالات چالشی در مورد سی‌پلاس‌پلاس است:

    IMG_0542_600.jpg

    گفتگو‌های کوتاه در طی جلسات سی‌پلاس‌پلاس صورت می‌گیرد. اما در سال‌های گذشته روش به گونه‌ای تغییر یافته است که سوالات پرسیده شده باید با گفتگو‌ها و سوالات دیگر رقایبت می‌کردند. با این حال این یک قالب و روش جالبی بود که نتیجهٔ موفقیت آمیزی را داشت. همهٔ شرکت کننده‌ها می‌توانستند این سوالات رو ببینند و در مورد آن‌ها تفکر کرده و پاسخ دهند.

    • نقل قول

      نتیجه : این رویداد بیشتر به عنوان یک دوره‌همی و گفتگو در مورد رفتار‌های خشن زبان سی‌پلاس‌پلاس و پاسخ‌های سرگرم کننده در مورد آن‌ها را فراهم کرده است و به ویژگی‌های جدید زبان در آن پرداخته نشده است.

    نکته: شما می‌توانید تصاویر ویدیویی مربوط به این رویداد را از کانال رسمی آن در یوتیوب دریافت کنید.

     

  5. در سالی که گذشت (۲۰۲۲)، سی‌پلاس‌پلاس محبوب‌ترین زبان برنامه‌نویسی با رشد شاخص محبوبیت ۴.۶۲٪ انتخاب شد!

    جایزه زبان برنامه‌نویسی سال TIOBE به ++C تعلق گرفت! این جایزه به زبان برنامه‌نویسی تعلق می‌گیرد که بیشترین افزایش محبوبیت را در یک سال تجربه کرده است.

    cpp-award.png

    شاخص TIOBE میزان محبوبیت زبان‌های برنامه‌نویسی را اندازه‌گیری می‌کند. با این حال، قبل از نتیجه‌گیری، توجه به این نکته مهم است که Index (شاخص) نه چیزی در مورد کیفیت یک زبان برنامه‌نویسی می‌گوید و نه ادعا می‌کند. این رتبه‌بندی با تجزیه و تحلیل تعداد مهندسان ماهر در یک زبان خاص، تعداد دوره‌های آموزشی در آن زبان و تعداد فروشندگان شخص ثالثی که محصولات یا خدمات مرتبط با آن زبان را ارائه می‌دهند، محاسبه می‌شود. این فهرست ماهانه به‌روز می‌شود و بر اساس داده‌های موتورهای جستجوی محبوب مانند گوگل، بینگ و یاهو است. جایزهٔ زبان برنامه‌نویسی سال TIOBE در ژانویه هر سال بر اساس رتبه‌بندی سال قبل اعلام می‌شود.

    سی‌پلاس‌پلاس یک زبان برنامه‌نویسی در سال ۲۰۲۲ انتخاب شد که با محبوبیت رشد ۴.۶۲ درصد و بیشترین رشد انتخاب شده است. این زبان برنامه‌نویسی سطح بالا با کارایی بالا و چندمنظوره برای توسعهٔ نرم‌افزار‌های سیستمی، برنامه‌های کاربردی و بازی‌های ویدیویی با انعطاف‌پذیری و قابلیت کنترل سطوح پایین است. این زبان در نوامبر ۲۰۲۲ جاوا را پشت‌سر گذاشت و به رتبهٔ سوم شاخص رسید و محبوبیت آن به طور پیوسته در حال افزایش است. نایب قهرمان در سال ۲۰۲۲ به ترتیب C با رشد ۳.۸۲ و پایتون با ۲.۷۸ درصد رشد بوده‌اند.

  6. Max Base
    آخرین نوشته

    توسط Max Base،

    سلام.

    عدم دسترسی به یک سیستم مناسب و با خبر نبودن از حساب کاربری گیت هاب خود یکی از مشکلاتی بود که در این چند ساله برنامه نویسان با آن روبرو بودند.

    چک کردن حساب ایمیل در تلفن همراه می توانست تا حدودی به این موضوع کمک کند. اما یک اپلیکیشن اختصاصی برای این مورد می تواند این امر را به بهترین شکل پوشش دهد.

    بعد از کارهایی که برروی اپلیکیشن رسمی شرکت گیت هاب برای پلتفرم iOS انجام شد و خوشبختانه بدون هیچ مشکلی در بزرگ رویداد و کنفرانس شرکت و مایکروسافت - GitHub Universe 2019 در تاریخ November 13-14, 2019 رونمایی شد. به عنوان یکی از اعضای شرکت این نوید را می دهم که نوبت به آن رسید تا اپلیکیشن برای اندروید نیز پیاده شود.

    در حال حاضر این اپلیکیشن در حال توسعه است و هنوز رونمایی نشده است.

    برای این اپلیکیشن میزان پشتیبانی API 21+ Android device در نظر گرفته شده است و خواهد توانست از نسخه Android 5.0 به بالا را پشتیبانی کند.

    می توانید پیشنهادات و نظرات خود را نیز ایمیل کنید. Max [@] Asrez {.DOR.} com

    Hi, I'm Max Base.

    GitHub team did work on the official GitHub application for the iOS platform and fortunately unveiled at the big event and conference(GitHub Universe 2019 on November 13-14, 2019). As a member of the company, I have the promise that the app will launch for Android.

    This app is currently under development and has not been unveiled yet.

    This app is designed to support Android 21+ API and will support Android 5.0 or later.

    You can also email your suggestions and comments. Max [@] Asrez {.DOR.} com

    Best,

    Max Base

    GitHub-APP-iOS.jpg

     

    1546157682482731460_mobile-work-all-2.pn

    29235157682482727545_mobile-triage-all.p

     

    3900157682482736585_mobile-nigode-all--m

    4116015768248237796_mobile-nigode-all.pn

    7086157682482713148_mobile-contribute-al

    11133157682483611776_mobile-beta-all.png

    با تشکر

    Max Base / مکس بیس

  7. سلام و درود،

    این اواخر راجع به مشورت و راهنمایی‌ها خیلی ساده به قضیه نگاه می‌شه، همه فکر کردن کشکه و فقط با دونستن JS یا QML می‌شه محصول ساخت. البته این مثال JS و QML یک مثال هست و این مسئله در همهٔ ابزار‌ها و حول محور حوزهٔ کامپیوتر و نرم‌افزار به چشم می‌خوره، هرچند روی داستان ساده هست اما حتی پشت این کار‌های ساده کلی زمان باید صرف بشه. همین گرفتن یک دادهٔ ساده از سمت سرور و تجزیه کردنش سمت JS نیاز به یک دانش خوب در مورد معماری Api‌داره، نیاز به آگاهی از استاندارد‌های Http داره، نیاز به تخصص کافی در ریز به ریز مسائل داره، نیاز به آگاهی لازم در مورد شبکه و نحوهٔ مدیریتش داره، نیاز به درک خوب راجع به کلاس‌های شبکه و نحوهٔ مدیریت بسته‌ها داره و صد‌ها جور مسئلهٔ دیگه.

    road-sign-01.png

    یا راهنمایی نکنیم یا می‌کنیم همه چیز رو ساده نشون ندیم!
    به خصوص برای کسایی که سال‌ها یه چیز دیگه خوندن و الآن قراره وارد این حوزه بشن.
    قشنگ واقعیت رو باید به نمایش گذاشت، و اگرنه به اشتراک گذاری چهارتا UI خفن که بگین با QML هم میشه کاری نداره، سه سوته می‌شه این‌ها رو طراحی کرد.

    اگر کسی اطلاعات کافی و پایهٔ تخصصی نداشته باشه و همینطور متکی به یک ابزار یا زبان پیش بره چه اتفاق می‌افته؟ از نظر من قطعاً بهتون از نظر تجربی آسیب میزنه، ساخت یک محصول واقعاً به این سادگی‌ها نیست که تو گروه‌های تلگرامی داریم راجع بهش صحبت می‌کنیم! قضیه خیلی پیچیده‌تر از این‌هاست. فراموش نکن در این حوزه اگه یک کار ساده رو سریع انجام میدیم یا به نتیجه می‌رسونیم دلیلش به خاطر سال‌ها زمان و تلاشه، امکان نداره کسی حتی با ۲..۳ سال تجربه یک کار رو سریع بتونه صفر تا صد انجام بده و مشکلی نداشته باشه یا نتیجهٔ اون در سطح یک استاندارد معتبر باشه.

    ساخت محصول اصول داره که اولین مرحلش شفاف‌سازی و نقشهٔ توسعه و ایده‌پردازی درسته، نباید مثل بعضی از مشتری‌ها باشه که پشت تلفن زنگ می‌زنن می‌گن یه سایت می‌خوایم یا یه اپلیکیشن چند می‌گیری و بعدش شروع کنن به چک و چونه زدن و شما هم کیف کنی بگی که آره دیگه مشتری دارم!

    شما تا زمانی که جزء به جزء محصول رو آگاه نباشید، یعنی تا زمانی که دقیق متوجه نشید نیاز چی هست و روش حلش رو متوجه نباشید منطقی نیست که واردش بشید. چون همین مرحلهٔ نیاز‌سنجی به قدری مهمه که فرآیند مسیر و نقشهٔ توسعهٔ یک محصول رو نشونتون میده و اگه درست تشخیص ندین و ابزار‌ها و راه‌کار‌ها رو درست انتخاب نکنید بی برو برگرد با مشکل مواجه می‌شید.

    مشکلاتش می‌تونه به این صورت باشه:

    - سردرگمی
    - عدم توانایی کالبد‌شکافی مسئله
    - عدم توانایی حل مسئله
    - عدم توانایی انتخاب یک روش یا ابزار صحیح و مناسب
    - عدم تعامل شما با مشتری
    - عدم رضایت شما از حق‌الزحمه
    - عدم رضایت مشتری از نتیجهٔ کار
    - عدم توانایی در پاسخ‌دهی به اعضا و شرکای کلیدی دیگه در محصولات تجاری و بزرگ!
    - و هزاران مسئلهٔ دیگه که همشون نتیجهٔ تشخیص نا درسته.
    - در کنارش مهمترین خاصیتی که پیدا می‌کنه این خواهد بود در اوج نادانی احساس خواهد کرد که همه چیز دان هست! به قولی همه چیز گیگ!

    از نظر من حداقل مواردی که (به طور خیلی خیلی خلاصه و محدود) نیاز هست تا یک متخصص بتونه پاسخ‌گوی‌ تصمیم‌گیری نقشهٔ توسعهٔ یک محصول برای مشتری در ابعاد مختلف و سطوح متفاوت از حوزه‌های موجود در قالب اصولی باشه به صورت زیر هستند:

    ۱- آشنا مبانی کامپیوتر که امر طبیعیه (شامل درک و فهم مسائل و نحوهٔ حلشون متناسب با پلتفرم اجرایی محصول)
    ۲- آشنا به ساختار نوع محصول استاندارد در یک حوزه مثل: وب، آی‌او‌اس، اندروید یا دسکتاپ‌های مختلف مثل لینوکس، مک و ویندوز، اینترنت اشیاء و دیگر موارد.
    ۳- آشنا به فلسفهٔ بک‌اند و فرانت‌اند یا ترکیبی از این دو به همراه ابزار‌های مناسب.
    ۴- آشنا به اصول طراحی UI/UX به عنوان یک نیاز و یک فاکتور مهم در ساخت محصولی که وابسته به عملکرد کاربر داره و در حوزهٔ فرانت‌اند مهم و کاربردی هست.
    ۵- آشنا به اصول SOLID و امثالش مهم هستند.
    ۶- آشنا اصول برنامه‌ریزی ساخت بانک اطلاعاتی، اینکه از چه بانک اطلاعاتی‌ای استفاده کنی و چرا؟
    ۷- آشنا به ارتباطات داده‌ای، جداول و ارتباط بین فیلد‌ها، جدوال و روش‌های درست تبادل اطلاعات مابینی داده‌ها.
    ۸- آشنا و تسلط کافی به یک محیط توسعه و ادغام ابزار‌ها و محیط طراحی برای هدف.
    ۹- آشنا به معماری ساختار و رابط‌های برنامه‌نویسی (Api)
    ۱۰- آشنا به استاندارد‌های Http، درک و مدیریت درخواست، پاسخ‌ها و ...
    ۱۱- آشنا به الگو‌های طراحی برنامه‌نویسی (DP)
    ۱۲- آشنا به روش‌های نگه‌داری و آزمایش نرم‌افزار و کد‌ها به خصوص درک مبحث Fault tolerance.
    ۱۳- آشنا به روش‌های اطمینان‌سازی و ایمن‌سازی پردازش‌های داخلی نرم‌افزار برای جلوگیری یا دشوار سازی نفوز و خراب‌کاری
    ۱۴- آشنا به روش‌ها و معماری‌های احراز هویت و نحوهٔ ادغامش با نرم‌افزار مثل:JWT, OAuth, AWS و غیره...
    ۱۵- آشنا به نوع پارادایم‌های زبان برنامه‌نویسی، در قالب‌های  (دستوری) Imperative و  (اعلانی) Declarative مثل OOP، functional و دیگر موارد.
    ۱۶- آشنا به سبک معماری نرم‌افزاری (Microservice یا مثلاً Monolith) مزایا و معایبشون.
    ۱۷- آشنا به سبک معماری طراحی مانند MVC در طراحی بدنهٔ محصول.
    ۱۸- آشنا به سبک و الگو‌های طراحی ساختاری در بک‌اند مانند Builder، Abstract، Factory و غیره.
    ۱۹- آشنا به ساختار یک زبان (در صورتی که می‌خواین جوابگوی مسائلِ پیش آمده باشید) کالبد‌شکافی زیر‌پوستی و عمیق یک زبان مهمه.
    ۲۰- آشنا و درک کامپایلر‌ها و مفسر‌ها، تفاوت‌ها و شیوه‌های عملکردیشون نسبت به کد‌های بهینه شده و عادی.
    ۲۱- آشنا و درک مدل‌های مختلفی از سیستم‌های توزیع شده مثل IaaS، PaaS، SaaS یا FaaS.
    ۲۲- آشنا به ابزار‌های ساخت و فرآیند کاری اون‌ها مثل CMake، NMake، QMake و غیره.
    ۲۳- آشنا به روش‌های مدیریت وابستگی‌های نرم‌افزار و ابزار‌های لازم برای بسته‌بندی بهتر خروجی.
    ۲۴- آشنا به روش‌های کد‌نویسی قابل آزمایش (Unit Test) و استفاده از ابزار‌هایی مثل CTest, GTest, Catch2 و غیره.
    ۲۵- آشنا به توسعهٔ آزمون محور (Test Driven- Development)
    ۲۶- آشنا به گام‌ها و شرایط نسخه‌نگاری و مراحل توسعهٔ نرم‌افزار (SDP)
    ۲۷- آشنا به روش‌های امنیت در کد و توسعه به شیوه‌های بررسی از طریق Fuzz-Test، Sanitizer، آنالیزر‌های پویا و ایستا و غیره...
    ۲۸-آشنا به قوائد طراحی بر پایهٔ خدمات مبتدی بر معماری ابری برای خدمات پیامی، وب‌سرویس‌ها، پردازش و غیره.
    ۲۹- در سطوح وب آشنا به مکانیزم شاخص بندی، فاکتور‌های SEO و شیوه‌‌های درست بهبود صفحات وب.
    ۳۰- آشنا به روش‌های به کار گیری و پیاده‌سازی ثبت کننده‌ٔ وقایع در دل محصول و روش‌های بازخورد برای توسعهٔ بهتر به همراه مانیتورینگ، نظارت و تریسینگ.
    ۳۱- در شرایط لزوم آشنا به نحوهٔ به کار گیری و دلیل استفاده از فناوری‌هایی مثل Redis، Memcached و غیره.
    ۳۲- آشنا و درک صحیح از مفاهیم هم‌زمانی (Concurrency) و روش‌های به کار گیری آن نسبت به زبان برنامه‌نویسی و شرایط مناسب استفاده.
    ۳۳- آشنا به سبک و قوائد و ساختار زبان‌های برنامه‌نویسی و فرآیند ساخت و ترجمه.
    ۳۴- و تا صد‌ها گزینهٔ دیگه می‌تونم لیست کنم اینجا که اگه انتخابتون زبان‌های نزدیک به سیستم باشه این داستان در ادامهٔ این توضیحات سر به فلک می‌کشه نمونش کامپایلر‌ها خودشون شونصد جور مباحث دارند، پلتفرم‌ها ومعماری‌های پردازنده‌ای هم در این زبان‌ها مهمن و شما حتی تا عمق سیستم‌عامل و رابط‌های اون‌ها و نحوهٔ رفتارشون باید اطلاعات کافی داشته باشید که هر کدوم به نوبهٔ خودشون هزاران صفحه می‌شه راجع بهشون کتاب معرفی کرد.

    این لیست چیزی بود که به زبان بسیار بسیار ساده شده و خیلی خلاصه به ذهنم رسید تا بدانید همچین هم الکی نیست ای عزیزانی که فتوا‌های صد من یه غاز میدین و این مسائل رو حل شده می‌دونید! 

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

    * وقتی می‌گم آشنا قطعاً در حد حروف الفبا کافی نیست، باید در حد نیاز تسلط و درک کافی ازشون وجود داشته باشه.
    * همهٔ این‌ها رو باید در کمترین زمان ممکن نسبت به یک مشتری، محصول و نیاز تشخیص بدین و انتخاب کنید، به این کار می‌گن ارزیابی محصول بر اساس دانسته‌های فنی که تماماً متکی بر دانش و تجربهٔ شماست. (کارشناسی پروژه دقیقاً همین موضوع است).
    * برای بهتر شدن و حرفه‌ای تر شدن هم باید فراتر از این‌ها پیش برید و در قالب «مثلث دانش» بهبودش بدهید.
    * محصولات معتبر جهانی حاصلِ چنین نقشه‌های پیش‌بردی هستند و اصول تخصصی و مهندسی رو رعایت می‌کنن تا به یک درجهٔ کیفی موفق و زبان زد می‌رسند. شاید این مسائل از نظر یک برنامه‌نویس ساده و نه چندان با تجربه مهم نباشه، اما در سطح کیفی یک محصول نرم‌افزاری همهٔ این مسائل مهم تلقی می‌شوند.

    برای همین می‌گم گولِ توصیه‌های ساده و ظاهر چهارتا برنامه یا کیوت، دات‌نت و امثال این ابزار‌ها رو نخورید، پشت همهٔ نیاز‌های یک محصول به فاکتور‌های بسیاری باید توجه کنید. فردا بخواهید بدون آگاهی در این مسائل وارد پروژه‌هایی بشید که به ظاهر ساده هستند یا باید دست به گریبان دیگران باشید و توی گروه‌ها مدام سوأل پرسی کنید و یا باید بیخیال آن شوید؛ چون به هیچ یک از این فاکتور‌های مورد نیاز توسعه توجه نکردین! پس این اصول رو به عنوان سر نخ مطالعه کنید تا بخش بزرگی از سرگردانی‌های شما حل شود.

    این مواردی که این جا اشاره کردم، همونطور که گفتم بخش بسیار کوچکی از دنیای نیازمندی‌های ساخت و ساز و طراحی یک محصول واقعی در پیرامون نرم‌افزار و کامپیوتر هست، اما یک دل‌گرمی بدم به کسایی که با خودشون فکر می‌کنند چنین مسیر یا نقشه‌ای از راه که قراره پیش بگیرند سخته و همهٔ ماجرا این نیست (جزئیات رو در کتاب‌ها، موقعیت و فرصت‌های شغلی، شکست‌ها، موفقیت‌ها و آزمون و خطاها یاد خواهند گرفت) و نتیجهٔ اون می‌تونه مطابق همین حکایت زیر باشه:

    نقل قول

    حکایت برنامه‌نویسان، ابزار‌ها، تجربه و تخصصی که در بازار بی ارتباط با آن نیست!

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

    وی با جعبه ابزار بزرگی آمد و بلافاصله مشغول بررسی دقیق موتور کشتی شد.
    دو نفر از صاحبان کشتی نیز مشغول تماشای کار او بودند.
    مرد از جعبه ابزارش آچار کوچکی بیرون آورد و با آن به آرامی ضربه ای به قسمتی از موتور زد، بلافاصله موتور شروع به کار کرد و درست شد.

    یک هفته بعد صورتحسابی ده هزار دلاری از آن مرد دریافت کردند، صاحب کشتی با عصبانیت فریاد زد:

    او واقعا هیچ کاری نکرد!
    ده هزار دلار برای چه می خواهد بگیرد؟

    بنابراین از آن مرد خواستند ریز صورتحساب را برایشان ارسال کند؟
    مرد تعمیر کار نیز صورتحساب را اینطور برایشان فرستاد:

    ضربه زدن با آچار: ۲دلار
    تشخیص اینکه ضربه به کجا باید زده شود: ۹۹۹۸ دلار

    و ذیل آن نیز نوشت:

    تلاش کردن مهم است.
    اما دانستن اینکه کجای زندگی باید تلاش کرد می‌تواند همه چیز را تغییر بدهد.

     

     

×
×
  • جدید...