<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های اسماعیل احمدی پور</title>
        <link>https://virgool.io/feed/@software8686</link>
        <description>برنامه نویس موبایل (فلاتر ، اندروید ، یونیتی ، iOS)</description>
        <language>fa</language>
        <pubDate>2026-04-15 02:51:45</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/386658/avatar/M7nCJK.png?height=120&amp;width=120</url>
            <title>اسماعیل احمدی پور</title>
            <link>https://virgool.io/@software8686</link>
        </image>

                    <item>
                <title>کش شدن وب اپلیکیشن فلاتری پس از نصب روی دستگاه</title>
                <link>https://virgool.io/@software8686/%DA%A9%D8%B4-%D8%B4%D8%AF%D9%86-%D9%88%D8%A8-%D8%A7%D9%BE%D9%84%DB%8C%DA%A9%DB%8C%D8%B4%D9%86-%D9%81%D9%84%D8%A7%D8%AA%D8%B1%DB%8C-%D9%BE%D8%B3-%D8%A7%D8%B2-%D9%86%D8%B5%D8%A8-%D8%B1%D9%88%DB%8C-%D8%AF%D8%B3%D8%AA%DA%AF%D8%A7%D9%87-nctq4eb3qgrv</link>
                <description>کش شدن وب اپلیکیشن فلاتری پس از نصب روی دستگاهتوسعه وب اپلیکیشنها با فلاتر جذابیتهای بسیاری دارد، اما همانطور که میدانیم، هر تکنولوژی با چالشهای خاص خود همراه است. یکی از مشکلاتی که در تجربه شخصی خود با آن مواجه شدم، کش شدن نسخههای قبلی وب اپلیکیشن بود. این مسئله زمانی بیشتر آزاردهنده میشود که کاربران حتی پس از بهروزرسانی، همچنان با نسخه قدیمی کار میکنند.این مشکل بهویژه زمانی که برنامه را بهصورت PWA (Progressive Web App) روی دستگاههای موبایل نصب میکردم، واضح تر بود. در چنین شرایطی، PWA نصب شده همچنان نسخه کش شده قبلی را بارگذاری میکرد، حتی اگر نسخه جدیدی از برنامه دیپلوی شده بود. این موضوع نه تنها تجربه کاربری را تحت تأثیر قرار میدهد، بلکه ممکن است باعث شود یک کسبوکار به کلی از استفاده از PWA فلاتر منصرف شود.تصور کنید که باگها در نسخه جدید رفع شدهاند، اما کاربران همچنان با نسخه پر از اشکال کار میکنند؛ این میتواند به شدت به اعتبار محصول و کسبوکار شما آسیب بزند.خوشبختانه، راهحل این مشکل بسیار ساده است. کافی است قطعه کد زیر را در فایل index.html پروژه خود قرار دهید:کد قبلی  که در فایل index.htmlباید با کد جدید جایگزین شود :کد قبلی :
  window.addEventListener(&#039;load&#039;, function(ev) {
    // Download main.dart.js
    _flutter.loader.loadEntrypoint({
      serviceWorker: {
        serviceWorkerVersion: serviceWorkerVersion,
      },
      onEntrypointLoaded: function(engineInitializer) {
        engineInitializer.initializeEngine().then(function(appRunner) {
          appRunner.runApp();
        });
      }
    });
  });
کدی جدیدی که  باید جایگزین کد قبلی در فایل index.html شود:
    window.addEventListener(&#039;load&#039;, function(ev) {
        // Register the service worker
        if (&#039;serviceWorker&#039; in navigator) {
            navigator.serviceWorker.register(&#039;/service_worker.js&#039;).then((registration) =&gt; {
                registration.onupdatefound = () =&gt; {
                    const installingWorker = registration.installing;
                    installingWorker.onstatechange = () =&gt; {
                        if (installingWorker.state === &#039;installed&#039;) {
                            if (navigator.serviceWorker.controller) {
                                // New update available, reload the page
                                console.log(&#039;New content is available; please refresh.&#039;);
                                .reload();
                            } else {
                                console.log(&#039;Content is cached for offline use.&#039;);
                            }
                        }
                    };
                };
            }).catch((error) =&gt; {
                console.error(&#039;Error during service worker registration:&#039;, error);
            });
        }

        // Download main.dart.js
        _flutter.loader.loadEntrypoint({
            serviceWorker: {
                serviceWorkerVersion: serviceWorkerVersion,
            },
            onEntrypointLoaded: function(engineInitializer) {
                engineInitializer.initializeEngine().then(function(appRunner) {
                    appRunner.runApp();
                });
            }
        });
    });
این کد به گونهای عمل میکند که هر بار که نسخه جدیدی از سرویس ورکر منتشر میشود، وجود نسخه جدید شناسایی شده و به صورت خودکار نسخه کششده سرویس ورکر قبلی حذف و نسخه جدید لود خواهد شد. با این روش، کاربران همیشه از آخرین نسخه برنامه استفاده خواهند کرد و از مشکلات ناشی از کش شدن نسخههای قدیمی جلوگیری میشود.امیدوارم این راهحل برای شما مفید باشد. اگر سوالی داشتید، میتوانید در بخش نظرات یا از طریق پیام در LinkedIn با من در ارتباط باشید.</description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Thu, 08 Aug 2024 23:16:51 +0330</pubDate>
            </item>
                    <item>
                <title>مدیریت دکمه بک مرورگر در فلاتر با استفاده از GoRouter</title>
                <link>https://virgool.io/flutter-community/%D9%85%D8%AF%DB%8C%D8%B1%DB%8C%D8%AA-%D8%AF%DA%A9%D9%85%D9%87-%D8%A8%DA%A9-%D9%85%D8%B1%D9%88%D8%B1%DA%AF%D8%B1-%D8%AF%D8%B1-%D9%81%D9%84%D8%A7%D8%AA%D8%B1-%D8%A8%D8%A7-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-gorouter-fnrqmmqlooa2</link>
                <description>مدیریت دکمه بک مرورگر در فلاتر با استفاده از GoRouterدر انتخاب ابزار مدیریت روتینگ در فلاتر، گزینههای زیادی وجود دارد. اما زمانی که به محبوبترین پکیجها نگاه میکنیم، GoRouter به عنوان یکی از بهترینها شناخته میشود. با وجود مزایای بسیار، GoRouter نیز با چالشهایی مواجه است و یکی از مشکلات قابل توجه آن، مدیریت دکمه بک مرورگر است. در این مقاله، به بررسی این مشکل و ارائه راهحل آن خواهیم پرداخت.مشکل:در یک برنامه معمولی، ناوبری بین صفحات به صورت پیوسته و منظم است. این ساختار اطمینان میدهد که کاربران روند خاصی را دنبال کنند. اما استفاده از دکمه بک مرورگر میتواند این روند را مختل کرده و باعث شود که برنامه به صورت غیرمنتظرهای رفتار کند یا توالی ناوبری مورد نظر از بین برود.علاوه بر این، مدیریت این مسئله در چندین پلتفرم پیچیدگی دیگری را اضافه میکند. مهم است که کد به طور یکپارچه در تمام پلتفرمها، از جمله وب، بدون مشکل کار کند. هدف داشتن راهحلی است که نه تنها دکمه بک مرورگر را در وب مدیریت کند بلکه در سایر پلتفرمها نیز به درستی عمل کند.راهحل:گام 1: ایجاد یک فایل جاوا اسکریپت برای محدود کردن دکمه بک به صفحه اول PWAاولین قدم، ایجاد یک فایل جاوا اسکریپت است که عملکرد دکمه بک را به صفحه اول برنامه وب پیشرفته (PWA) محدود کند.نام فایل:  clear_browser_history.jsfunction clearBrowserHistory(redirectUrl) {
  // جایگزین کردن وضعیت فعلی با وضعیت جدید
  history.replaceState(null, document.title, location.pathname);
  // پاک کردن تاریخچه جلو
   = function(event) {
    // هدایت به یک صفحه خاص
    .href = redirectUrl;
  };
}گام 2: درج فایل جاوا اسکریپت در HTMLدر مرحله بعد، باید این فایل جاوا اسکریپت را به فایل HTML خود اضافه کنید. خط کد زیر را درست بالای تگ &lt;/body&gt; اضافه کنید.&lt;script src=&amp;quotclear_browser_history.js&amp;quot&gt;گام 3: کپی فایل جاوا اسکریپتاطمینان حاصل کنید که فایل clear_browser_history.js در همان دایرکتوری که فایل HTML شما قرار دارد، کپی شده است.گام 4: وارد کردن پکیج js و فراخوانی تابع جاوا اسکریپت در Dartقبل از فراخوانی تابع جاوا اسکریپت، باید پکیج js را به فایل pubspec.yaml خود اضافه کنید:dependencies:
  flutter:
   sdk: flutter
  js: ^0.6.3سپس، در کد Dart خود، پکیج js را وارد کرده و تابع را فراخوانی کنید:میتوانید دکمه بک مرورگر را شرطی کنید که در حالت دیباگ و یا رلیز به کدام صفحه برگردد.js.context.callMethod(&#039;clearBrowserHistory&#039;, [
  kDebugMode
   ? &amp;quothttp://localhost:80&amp;quot // میتوانید پورت محلی خود را تنظیم کنید
      : &amp;quothttps://ea2.dev&amp;quot  //  میتوانید صفحه وب دلخواه خود را تنظیم کنید تا دکمه بک مرورگر به آن برگردد
]);گام 5: ایجاد کلاس واسط برای مدیریت محیطهای وب و نیتیواز آنجا که ما از پکیج js برای اجرای کد جاوا اسکریپت استفاده میکنیم، باید اطمینان حاصل کنیم که ایمپورت بسته به پلتفرم به صورت شرطی انجام میشود. ما یک کلاس واسط ایجاد خواهیم کرد که بسته به اینکه در محیط وب یا نیتیو اجرا میشود، رفتار متفاوتی داشته باشد. این نیاز به سه فایل برای پیادهسازی دارد:نام فایل: multiPlatforms.dartimport &#039;native.dart&#039; if (dart.library.html) &#039;web.dart&#039; as switch_value;
class MultiPlatforms {
  MultiPlatforms._();
static Future&lt;void&gt; clearBrowserHistory() {
    return switch_value.clearBrowserHistory();
  }
}نام فایل: web.dartimport &#039;dart:js&#039; as js;
import &#039;package:flutter/foundation.dart&#039;;
Future&lt;void&gt; clearBrowserHistory() async {
  js.context.callMethod(&#039;clearBrowserHistory&#039;, [
    kDebugMode
        ? &amp;quothttp://localhost:80&amp;quot // میتوانید پورت سفارشی خود را تنظیم کنید
        : &amp;quothttps://ea2.dev&amp;quot  // میتوانید صفحه وب سفارشی خود را تنظیم کنید
  ]);
}نام فایل: native.dartFuture&lt;void&gt; clearBrowserHistory() async {}مرحله 6: ادغام کد با GoRouterبرای گام آخر، باید تعیین کنید که کجا این کد را فراخوانی کنید. در GoRouter، قسمتی وجود دارد که ریدایرکت شدن را مدیریت میکند. بهترین نقطه برای فراخوانی کد پاک کردن تاریخچه مرورگر، این بخش است.در اینجا یک نمونه کد آورده شده است:final appRouter = GoRouter(
  initialLocation:  ... // این قسمت را بر اساس کد خود تکمیل کنید
  redirect: (context, state) {  // بخش مهم برای این مقاله در اینجا است
MultiPlatforms.clearBrowserHistory();
    return null;
  },
  routes: [...] // این قسمت را بر اساس کد خود تکمیل کنید
);با دنبال کردن این مراحل، میتوانید دکمه بازگشت مرورگر را به طور موثر در برنامه Flutter خود با استفاده از GoRouter مدیریت کنید و تجربه کاربری یکنواختی را در همه پلتفرمها تضمین کنید.برای هرگونه سوال یا گفتگوی بیشتر، می‌توانید در کامنت‌ها یا از طریق LinkedIn با من ارتباط برقرار کنید.</description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Fri, 02 Aug 2024 01:13:52 +0330</pubDate>
            </item>
                    <item>
                <title>پیاده سازی ارث بری در OOP با کدهای دارت برای فریم ورک Flutter-بخش دوم</title>
                <link>https://virgool.io/@software8686/%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D8%A7%D8%B1%D8%AB-%D8%A8%D8%B1%DB%8C-%D8%AF%D8%B1-oop-%D8%A8%D8%A7-%DA%A9%D8%AF%D9%87%D8%A7%DB%8C-%D8%AF%D8%A7%D8%B1%D8%AA-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-flutter-%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-t8p4eewechzt</link>
                <description> ارث‌ بری چندگانه   (Multiple Inheritance)
مقدمه:در این مقاله، مبحث ارث بری  را مرور می کنیم  و به بررسی ارث‌بری چندگانه  (Multiple Inheritance) و چگونگی پیاده‌سازی  آن می‌پردازیم.در برنامه‌نویسی شیءگرا یا OOP مفهومی به نام ارث‌بری Inheritanceداریم. مفهوم ارث‌بری به برنامه‌نویسان این امکان را می‌دهد که کلاس جدیدی (مثلا فرزند) را بر اساس کلاس موجود (یا اصطلاحا والد) تعریف کنند و ویژگی‌ها و رفتارهای کلاس والد را به کلاس فرزند منتقل کنند. در واقع، کلاس فرزند می‌تواند از کلاس والد به عنوان یک پایه برای ساختار خود استفاده کند.مفهوم ارث‌بری چندگانه:ارث‌بری چندگانه به برقراری ارتباط بین یک کلاس فرزند و چندین کلاس والد می پردازد. جایی که کلاس فرزند ویژگی‌ها و عملکردهای همه کلاس‌های والد خود را به ارث می‌برد. این ویژگی به برنامه‌نویس این امکان را می‌دهد که از ویژگی‌های مختلف کلاس‌های والد برای ایجاد کلاس‌ یا کلاس های فرزند استفاده کنند.قبل از تشریح موضوع با ذکر مثال ,  گفتن این نکته حائز اهمیت است که در زبان دارت   ,به طور مستقیم امکان ارث بری چندگانه مقدور نیست. چون در زبان دارت امکان  ارث‌بری چندگانه با ابهام یا (Diamond Inheritance) وجود ندارد ما نمیتوانیم چنین کدی را به زبان دارت بنویسیم :class A {
  void show() {
    print(&#039;کلاس A&#039;);
  }
}

class B extends A {
  void show() {
    print(&#039;کلاس B&#039;);
  }
}

class C extends A {
  void show() {
    print(&#039;کلاس C&#039;);
  }
}

class D extends B with C {}

void main() {
  var obj = D();
  obj.show(); // خطا: ارث‌بری چندگانه با ابهام
}اما به دو روش امکان پیاده سازی آن وجود دارد :1- با استفاده از mixin ها2- با استفاده از کلاس های abstractدر ادامه هر دو روش پیاده‌سازی  را با حل یک مساله بررسی خواهیم کرد.صورت مساله:ما نیاز داریم یک برنامه بنویسیم که دو نفر با جنسیت و شغل مشخص شده را به عنوان دو شیء از کلاس Human ایجاد کند و سپس با فراخوانی تابعintroduce()، جمله‌ای را چاپ کند که جنسیت و شغل هر فرد را نمایش دهد.پیاده‌سازی ارث‌بری چندگانه با میکسین‌ها:میکسین‌ها کلاس‌هایی هستند که می‌توانند ویژگی‌ها و متدهایی را شامل شوند و سپس این میکسین‌ها را به یک یا چند کلاس فرزند ( به کمک عبارت کلیدی with ) اضافه می کنیم و به این ترتیب، کلاس های فرزند قابلیت استفاده از ویژگی‌ها و متدهای mixin  را خواهد داشت.mixin GenderMixin {
  String _gender = &#039;&#039; ;
  String getGender() {
  return _gender;
  }

  void setGender(String gender) {
    _gender = gender;
  }
}
mixin JobMixin {
  String _job = &#039;&#039;;
  String getJob() {
    return _job;
  }

  void setJob(String job) {
    _job = job;
  }
}

class Human with GenderMixin, JobMixin {
  Human(String gender, String job) {
    setGender(gender);
    setJob(job);
  }

  void introduce() {
    print(&#039;من یک ${getGender()} هستم و شغل من ${getJob()} است.&#039;);
  }
}

void main() {
  var person1 = Human(&#039;مرد&#039;, &#039;مهندس&#039;);
  var person2 = Human(&#039;زن&#039;, &#039;پزشک&#039;);
  person1.introduce(); // خروجی: من یک مرد هستم و شغل من مهندس است.
  person2.introduce(); // خروجی: من یک زن هستم و شغل من پزشک است.
}پیاده‌سازی با آبسترکت کلاس:آبسترکت کلاس‌ها (Abstract Classes) در Dart نیز برای پیاده‌سازی ارث‌بری چندگانه قابل استفاده هستند و این امکان را فراهم می‌کنند که یک کلاس از چند کلاس آبسترکت به عنوان والد ارث‌بری کند. این امر امکان اشتراک ویژگی‌ها و متدها بین چند کلاس را بدون نیاز به ارث‌بری چندگانه فراهم می‌کند.abstract class Gender {
  String getGender();
  void setGender(String gender);
}

abstract class Job {
  String getJob();
  void setJob(String job);
}

class Human implements Gender, Job {
  String _gender = &#039;&#039;;
  String _job = &#039;&#039;;
  @override
  String getGender() {
    return _gender;
  }

  @override
  void setGender(String gender) {
    _gender = gender;
  }

  @override
  String getJob() {
    return _job;
  }

  @override
  void setJob(String job) {
    _job = job;
  }

  void introduce() {
    print(&#039;من یک ${getGender()} هستم و شغل من ${getJob()} است.&#039;);
}مشکلات در پیاده سازی ارث بری چندگانه :وراثت مکانیزمی است که به برنامه نویسان اجازه می دهد تا کلاس هایی را ایجاد کنند که بر اساس کلاس های موجود ساخته شده اند، پیاده سازی جدیدی را با حفظ رفتارهای مشابه مشخص کنند، از کدها استفاده مجدد کنند و به طور مستقل نرم افزار اصلی را از طریق کلاس ها و رابط های عمومی گسترش دهند. وراثت  علی رغم  سودمندی که  در برنامه نویسی شی گرا دارد , می تواند یکی از  موارد  پیچیده و مستعد خطا نیز باشد.مورد اول - Method overriding :این مورد زمانی اتفاق می افتد که یک زیر کلاس پیاده سازی خود را از طریق متد یا فانکشنی ارائه می کند که قبلاً توسط کلاس والد آن ارائه شده است.مورد دوم- Diamond problem :این زمانی اتفاق می افتد که دو ابر کلاس از یک کلاس یک کلاس پایه مشترک داشته باشند. این مشکل می تواند منجر به ابهام و سردرگمی در سلسله مراتب وراثت شود.مورد سوم- Method overloading :این مورد زمانی اتفاق می افتد که یک کلاس دو یا چند متد با نام یکسان اما پارامترهای متفاوت دارد.راه حل ها در پیاده سازی ارث بری چندگانه :برای جلوگیری از این مسائل، رعایت بهترین شیوه ها هنگام طراحی و اجرای برنامه های شی گرا مهم است. که در ادامه به چند مورد از آنها اشاره می کنیم .از سلسله مراتب ارثی عمیق اجتناب کنید:سلسله مراتب وراثت عمیق می تواند درک و نگهداری کد را دشوار کند. در عوض، سعی کنید سلسله مراتب ارثی خود را کم عمق و ساده نگه دارید.از ترکیب به جای وراثت استفاده کنید:به جای تلاش برای ارث‌بری از چند کلاس مختلف و ترتیب‌های پیچیده، از ترکیب کلاس‌ها به عنوان یک راه حل ساده و قابل درک استفاده کنید. شما می‌توانید از ترکیب به جای وراثت استفاده کنید و اشیاء پیچیده را از کلاس های ساده تری بسازید. این حالت می تواند انعطاف پذیرتر و راحت تر از وراثت قابل درک باشد.از اصل جایگزینی لیسکوف پیروی کنید:این اصل بیان می‌کند که اگر برنامه‌ای از یک کلاس پایه استفاده می‌کند، باید بتواند از هر یک از کلاس‌های مشتق شده خود بدون اطلاع از آن استفاده کند. به عنوان مثال، اگر یک کلاس پایه به نام &quot;حیوان&quot; داشته باشیم و دو کلاس مشتق شده به نام‌های &quot;شیر&quot; و &quot;گربه&quot; داشته باشیم، اگر این دو کلاس مشتق شده توانایی جایگزینی کلاس &quot;حیوان&quot; را داشته باشند و تمام ویژگی‌ها و توابع مورد نیاز برای این جایگزینی را داشته باشند، می‌توانیم از هر کدام از این دو کلاس بجای کلاس &quot;حیوان&quot; در برنامه‌ی خود استفاده کنیم. این می‌تواند به ما امکان افزودن انعطاف‌پذیری به برنامه و استفاده آسان از ارث‌بری چندگانه را بدهد.در مجموعه مقالات برنامه‌نویسی شیءگرا، مانند مقالات SOLID، برای هر یک از اصول برنامه‌نویسی شیءگرا (OOP)، مثال‌هایی با استفاده از زبان برنامه‌نویسی Dart خواهیم داشت که نمونه‌های صحیح و نمونه‌های نادرست پیاده‌سازی این اصول را نشان می‌دهیم.مقالات مرتبط:پیاده سازی OOP با کدهای دارت برای فریم ورک Flutter پیاده سازی ارث بری در OOP با کدهای دارت برای فریم ورک Flutter-بخش اول</description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Sun, 10 Sep 2023 23:39:59 +0330</pubDate>
            </item>
                    <item>
                <title>پیاده سازی ارث بری در OOP با کدهای دارت برای فریم ورک Flutter-بخش اول</title>
                <link>https://virgool.io/@software8686/%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D8%A7%D8%B1%D8%AB-%D8%A8%D8%B1%DB%8C-%D8%AF%D8%B1-oop-%D8%A8%D8%A7-%DA%A9%D8%AF%D9%87%D8%A7%DB%8C-%D8%AF%D8%A7%D8%B1%D8%AA-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-flutter-%D8%A8%D8%AE%D8%B4-%D8%A7%D9%88%D9%84-qjspwxg9nzhl</link>
                <description>ارث‌بری تکی (Single Inheritance)  ارث بری یا Inheritance در (OOP) چیست؟ارث‌بری (Inheritance) : در برنامه‌نویسی شیءگرا یا OOP مفهومی به نام ارث‌بری Inheritanceداریم.  مفهوم ارث‌بری به برنامه‌نویسان این امکان را می‌دهد که کلاس جدیدی (مثلا  کلاس دختر یا Girl) را بر اساس کلاس موجود  (مثلا  کلاس مادر یا Mom) تعریف کنند و ویژگی‌ها و رفتارهای کلاس مادر را به کلاس فرزند منتقل کنند. در واقع، کلاس فرزند می‌تواند از کلاس والد به عنوان یک پایه برای ساختار خود استفاده کند.مفهوم ارث‌بری دارای انواع مختلفی است:ارث‌بری تکی (Single Inheritance)ارث‌بری چندگانه (Multiple Inheritance)ارث‌بری چندسطحی (Multilevel Inheritance)ارث‌بری سلسله‌مراتبی (Hierarchical Inheritance)ارث‌بری ترکیبی (Hybrid Inheritance)ارث‌بری تکی (Single Inheritance) چیست؟در ارث‌بری تکی، تمرکز روی این است که فقط کلاس فرزند از یک کلاس والد ارث‌بری کند. به عنوان مثال، در کد زیر، کلاس &quot;دختر&quot; (Girl) از کلاس &quot;انسان&quot; (Human) ارث‌بری کرده است.مثالی که Single Inheritance را رعایت می کند:class Human {
  String name;
  int age;
  Human(this.name, this.age);
  void displayHumanInfo() {
    print(&#039;نام: $name&#039;);
    print(&#039;سن: $age سال&#039;);
  }
}
class Girl extends Human {
  Girl(String name, int age) : super(name, age);
  void displayGirlInfo() {
    print(&#039;من یک دختر هستم&#039;);
  }
}
void main() {
  Girl sara = Girl(&#039;سارا&#039;, 25);
  sara.displayHumanInfo();
  sara.displayGirlInfo();
}وقتی میخواهیم از کلاس Girl یک نمونه بسازیم ما باید age و name را برای کلاس  Girlمقدار دهی کنیم  در واقع داریم برای کلاس &quot;Human&quot; مقداردهی را انجام می‌دهیم و چون کلاس&quot;Girl&quot; از کلاس &quot;Human&quot; به عنوان کلاس پایه ارث‌بری  کرده است, مقادیر به کلاس Girl  نیز به ارث خواهد رسید .مثالی که Single Inheritance را نقض می کند:اگر بخواهیم مثالی داشته باشیم که این مورد را نقض کند میتوانیم به ارث بری چندگانه مراجعه کنیم . وقتی که یک کلاس فرزند از دو کلاس پدر به عنوان کلاس پایه به ارث ببرد. به عبارت دیگر، ارث‌بری از چند کلاس پدر به یک کلاس فرزند تضاد ایجاد می‌کند و این درست نیست.یا اینکه به مثال زیر نگاهی بیندازیم که اصل وراثت را به طرز صحیحی پیاده نکرده است:class Vehicle {
  void startEngine() {
    print(&#039;موتور راه‌اندازی شد.&#039;);
  }
  void stopEngine() {
    print(&#039;موتور متوقف شد.&#039;);
  }
  void accelerate() {
    print(&#039;سرعت افزایش یافت.&#039;);
  }
  void brake() {
    print(&#039;ترمز زده شد.&#039;);
  }
}
class Bicycle extends Vehicle {
  // Mistake!!! : تمام ویژگی‌ها و رفتارهای &amp;quotوسیله نقلیه&amp;quot توسط &amp;quotدوچرخه&amp;quot ارث‌بری شده است
}ایراد این مثال در این است که رفتارها و ویژگی های یک دوچرخه با یک ماشین متفاوت است ولی ارث بری کلاس Bicycle   از Vehicle منجر به رفتارها و ویژگی هایی برای دچرخه شده که برخی از آنها را ندارد.اگر بخواهیم این مثال را اصلاح کنیم میتوانیم به شکل زیر آن را تغییر دهیم:کد اصلاح شده ی مثالی که Single Inheritance را نقض میکرد:class Vehicle {
  void color(String selectedColor) {
    print(&#039;رنگ وسیله نقلیه: $selectedColor&#039;);
  }
  void name(String selectedName) {
    print(&#039;نام وسیله نقلیه: $selectedName&#039;);
  }
    void maxSpeedPerHour(int mph) {
    print(&#039;سرعت وسیله نقلیه: $mph&#039;);
  }
}
class Bicycle extends Vehicle {
  void pedal() {
    print(&#039;پدال زدن دوچرخه را حرکت داد&#039;);
  }
}

void main() {
  Bicycle bicycle = Bicycle();
  bicycle.name(&amp;quotTop Bicycle Brand&amp;quot);
  bicycle.color(&amp;quotred&amp;quot);
  bicycle.maxSpeedPerHour(25);
  bicycle.pedal();
 }در نسخه اصلاح شده، می‌توانید انتزاع بیشتری در کلاس Vehicle مشاهده کنید که ویژگی‌ها و رفتارهای نامناسب کلاس قبلی  Bicycle را از بین برده است.در مجموعه مقالات برنامه‌نویسی شیءگرا، مانند مقالات SOLID، برای هر یک از اصول برنامه‌نویسی شیءگرا (OOP)، مثال‌هایی با استفاده از زبان برنامه‌نویسی Dart خواهیم داشت که نمونه‌های صحیح و نمونه‌های نادرست پیاده‌سازی این اصول را نشان می‌دهیم.  مقالات مرتبط: پیاده سازی OOP با کدهای دارت برای فریم ورک Flutter پیاده سازی ارث بری در OOP با کدهای دارت برای فریم ورک Flutter-بخش اول</description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Fri, 08 Sep 2023 16:17:12 +0330</pubDate>
            </item>
                    <item>
                <title>پیاده سازی OOP با کدهای دارت برای فریم ورک Flutter</title>
                <link>https://virgool.io/@software8686/%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-oop-%D8%A8%D8%A7-%DA%A9%D8%AF%D9%87%D8%A7%DB%8C-%D8%AF%D8%A7%D8%B1%D8%AA-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-flutter-lnabaxicihgx</link>
                <description>برنامه نویسی شی گرا  یا Object-Oriented Programming  به اختصار (OOP)  برنامه نویسی شی گرا (OOP) چیست؟برنامه نویسی شی گرا  یا Object-Oriented Programming  که به اختصار (OOP) نامیده می شود ، یک الگوی برنامه نویسی پیشرفته است که تمرکز خود را بر روی استفاده از اشیاء برای نمایش و کنترل داده‌ها قرار می‌دهد. در OOP ، داده‌ها در داخل اشیاء قرار می‌گیرند . اشیا شامل ویژگی ها و توابع می باشند . ویژگی‌ها (Properties):ویژگی‌ها در OOP به داده‌های متعلق به یک شیء اشاره دارند. این داده‌ها ممکن است متغیرهایی باشند که وضعیت یک شیء را نشان می‌دهند.ویژگی‌ها به عنوان ویژگی‌های مخزنی برای داده‌های شیء عمل می‌کنند و معمولاً به صورت متغیرهای اعضای شیء تعریف می‌شوند.مقادیر ویژگی‌ها می‌توانند در زمان ایجاد شیء تنظیم شوند و یا در طول عمر شیء تغییر کنند.توابع (Methods):توابع در OOP عملکردهایی هستند که یک شیء می‌تواند انجام دهد. این عملکردها به شکل متدهای کلاس تعریف می‌شوند.توابع می‌توانند داده‌ها را تغییر دهند یا اطلاعاتی را از شیء بازگردانند.توابع معمولاً برای انجام عملیات‌های مختلفی بر روی ویژگی‌ها یا انجام تغییرات در وضعیت شیء استفاده می‌شوند.اشیاء با ویژگی‌ها (properties) و توابع (methods) تعریف می‌شوند. مفاهیم مهمی را ارائه می‌دهد که به توسعه دهندگان امکان می‌دهد کدها را به صورت ماژولار، قابل استفاده مجدد و قابل نگهداری ترتیب دهند.اصول برنامه نویسی شی گراانتزاع یا Abstraction : این مفهوم به این اشاره دارد که ما از چیزهای ساده‌تر برای نمایش پیچیدگی‌ها استفاده می‌کنیم. به عبارت دیگر، به جای دانستن نحوه کارکرد دقیق یک سیستم، از اشیاء، کلاس‌ها و متغیرها برای نمایش ساختار و داده‌های پایه‌ای پیچیده‌تر استفاده می‌شود. این ایده مهم است چرا که از تکرار و تکرار کد جلوگیری می‌کند.کپسوله سازی یا Encapsulation  : این مفهوم به معنای نگه‌داشتن داده‌ها درون یک کلاس و دسترسی به آن داده‌ها از طریق متدهای عمومی است. کپسوله سازی به ما این امکان را می‌دهد که داده‌ها و کد را درون یک کلاس محافظت کنیم و به طور ایمن از آنها استفاده کنیم. این به معنای قابلیت استفاده مجدد از اشیاء و کدها بدون نگرانی از امنیت داده‌ ی آنهاست.وراثت یاInheritance  : وراثت به برنامه‌نویسان اجازه می‌دهد که کلاس‌های جدیدی را با استفاده از ویژگی‌ها و رفتارهای کلاس‌های موجود ایجاد کنند. این به معنای اشتراک گذاری ویژگی‌ها و عملکردها بین کلاس‌ها است و امکان ساخت کلاس‌های جدید با استفاده از کد قبلی را فراهم می‌کند.پلی مورفیسم Polymorphism  : این اصل به شما امکان می‌دهد که یک عملیات را بر روی اشیاء مختلف اجرا کنید، به طوری که عملیات به تناسب نوع ویژگی‌های اشیاء تغییر کند. به این مورد نیاز داریم تا کدهایمان بتوانند به راحتی با انواع مختلف اشیاء کار کنند و نیازی به تغییرات بزرگ در کد نباشد. این اصل باعث می‌شود که کدها انعطاف‌پذیرتر باشند و بتوانیم آنها را به سادگی تغییر دهیم و تطبیق بخش‌های مختلف کد را با نیازهای جدید انجام دهیم.مفاهیم OOP به برنامه‌نویسان این امکان را می‌دهند که اشیاء و کدهایی را ایجاد کنند که قابل استفاده مجدد هستند و در عین حال امنیت داده‌ها را حفظ می‌کنند و نهایتا کدها را به صورت ماژولار نوشته شوند و از قابلیتReusability  برای جلوگیری از تکرار کدها استفاده کنند.در مجموعه مقالات برنامه‌نویسی شیءگرا، مانند مقالات SOLID، برای هر یک از اصول برنامه‌نویسی شیءگرا (OOP)، مثال‌هایی با استفاده از زبان برنامه‌نویسی Dart خواهیم داشت که نمونه‌های صحیح و نمونه‌های نادرست پیاده‌سازی این اصول را نشان می‌دهیم.مقالات مرتبط:پیاده سازی OOP با کدهای دارت برای فریم ورک Flutterپیاده سازی ارث بری در OOP با کدهای دارت برای فریم ورک Flutter-بخش اول</description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Fri, 08 Sep 2023 15:28:55 +0330</pubDate>
            </item>
                    <item>
                <title>اصل پنجم پیاده سازی SOLID با کدهای دارت برای فریم ورک Flutter</title>
                <link>https://virgool.io/flutter-community/%D8%A7%D8%B5%D9%84-%D9%BE%D9%86%D8%AC%D9%85-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-solid-%D8%A8%D8%A7-%DA%A9%D8%AF%D9%87%D8%A7%DB%8C-%D8%AF%D8%A7%D8%B1%D8%AA-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-flutter-gn3mu9bdpbp3</link>
                <description>Dependency Inversion Principle“اصل معکوس سازی وابستگی“ که آنرا  “اصل وارونگی وابستگی” هم می نامند برگرفته از  عبارات لاتین (Dependency Inversion Principle) یا به طور خلاصه (DIP) ، پنجمین  اصل از SOLID است و می گوید که:  “ماژول‌های سطح بالا نباید به ماژول‌های سطح پایین وابسته باشند” .در واقع،  ماژول ها به جای دسترسی مستقیم به منابعی که وابستگی ایجاد می کنند (مثلا کلاس ها) ، باید  از طریق interface ها، به آنها دسترسی داشته باشند. در این صورت  تغییرات کلاس های ما ، توسط interface ها به درون خود کلاس ها محدود می شود و لایه های بالاتر را درگیر تغییر نمی کنند.در وصف اصل وارونگی وابستگی ، گفته می شود که : اصل وارونگی وابستگی، ترکیبی ناب ، از اصل باز/بسته و اصل جایگزینی لیسکوف است.برای اینکه مفهوم را در مثال عملی کاملتر متوجه شویم آن را به دو شیوه صحیح و غلط آن پیاده سازی میکنیم.۱-  مثال زیر DIP را نقض می کند.فرض کنیم که قرار است  برای یک فروشگاه کتاب نرم افزاری کتابخوان بسازیم . از ما خواسته شده برای کاربری امکانات زیر را فراهم کنیم:۱- بخشی از کتاب مدنظر را ببیند.۲-از نظر سایر کاربران درباره کتاب مطلع شود.۳- اگر مایل بود، آن کتاب را به لیست کتابهای موجود در کتابخانه خود اضافه کند.برای شروع کلاس کتاب و کلاس  کتابخانه را به صورت زیر پیاده سازی می کنیم:class Book {
  void seeReviews() {
    // logic book reviews
  }

  void readSample() {
    // logic read book-sample
  }
}

class Library {
  late Book book;
  void addBook(Book book) {
    // logic add book
  }
}همانطور که مشاهده می کنید کلاس Book به ما اجازه خواندن sample و مشاهده review های کتاب را می دهد. همینطور کلاس Library برای ما امکان افزودن کتاب جدید را فراهم کرده است.به ظاهر کار تمام است اما مشکلی وجود دارد. کلاس سطح بالا (Library) به کلاسی سطح پایین  (Book) وابسطه شده است. به این ترتیب اصل وارونگی وابستگی نقض می شود.علاوه بر این اگر فروشگاه از ما بخواهد برای کاربران علاوه بر کتاب امکان استفاده از کتاب صوتی را  نیز فراهم کنیم به وضوح اصل دیگری از SOLID را هم نقض کرده ایم.( اصل باز/بسته )class AudioBook {
  void seeReviews() {
    // logic audio-book reviews
  }

  void listenSample() {
    // logic listen audio-book-sample
  }
}اکنون بیایید این بار با رعایت اصل اصل وارونگی وابستگی ، ایرادات برنامه فوق را برطرف کنیم.۲-  مثال زیر DIP  را رعایت می کند.برای حل مشکل،  یک interface برای کلاس های سطح پایین (کتاب و کتاب صوتی) ایجاد می کنیم. بدین منظور از یک interface به نام Product استفاده می کنیم، که باید هر دو کلاس آن را ایمپلمنت کنند.برای درک بهتر کد زیر را دنبال کنید:abstract class Product {
  void seeReviews();
  void getSample();
}

class Book implements Product {
  @override
  void seeReviews() {
    // logic book reviews
  }

  @override
  void getSample() {
    // logic book-sample
  }
}

class AudioBook implements Product {
  @override
  void seeReviews() {
    // logic audio-book reviews
  }

  @override
  void getSample() {
    // logic audio-book-sample
  }
}همانطور که کد ریفکتور شده کتابخانه را در ادامه خواهید دید، در کلاس Library به جای ارجاع مستقیم به Book و AudioBook از اینترفیس Product استفاده می کنیم. به این صورت امکان افزودن محصولات جدیدی (مثلا مجله و .. ) نیز فراهم می شود و کاربران می توانند آنها را به کتابخانه خود اضافه کنند.class Library {

    late Product product;

    void addProduct(Product product) {
          // logic add product (can be book or audio-book)
    }
}کد بالا از اصل جایگزینی Liskov نیز پیروی می کند، چون  Product را می توان با هر دو زیرشاخه آن بدون شکستن برنامه جایگزین کرد. همزمان، ما اصل وارونگی وابستگی را نیز پیاده‌سازی کرده‌ایم، زیرا در کد ریفکتور شده ، کلاس‌های سطح بالا به کلاس‌های سطح پایین وابسته نیستند.در مقالات بعدی جزئیات پیاده سازی هر بخش رو با کدهای دارت، با همدیگر بررسی می کنیم.مقدمه ای بر SOLID توضیح اصل اول : Single Responsibility Principleتوضیح اصل دوم : Open Closed Principle توضیح اصل سوم : Liskov Substitution Principleتوضیح اصل چهارم : Interface Segregation Principle توضیح اصل پنجم : Dependency Inversion Principle </description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Fri, 01 Apr 2022 13:33:33 +0430</pubDate>
            </item>
                    <item>
                <title>اصل چهارم  پیاده سازی SOLID با کدهای دارت برای فریم ورک Flutter</title>
                <link>https://virgool.io/flutter-community/%D8%A7%D8%B5%D9%84-%DA%86%D9%87%D8%A7%D8%B1%D9%85-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-solid-%D8%A8%D8%A7-%DA%A9%D8%AF%D9%87%D8%A7%DB%8C-%D8%AF%D8%A7%D8%B1%D8%AA-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-flutter-gxzmh12iqws5</link>
                <description>Interface Segregation Principle“اصل جداسازی اینترفیس ها “یا (Interface Segregation Principle) یا به طور خلاصه (ISP) ، چهارمین اصل از SOLID است و می گوید که: “کلاینت ها نباید مجبور شوند به اینترفیس هایی وابسته شوند که از آنها استفاده نمی کنند”. به زبانی بسیار ساده تر، باید اینترفیس را طوری طراحی کنیم که وقتی کلاسی از آن استفاده می کند، ملزم نباشد متدی که از آن استفاده نمی کند را پیاده‌سازی ( یا override ) کند.خیلی خلاصه تر و در یک جمله کوتاه  &quot;به چیزهایی که نیاز ندارید وابسته نباشید&quot;.برای اینکه مفهوم را در مثال عملی کاملتر متوجه شویم آن را به دو شیوه صحیح و غلط آن پیاده سازی میکنیم.۱-  مثال زیر ISP را نقض می کند.بیایید فرض کنیم که یک آژانس مسافرتی وجود دارد که شامل چندین روش برای رزور بلیط هواپیما می باشد. مثلا مشتریان آنلاین، تلفنی و حضوری دارد. همچنین برای رسیدگی به پرداخت های آنها، درگاه آنلاین برای (مشتریان آنلاین) و پرداخت از درگاه POS را برای (مشتریان حضوری و تلفنی) دارد. برای شروع یک اینترفیس یا کلاس abstract  به نام TravelAgencyInterface ایجاد می کنیم .abstract class TravelAgencyInterface {

  void acceptWalkInReserveTicket();

  void acceptOnlineReserveTicket ();

  void acceptTelephoneReserveTicket();

  void payOnline();

  void payByPOS();
}همانطور که مشاهده می کنید ما سه متد برای مشتری حضوری، مشتری تلفنی و مشتری آنلاین داریم. مشتری حضوری و تلفنی با دستگاه POS و مشتری آنلاین با استفاده از درگاه پرداخت آنلاین هزینه بلیط را پرداخت خواهند کرد.بیایید با ایمپلمنت کردن TravelAgencyInterface برای مشتریان آنلاین کار را شروع کنیم. نام کلاس را  OnlineCustomerImpl در نظر می گیریم .class OnlineCustomerImpl implements TravelAgencyInterface {

    @override
  void acceptWalkInReserveTicket() {
        // Not Applicable
    throw Exception();
  }

  @override
  void acceptOnlineReserveTicket() {
    // Logic for online customer
  }

  @override
  void acceptTelephoneReserveTicket() {
    // Not Applicable
    throw Exception();
  }

    void payOnline(){
      // Logic for online payment
    }

  void payByPOS(){
    // Not Applicable
    throw Exception(); 
  }
}از آنجایی که OnlineCustomerImpl   برای مشتریان آنلاین است، ما باید یک Exception برای متدهایی که برای مشتریان آنلاین نیست اجرا کنیم. در اینجاست که می‌توانیم نقض آشکار اصل جداسازی اینترفیس ها را مشاهده کنیم که علاوه بر آن اصل مسئولیت واحد را نیز زیر پا گذاشته است!اکنون بیایید این بار با رعایت اصل جداسازی اینترفیس ها ، ایرادات برنامه فوق را برطرف کنیم.۲-  مثال زیر ISP  را رعایت می کند.برای حل مشکل،  اقدام به کوچک تر کردن اینترفیس OnlineCustomerImpl کرده و آن را به دو اینترفیس  OrderInterface  و PaymentInterface تقسیم می کنیم.abstract class OrderInterface  {
  void reserveOrder();
}

abstract class PaymentInterface {
  void payForOrder();
}حالا، برای هر سه نوع مشتری، اینترفیس های جدید را ایمپلمنت می کنیم:class OnlineCustomerImpl implements OrderInterface, PaymentInterface {

  @override
  void reserveOrder() {
    // logic for online reserve
  }

  @override
  void payForOrder() {
    // logic to do online payment
  }
}

class WalkInCustomerImpl implements OrderInterface, PaymentInterface {
  @override
  void reserveOrder() {
    // logic for in-person reserve
  }

  @override
  void payForOrder() {
    // logic to do pos payment
  }
}

class TelephoneCustomerImpl implements OrderInterface, PaymentInterface {
  @override
  void reserveOrder() {
    // logic for telephonic reserve
  }

  @override
  void payForOrder() {
    // logic to do pos payment
  }
}از مزایایی که اصل جداسازی اینترفیس ها برای ما فراهم کرده میتوانیم به موارد زیر اشاره کنیم : ۱- افزایش خوانایی کد۲- پیاده سازی آسان تر۳-نگهداری آسان تر۴-سازماندهی بهتر کد۵- نیازی نیست از throw Exception های بیهوده استفاده کنید.نکته پایانی اینکه، هر دو اصل جداسازی اینترفیس ها و اصل تک مسئولیتی تقریباً یک هدف دارند: اطمینان از اجزای نرم افزاری کوچک، متمرکز و بسیار منسجم.و تفاوت آنها نیز در این است که، اصل تک مسئولیتی مربوط به کلاس ها است، در حالی که اصل جداسازی اینترفیس ها مربوط به اینترفیس ها می باشد.در مقالات بعدی جزئیات پیاده سازی هر بخش رو با کدهای دارت، با همدیگر بررسی می کنیم.مقدمه ای بر SOLID توضیح اصل اول : Single Responsibility Principleتوضیح اصل دوم : Open Closed Principle توضیح اصل سوم : Liskov Substitution Principleتوضیح اصل چهارم : Interface Segregation Principle توضیح اصل پنجم : Dependency Inversion Principle </description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Thu, 31 Mar 2022 22:04:06 +0430</pubDate>
            </item>
                    <item>
                <title>اصل سوم پیاده سازی SOLID با کدهای دارت برای فریم ورک Flutter</title>
                <link>https://virgool.io/flutter-community/%D8%A7%D8%B5%D9%84-%D8%B3%D9%88%D9%85-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-solid-%D8%A8%D8%A7-%DA%A9%D8%AF%D9%87%D8%A7%DB%8C-%D8%AF%D8%A7%D8%B1%D8%AA-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-flutter-u8fwdfn1sqgv</link>
                <description>Liskov Substitution Principle“اصل جایگزینی لیسکوف“ یا (Liskov Substitution Principle) یا به طور خلاصه (LSP) سومین اصل از SOLID است و می گوید که: &quot;انواع مشتق شده باید کاملاً قابل جایگزینی برای انواع پایه خود باشند&quot; برای درک بهتر آن به مثال زیر توجه کنید.فرض کنید کلاسی به نام مشتری داریم و بیزینس ما چندین نوع مشتری دارد(مثلاً مشتری تلفنی و مشتری عبوری و مشتری آنلاین) . برای این منظور کلاسی پایه به اسم Customer می سازیم و همه انواع مشتری ها را ملزم به ارث بری از کلاس Customer می کنیم .در این میان ممکن است برای هر نوع مشتری رفتاری خاص تعریف کنیم. اما مشتری ها بابت ارث بری از کلاس Customer می بایست به جز رفتار مخصوص خود همگی قادر به ارایه رفتاری مشابه والد خود باشند و اگر قادر نباشند  (مثلاً استثنایی مانع شده باشد) اصل لیسکوف رعایت نشده است.بنابراین، همه Sub کلاس‌ها باید به همان شیوه کلاس‌های پایه خود عمل کنند. عملکرد خاص Sub کلاس ممکن است متفاوت باشد، اما باید با رفتار مورد انتظار کلاس پایه مطابقت داشته باشد.نهایتا باید کلاس پایه  بتوانند با Sub کلاس‌ خود جایگزین شوند. به عبارتی دیگر کلاس والد بتوانند جایگزین کلاس فرزند خود شود.برای اینکه مفهوم را در مثال عملی کاملتر متوجه شویم آن را به دو شیوه صحیح و غلط آن پیاده سازی میکنیم.۱-  مثال زیر LSP  را نقض می کند.بیایید یک مثال جدید بزنیم، فرض کنید که یک فروشگاه از ما میخواهد برای آن یک سیستم ثبت پرداخت پیاده سازی کنیم.  بنابر این، ما برای شروع یک کلاس Payment ایجاد می کنیم .class Payment {
  late int customerID;
  late double orderCost;

  void getMoneyByCrashier() {
    // logic code for payment in store.
  }
}این فروشگاه قصد دارد پرداخت مشتریان حضوری را به صورت تحویل به صندوقدار داشته باشد. بنابراین، ما یک Sub کلاس جدید به نام  InStorePayment  از کلاس  Payment ایجاد می‌کنیم.class InStorePayment extends Payment {
  @override
  void getMoneyByCrashier() {
    // logic code for payment in store.
  }
}بعد از مدتی، فروشگاه از ما می‌خواهد که برای مشتریان تلفنی نیز سیستم پرداخت را توسعه دهیم. اکنون، ما یک Sub کلاس جدید به نام  TelephonePayment از کلاس Payment ایجاد می‌کنیم. اما، وقتی می‌خواهیم متد () getMoneyByCrashier را پیاده سازی کنیم، متوجه می‌شویم که مشتریان تلفنی نمی‌توان مبلغ را به صندوقدار تحویل دهند!class TelephonePayment extends Payment {
  @override
  void getMoneyByCrashier() {
    /* Can&#039;t be implemented since
     * The Customer is not in Store.
    */
  }
}اکنون که با مشکل از نزدیک روبرو شدیم و درک بهتری از موضوع داریم، بیایید این بار با رعایت اصل جایگزینی لیسکوف ، ایرادات برنامه فوق را برطرف کنیم.۲-  مثال زیر LSP  را رعایت می کند.برای حل مشکل، باید سلسله مراتب وراثت را اصلاح کنیم .بیایید یک لایه اضافی تعریف کنیم که کمک کند انواع پرداخت ها را بهتر مدیریت کنیم. کلاس‌های OfflinePayment و OnlinePayment وظایف سوپر کلاس  Payment را بین خود تقسیم خواهند کرد. همچنین متد ()getMoneyByCrashier را به OfflinePayment  منتقل می کنیم و در مرحله بعد، یک متد ()getMoneyOnlineOptions برای کلاس OnlinePayment ایجاد می کنیم.  در نهایت، کدهای مربوطه به شکل زیر خواهد بود.class Payment {
  late int customerID;
  late double orderCost;
}

abstract class OfflinePayment extends Payment {
  void getMoneyByCrashier();
}

abstract class OnlinePayment extends Payment {
  void getMoneyOnlineOptions();
}

class TelephonePayment extends OnlinePayment {
  @override
  void getMoneyOnlineOptions() {
    // logic code for payment online.
  }
}

class InStorePayment extends OfflinePayment {
  @override
  void getMoneyByCrashier() {
    // logic code for payment in store.
  }
}همان طور که مشاهده می کنید، اکنون می‌توانیم از هر Sub کلاسی به جای Super کلاس آن استفاده کنیم. علاوه بر این کد شما : قابلیت استفاده مجدد را دارد ، نگهداری از آن ساده تر است و منجر به کاهش Coupling (یا به عبارتی وابستگی بین ماژول ها) شده است.در مقالات بعدی جزئیات پیاده سازی هر بخش رو با کدهای دارت، با همدیگر بررسی می کنیم.مقدمه ای بر SOLID توضیح اصل اول : Single Responsibility Principleتوضیح اصل دوم : Open Closed Principle توضیح اصل سوم : Liskov Substitution Principleتوضیح اصل چهارم : Interface Segregation Principle توضیح اصل پنجم : Dependency Inversion Principle </description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Thu, 31 Mar 2022 12:57:36 +0430</pubDate>
            </item>
                    <item>
                <title>اصل دوم پیاده سازی SOLID با کدهای دارت برای فریم ورک Flutter</title>
                <link>https://virgool.io/flutter-community/%D8%A7%D8%B5%D9%84-%D8%AF%D9%88%D9%85-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-solid-%D8%A8%D8%A7-%DA%A9%D8%AF%D9%87%D8%A7%DB%8C-%D8%AF%D8%A7%D8%B1%D8%AA-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-flutter-jnsovmoq5uk0</link>
                <description>Open Closed Principle“اصل باز/بسته “یا (Open Closed Principle) یا به طور خلاصه (OCP) دومین اصل از SOLID است و می گوید که: اجزای نرم افزار ( اعم از کلاس ها، ماژول ها و توابع) باید برای توسعه باز باشد، اما برای اصلاح بسته شود.&quot;باز برای توسعه&quot;  به این معنی است که باید کلاس های خود را طوری طراحی کنید که با توجه به نیازهای جدید، قابلیت های جدید بتواند اضافه شود.&quot;بسته برای اصلاح&quot; به این معنی است که وقتی کلاسی را توسعه دادید، هرگز نباید آن را تغییر دهید، مگر اینکه برای اصلاح جزئی اشکالات باشد.به نظر می رسد این دو بخش از پایه متناقض هم باشند با این حال، اگر از ابتدا کلاس‌ها و وابستگی‌هایشان را به درستی ساختار بندی کنید، می‌توانید بدون ویرایش کد موجود، عملکرد جدید مدنظر را اضافه کنید.راه های گسترش کلاس شامل  ارث بری از کلاس و همینطور توسعه یا بازنویسی Method های مورد نیاز است و شیوه کار به طور کلی این است که شما به جای استفاده از کلاس‌های پایه تان، با refer دادن به  abstract کلاس ها برای ایجاد وابستگی‌ها کارتان را انجام می دهید. ما می‌توانیم با ایجاد کلاس‌های جدید که روابط را پیاده‌سازی می‌کنند، عملکرد جدید را اضافه کنیم.پیاده سازی به این روش، احتمال ایجاد مشکلات جدید در کدها را کاهش می دهد و منجر به تولید  برنامه ای قوی تر می شود.برای اینکه مفهوم را در مثال عملی کاملتر متوجه شویم  آن را به دو شیوه صحیح و غلط آن پیاده سازی میکنیم.۱- مثال زیر کدی که OCP را نقض می کند.قرار است برنامه ای بنویسیم که مساحت اشکال مختلف را محاسبه کند.  یک کلاس برای  مستطیل که دارای 2 ویژگی طول و عرض است ایجاد می کنیم. نام کلاس را Rectangle  میگذاریم.class Rectangle {
  final double length;
  final double width;
  Rectangle(this.width, this.length);
}علاوه بر این، ما یک کلاس برای محاسبه مساحت این مستطیل ایجاد می کنیم که دارای یک متد محاسبه ()RectangleArea  است که Rectangle را به عنوان پارامتر ورودی می گیرد و مساحت آن را محاسبه می کند.class AreaCalculator {
  double calculateRectangleArea(Rectangle rectangle) {
    return rectangle.length * rectangle.width;
  }
}تا اینجا که خوب بود. حالا فرض کنید باید برای شکل دوم (که دایره است) نیز، کد مربوطه را بنویسیم. بنابراین، ما سریع یک کلاس Circle  با ویژگی radius (به عنوان شعاع) ایجاد می کنیم.class Circle {
  final double radius;
  Circle(this.radius);
}سپس کلاس AreaCalculator را تغییر می دهیم تا محاسبات دایره را از طریق  یک متد جدید به نام  ()calculatCircleArea انجام دهد.class AreaCalculator {
  double calculateRectangleArea(Rectangle rectangle) {
    return rectangle.length * rectangle.width;
  }

  double calculateCircleArea(Circle circle) {
    return (3.14159265359) * circle.radius * circle.radius;
  }
}بد شد ! اگر توجه داشته باشید اشکالاتی در راه حل ما در بالا وجود دارد.فرض کنید یک شکل جدید مثلا پنج ضلعی داریم. در آن صورت، ما دوباره کلاس AreaCalculator را اصلاح می کنیم. همانطور که انواع شکل ها بیشتر می شوند، با تغییر مداوم AreaCalculatorو هر کلاسی که از استفاده می کند، باید قسمت هایی از برنامه را که حاوی AreaCalculator هستند، ریفکتور کنند، باعث شلوغ تر و پیچیده تر  شدن برنامه می شود. در نتیجه، کلاس AreaCalculator  هر بار که شکل جدیدی می‌آید، باید اصلاح می‌شود. بنابراین، این برنامه ای که نوشتیم برای اصلاح بسته نیست.اکنون که با مشکل از نزدیک روبرو شدیم و درک بهتری از موضوع داریم،  بیایید این بار با رعایت اصل باز/بسته، ایرادات برنامه فوق را برطرف کنیم.۲- مثال: کدی که OCP را رعایت می کند.اول از همه، ما کد را توسعه پذیر می کنیم. برای این کار ابتدا باید یک شکل از نوع پایه تعریف کنیم و اینترفیس شکل دایره و مستطیل را پیاده سازی کنیم. کد زیر را مشاهده کنید!abstract class Shape {
  double calculateArea();
}

class Rectangle implements Shape {
  late double length;
  late double width;

  @override
  double calculateArea() {
    return length * width;
  }
}

class Circle implements Shape {
  late double radius;

  @override
  double calculateArea() {
    return (3.14159265359) * radius * radius;
  }
}همانطور که قبلا گفتیم، یک شکل اصلی وجود دارد به نام کلاس Shape که سایر اشکال از آن ارث بری می کنند. کلاس Shape دارای یک متد انتزاعی محاسبه ()calculateArea است. دایره و مستطیل هر دو پیاده سازی خاص خود را برای ()calculateArea دارند . اگر در آینده بخواهیم مساحت اشکال دیگری مانند مثلث، مربع و غیره را محاسبه کنیم، این کار بدون تغییر  کلاس Shape امکان پذیر خواهد بود.نکته آخر Consumer یا استفاده کننده نهایی این اشکال است. استفاده کننده نهایی، کلاس AreaCalculator خواهد بود که اکنون به این شکل است.class AreaCalculator {
  double calculateShapeArea(Shape shape) {
    return shape.calculateArea();
  }
}این کلاس AreaCalculator اکنون به طور کامل ایرادات مثال قبل را برطرف می کند و یک راه حل Clean ارائه می دهد که به اصل باز-بسته پایبند است.سوال : مزایای استفاده از اصل بسته باز چیست؟جواب: توسعه پذیری آسان تر / نگهداری آسان تر / انعطاف پذیریسوال : محدودیت های Open Closed Principle چیست؟جواب: زمانی که در کد تغییری را به عنوان مورد جدید اضافه می کنیم، باید قبل و بعد از آن ,  Unit Test را انجام دهیم  که از صحت اجرای سایر کدها مطمئن شویم.سوال : الگوهای طراحی که از اصل بسته باز پیروی می کنند کدامند؟جواب: چندین الگوی طراحی وجود دارد که به ما کمک می کند تا کد را بدون تغییر آن گسترش دهیم. به عنوان مثال، الگوی Decorator به ما پیشنهاد می دهد که از اصل Open Close پیروی کنیم. علاوه بر این، ممکن است از روش Factory، الگوی Strategy  و الگوی Observer  برای طراحی برنامه‌ای با حداقل تغییرات در کد موجود استفاده کنیم.در مقالات بعدی جزئیات پیاده سازی هر بخش از Solid با کدهای دارت رو با همدیگر بررسی می کنیم.مقدمه ای بر SOLID توضیح اصل اول : Single Responsibility Principleتوضیح اصل دوم : Open Closed Principle توضیح اصل سوم : Liskov Substitution Principleتوضیح اصل چهارم : Interface Segregation Principle توضیح اصل پنجم : Dependency Inversion Principle </description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Wed, 30 Mar 2022 16:24:31 +0430</pubDate>
            </item>
                    <item>
                <title>اصل اول پیاده سازی SOLID با کدهای دارت برای فریم ورک Flutter</title>
                <link>https://virgool.io/flutter-community/%D8%A7%D8%B5%D9%84-%D8%A7%D9%88%D9%84-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-solid-%D8%A8%D8%A7-%DA%A9%D8%AF%D9%87%D8%A7%DB%8C-%D8%AF%D8%A7%D8%B1%D8%AA-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9flutter-n5dnyu6h37hv</link>
                <description>Single Responsibility Principleاصل تک مسولیتی “یا (Single Responsibility Principle) اولین اصل از SOLID است و می گوید که : یک کلاس باید بر روی یک هدف واحد تمرکز داشته باشد و به یک نگرانی مشخص رسیدگی کند. یعنی هر کلاس یا ساختار مشابه در کد شما باید فقط یک کار برای انجام دادن داشته باشد.اگر کلاسهای شما چندین مسئولیت را به عهده بگیرند، دیگر مستقل از یکدیگر نیستند و شما در مقابل تغییرات باید کلاس های بیشتری را ویرایش کنید. و در نتیجه در مقابل یک تغییر کار جانبی بیشتری انجام می دهید و زمان بیشتری مصرف می کنید و پیچیدگی کد شما بیشتر می شود.بنابراین، بهتر است با اطمینان از اینکه هر کلاس فقط یک مسئولیت دارد، از این مشکلات جلوگیری کنید.فرض کنیم نرم افزاری داریم که با درخواست های تغییر مداوم مواجه است. شاید احساس کنید ساده‌ترین و سریع‌ترین روش، اعمال تغییرات در کلاس ها و یا اضافه کردن یک متد به کلاس مربوطه باشد. اما این کار در اغلب باعث ایجاد کلاس هایی با مسئولیت بیشتر می شود و نگهداری نرم افزار را بیش از پیش دشوارتر می کند.بیایید با یک مثال عملی قضیه را از نزدیک و بهتر درک کنیم.فرض کنید ما در حال نوشتن یک نرم افزار برای یک مشاور املاک هستیم. ما یک کلاس Home ایجاد خواهیم کرد که به مشاور اجازه می دهد تعداد اتاق ها و قیمت و آدرس را از هر خانه دریافت و تنظیم کند و خانه را از Repository جستجو کند.کد ابتدایی به این شکل خواهد شد:class Home {
   String _address;
   int _cost;

  Home(this._address, this._cost);

  get getAddress =&gt; _address;
  get getCost =&gt; _cost;

  set setAddressy(String address) {
    _address = address;
  }

  set setCost(int cost) {
    _cost = cost;
  }

  void searchHome() {
    //logic to search home goes here
  }
  
}با این حال، کد بالا اصل مسئولیت واحد را نقض می کند، زیرا کلاس Home دو مسئولیت دارد.ابتدا، ویژگی‌های (قیمت و آدرس) مربوط به خانه را تنظیم می‌کند. دوم اینکه خانه را در Repository جستجو می کند. متدهای Setter، شی Home را تغییر می دهند، که ممکن است زمانی که بخواهیم همان خانه را در Repository جستجو کنیم، مشکل ایجاد کند.برای اعمال اصل تک مسولیتی، باید این دو مسئولیت را از هم جدا کنیم. در کد ریفکتور شده، کلاس Home فقط مسئول دریافت و تنظیم خصوصیات شی Home خواهد بود. به کد زیر دقت کنید:class Home {
   String _address;
   int _cost;

  Home(this._address, this._cost);

  get getAddress =&gt; _address;
  get getCost =&gt; _cost;

  set setAddressy(String address) {
    _address = address;
  }

  set setCost(int cost) {
   _cost = cost;
  }
}

class RepositoryView {
   final Home home;
  RepositoryView(this.home);

  void searchHome() {
    //logic to search home goes here
  }
}ما کلاس خانه اولیه را که دو مسئولیت داشت به دو کلاس تقسیم کردیم که هر کدام مسئولیت خاص خود را دارند.در مقالات بعدی جزئیات پیاده سازی هر بخش از سالید با کدهای دارت رو با همدیگر بررسی می کنیم.مقدمه ای بر SOLID توضیح اصل اول : Single Responsibility Principleتوضیح اصل دوم : Open Closed Principle توضیح اصل سوم : Liskov Substitution Principleتوضیح اصل چهارم : Interface Segregation Principle توضیح اصل پنجم : Dependency Inversion Principle </description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Wed, 30 Mar 2022 04:05:05 +0430</pubDate>
            </item>
                    <item>
                <title>پیاده سازی SOLID با کدهای دارت برای فریم ورک Flutter</title>
                <link>https://virgool.io/flutter-community/%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-solid-%D8%A8%D8%A7-%DA%A9%D8%AF%D9%87%D8%A7%DB%8C-%D8%AF%D8%A7%D8%B1%D8%AA-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%81%D8%B1%DB%8C%D9%85-%D9%88%D8%B1%DA%A9-flutter-qbhr8vygdm4z</link>
                <description>SOLIDدر دنیای برنامه نویسی شی گرا ( OOP) ، دستورالعمل ها، الگوها یا اصول طراحی بسیاری وجود دارد. پنج مورد از این اصول معمولا با هم گروه بندی می شوند و با مخفف SOLID شناخته می شوند. در حالی که هر یک از این پنج اصل چیزی خاص را توصیف می‌کنند، اما با هم همپوشانی دارند، به طوری که اتخاذ یکی از آنها متضمن یا منجر به پذیرش دیگری می‌شود.اصول SOLID ما را تشویق می کند تا نرم افزار قابل نگهداری، قابل فهم و انعطاف پذیرتری ایجاد کنیم . در نتیجه، همانطور که برنامه های ما در اندازه بزرگ می شوند، می توانیم پیچیدگی آنها را کاهش دهیم و علاوه بر سرعت بالاتر توسعه، تجربه راحت تری داشته باشیم !وقتی توسعه‌دهندگان بدون استفاده از SOLID روی طراحی برنامه ای کار می‌کنند، می‌توانند مشکلات عمده ای  را برای توسعه‌دهندگان آینده که روی پروژه کار می‌کنند ایجاد کنند و زمان زیادی از پروژه هدر برود و موفقیت بالقوه برنامه‌ای را که در حال توسعه هستند محدود کنند.حال سوال اینجاست که :   اگرسالید را رعایت نکنیم چه میشود ؟جواب به طور خلاصه این هست : باعث حالت &quot;Code Rot&quot; یا &quot;کد پوسیده&quot; میشود .که شامل چهار آفت  می شود که در ادامه به ترتیب توضیح خواهم داد که چه هستند.۱- سختی  یا Rigidity : تغییری کوچک باعث می شود کل سیستم بازسازی شود.۲- شکننده بودن یا Fragility : تغییرات در یک ماژول باعث می شود که ماژول های نامرتبط  به هم رفتار نادرست داشته باشند.۳- غیر قابل جابجا کردن یا Immobility : اجزای داخلی یک ماژول را نمی توان استخراج کرد و در محیط های جدید دوباره استفاده کرد. به عنوان مثال، اگر ماژول ورود به سیستم یک برنامه کاربردی را نمی توان در سیستم کاملاً متفاوت استفاده کرد، این ماژول اصطلاحا” immobile  یا غیر قابل جابجا کردن است که ناشی از اتصال و وابستگی بین ماژول های مختلف است.۴- چسبندگی یا Viscosity : مراحل ساخت و Test برنامه دشوار و Debug آن زمان زیادی می برد . به خصوص زمانی که حتی انجام یک تغییر ساده پرهزینه است و شما را ملزم به ایجاد تغییرات در چندین قسمت یا لایه از Code می کند.داستان SOLID به سال 2000 برمیگردد، وقتی که برای اولین بار توسط رابرت سی. مارتین در مقاله خود با عنوان اصول طراحی و الگوهای طراحی،  آن را مطرح کرد. این مفاهیم بعداً توسط Michael Feathers ساخته شد، که ما را با مخفف SOLID آشنا کرد. و در سالهای گذشته، این 5 اصل، دنیای برنامه نویسی شی گرا را متحول کرده و روش نوشتن نرم افزار را تغییر داده است.کد شما  همواره نیاز به ریفکتور دارد.  نرم افزار شما باید بتواند با نیازهای در حال تغییر مشتری شما هماهنگی داشته باشد. از این رو همیشه این امکان وجود دارد که کد نوشته شده را تغییر دهید و آن را بهتر کنید.  چه شما روی پروژه باشید یا نوبت به توسعه دهنده بعدی رسیده باشد. از این رو اهمیت SOLID پررنگ تر می شود.هنگامی که از تمام اصولS.O.L.I.D به صورت ترکیبی استفاده می کنید، توسعه نرم افزاری که به راحتی قابل مدیریت باشد، برای شما و سایر توسعه دهندگان به مراتب آسان تر می شود.در مقالات بعدی ( که لینکهای آن را در ادامه می بینید ) ، جزئیات پیاده سازی هر بخش رو با کدهای دارت، با همدیگر بررسی می کنیم.مقدمه ای بر SOLID توضیح اصل اول : Single Responsibility Principleتوضیح اصل دوم : Open Closed Principle توضیح اصل سوم : Liskov Substitution Principleتوضیح اصل چهارم : Interface Segregation Principle توضیح اصل پنجم : Dependency Inversion Principle </description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Tue, 29 Mar 2022 22:03:01 +0430</pubDate>
            </item>
                    <item>
                <title>چک لیست یک برنامه نویس Clean Code</title>
                <link>https://virgool.io/CodeLovers/%DA%86%DA%A9-%D9%84%DB%8C%D8%B3%D8%AA-%DB%8C%DA%A9-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3-clean-code-pbdydgcljvzu</link>
                <description>نوشتن کد تمیزکد تمیز یا Clean Code یعنی کدی که  قابل توسعه و خوانا باشد . تبدیل شدن به یک برنامه نویس کد تمیز ، شامل رعایت موارد زیر است.1- جهت ماژول بندی بهتر طول توابع نباید بیش از 25 تا 30 خط شود.2- سعی کنید گویا ترین نام را برای اجزای برنامه تان انتخاب کنید.3- از مدیریت ورودی توابع (نهایتا 4 مورد), جهت پوشش تک مسولیتی بهره بگیرید.4- از نوشتن کلاس های بزرگ در برنامه تان خودداری کنید.5- در استفاده از کتابخانه ها یا برنامه های Third-Party نهایت دقت را به کار ببرید.6- دیزاین پترن ها را بشناسید و از آن ها استفاده کنید.7- همیشه نفر بعدی که از کد شما استفاده می‌کند را مد نظر بگیرید.8- یاد بگیرید کد های دیگران را بخوانید.9- ساده ترین و کامل ترین راه را برای حل مشکل استفاده کنید.10- سعی کنید، آنقدر خوب کد بنویسید که به کامنت نیازی نداشته باشید.11- رعایت قوانین SOLID مهم تر از استفاده از design pattern ها می باشد.12- از تکرار کدهای مشابه یا اصطلاحا&quot; Duplicate Code بپرهیزید.13- بخش های مرتبط را encapsulate کنید.14- قانون تک مسولیتی بودن را سرلوحه کد نویسی کنید.15- قانون Open/Closed را برای راحتی آینده خود رعایت کنید.16- با رعایت Dependency Inversion توسعه پذیری برنامه تان را متحول کنید.17- از تعداد زیادی if , برای پوشش چند مسولیتی بودن  پرهیز کنید.18- در تمام کد از یک سری از قوانین و الگو ها استفاده کنید.19- روزانه یا هفتگی کد خود را ریفکتور کنید.20- قبل کد زدن آنرا دوبار مرور کنید (روی برگه طراحی و Review کنید) .21- برای کد خود تست بنویسید.</description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Wed, 31 Mar 2021 13:33:17 +0430</pubDate>
            </item>
                    <item>
                <title>توضیح اصول پنج گانه برنامه نویسی بدون یک خط کد</title>
                <link>https://virgool.io/FlutterDeveloper/%D8%A7%D8%B5%D9%88%D9%84-solid-%D8%A8%D9%87-%D8%B2%D8%A8%D8%A7%D9%86-%D8%A8%D8%B3%DB%8C%D8%A7%D8%B1-%D8%B3%D8%A7%D8%AF%D9%87-wbe2dmacxlz3</link>
                <description>اصول S.O.L.I.D  به زبان بسیار سادهدر این مقاله شما بسیار سطحی و خلاصه شده با اصول سالید آشنا خواهید شد،  اگر با کلیات SOLID آشنایی ندارید پیشنهاد می کنم ابتدا مقاله مقدمه ای بر SOLID را مطالعه کنید.اصل اول :  (SRP) The Single Responsibility Principle  این اصل می‌خواهد بگوید که هر کلاسی، هر تابعی یا هر موجودیت دیگری فقط باید یک مسئولیت داشته باشد. چند مسولیتی ناقض این اصل است.(مشاهده توضیح بیشتر)اصل دوم:  The Open-Closed Principle (OCP)هر موجودیت نرم‌افزاری اعم از کلاس، تابع، ماژول و … باید برای توسعه باز و برای اصلاح بسته باشد. یعنی برنامه ی  ما  بدون اینکه متد یا کلاسی را ویراش کنیم بتواند توسعه یابد .مثال : استفاده از اینترفیس برای تعیین متغییر مشترک بین آبجکت ها  جهت استفاده در کلاس یا متد نهایی و در نهایت هیچ وقت متد نهایی ویرایش نخواهد شد . به طوری که  با آبجکت جدید نیز  بتواند کارش را انجام دهد.(مشاهده توضیح بیشتر)اصل سوم :  (LSP) The Liskov Substitution Principleاگر S زیرکلاسی از T باشد، اشیائی از نوع T را باید بتوان با اشیائی از نوع S جایگزین کرد.مثال:کلاس  والد باید به نحوی شکسته شوند که بتوان شیء ای از نوع والد جایگزین فرزندش شود.این شکستن میتواند یک فرزند-دیگر باشد که ویژگی خاصی دارد که پدرش ندارد.آنگاه این فرزند-دیگر  اگر فرزند-جدید داشته باشد میتواند شیء ای از خودش را جایگزین فرزند-جدید کند.(مشاهده توضیح بیشتر)اصل چهارم  :  (ISP) The Interface Segregation Principleکلاینت‌ها نباید به متدهایی وابسته باشند که نیازی به آن‌ها ندارند.مثال: اینترفیس های بزرگ با چندین متد به اینترفیس هایی کوچک‌تر شکسته شوند تا کلاینت ها  به واسطه فراخوانی متدهای بلا استفاده شلوغ نشوند.(مشاهده توضیح بیشتر)اصل پنجم :  The Dependency Inversion Principle (DIP)ماژول‌های سطح بالای برنامه نباید به ماژول‌های سطح پایین آن وابسته باشند .مثال: ساخت شیء از یک کلاس در کلاس دیگر ایجاد وابستگی می کند . برای رفع وابستگی از اینترفیس استفاده میکنیم به نحوی که کلاس‌هایی که لازمشان داریما را از یک اینترفیس ایمپلمنت میکنیم و در کلاس اصلی بجای ساخت شیء از کلاس‌ها , یک شیء از اینترفیس میسازیم و با متدی مشخص میکنیم که کدام کلاس را برای ادامه مدنظر  داریم.(مشاهده توضیح بیشتر)</description>
                <category>اسماعیل احمدی پور</category>
                <author>اسماعیل احمدی پور</author>
                <pubDate>Sat, 27 Mar 2021 22:24:32 +0430</pubDate>
            </item>
            </channel>
</rss>