<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های miiimkaaaf</title><link>https://virgool.ir/feed/@miiimkaaaf</link><description></description><language>fa</language><pubDate>2026-11-13 01:10:26</pubDate><image><url>https://virgool.ir/images/default-avatar.jpg</url><title>miiimkaaaf</title><link>https://virgool.ir/@miiimkaaaf</link></image><item><title>توضیحاتی مختصر راجع به CI/CD</title><link>https://virgool.ir/@miiimkaaaf/توضیحاتی-مختصر-راجع-به-cicd-ek1obdvdc07f</link><description>سرواژه CI/CD درواقع پلی است که فاصله بین توسعه پروژه و عملکرد آن و تیم های مربوطه را کاهش میدهد. این کار با استفاده از اتوماتیک کردن فرایند های مربوط به ساخت (Build) و تست کردن پروژه و قراردادن آن برروی سرور اصلی (Deployment) انجام می شود.سرواژه‌های CI و CD دقیقا یعنی چی؟سرواژه CI یا Continuous Integration یک روش توسعه نرم افزار است که در آن تا حدامکان سعی می شود که تغییراتی که توسط توسعه دهنده ها در کد اعمال میشه را با کدی که در ریپازیتوری اصلی وجود داره مرج بشود. (چندین بار در روز)سرواژه CD یا Continuous Delivery درواقع یک لایه برروی CI هست که به دنبال این است که تمام پروسه انتشار نسخه جدید از نرم افزار را اتوماتیک کند.درواقع با CI بعد از هر تغییری که در کد انجام میشود (درواقع بعد از هر کامیت) به صورت اتوماتیک باعث می شود که پروژه مورد نظر دوباره ساخته شده (Build) و تست های آن انجام شود و گزارش آن دراختیار توسعه دهنده ها قرار داده می شود.فرآیند CI/CD شامل چه المان ها و مراحلی میشود؟درواقع این بستگی زیادی به پروژه داره ولی مرحله هایی که معمولا درنظر گرفته میشه تا نسخه جدیدی از نرم افزار انتشار پیدا کند شامل :اگر درهرکدام از این مراحل مشکلی وجود داشته باشد به توسعه دهنده اطلاع داده میشود تا مشکل و باگ موجود برطرف شود و مراحل از اول اجرا می شود.Build کردن پروژهدر این مرحله کد مرجع (source code) را به همراه کدها و کتابخانه های وابسته (dependencies) مرج می کنیم تا بتوانیم یک نمونه قابل اجرا از محصول را که قابلیت ارائه شدن به کاربر را داشته باشد را از پروژه بسازیم.درصورت اینکه پروسه در این مرحله به مشکل برخورد کند نشان دهنده این است که مشکل اساسی در پروژه وجود دارد.تست کردن پروژهدر این فاز برای تشخیص اینکه محصول پس از build شدن به طور صحیح کار میکند یا نه، تست هایی که توسط توسعه دهنده ها نوشته شده انجام می شود. این تست ها هم رفتار محصول و هم استایل کد را چک میکنند. بررسی استایل کد از این جهت مفید است که خوانایی کد را برای همه اعضای تیم توسعه بالا می برد.باتوجه به اندازه پروژه و پیچیدگی آن این فاز ممکن است از چند دقیقه تا چندین ساعت طول بکشد. در خیلی از پروژه های بزرگ این فاز به چندین مرحله تقسیم می شود و در نهایت تمام سیستم چک می شود.در صورت اینکه در این مرحله به مشکل برخورد کند نشان دهنده مشکلاتی بوده است که در هنگام نوشتن کد توسعه دهنده ها دقت کافی را نداشتن و پیش بینی آن را نکردند. (که خوب برای همین تست میکنیم دیگه!!)ومرحله نهایی Deploymentدر این مرحله که نسخه قابل اجرا پروژه ساخته شده و همه تست های تعریف شده را با موفقیت پشت سر گذاشته، آماده است که در اختیار کاربران قرار بگیرد. معمولا چند محیط برای deployment وجود دارد (معمولا بتا(Beta) یا Staging و Production نامیده می شوند). در محیط Beta محصول همچنان در مرحله تست قرار دارد. (این نسخه برای تست ممکن است در اختیار کاربران قرار بگیرد یا توسط یک تیم مورد بررسی قرار بگیرد.) و در محیط Production  نسخه جدید از محصول در اختیار کاربران قرار گرفته است.مثالی از یک پروسه CI/CDپروسه میتواند خیلی ساده یا در صورت اینکه پروژه بزرگ باشد خیلی پیچیده شود. یک مثال ساده از این پروسه که برای یک پروژه به زبان GO نوشته شده است را میتوانید در اینجا ببینید. این پروسه کد را کامپایل کرده، استایل آن را بررسی و تست های نوشته شده را اجرا می کند.فریم ورک های CI/CD1. Jenkins : یکی از ابزارهای open-source موجود برای CI/CD است که با Java نوشته شده است و cross platform است. مجموعه ای از مثال ها برای این ابزار را میتوانید در اینجا ببینید.2. TeamCity : یکی از ابزارهای server based برای CI/CD است بر پایه جاوا که توسط شرکت jetbrains توسعه داده شده است و برای پروژه های open-source رایگان است.3. Travis CI : همانند Jenkins جزو اولین ابزارها برای CI/CD است و در ابتدا فقط برای پروژه های open-source ارائه شد. درحال حاضر پروژه های close-source را هم پشتیبانی میکند. با زیان Ruby نوشته شده و 30 زبان برنامه نویسی را پشتیبانی میکند.و تعداد زیادی ابزار دیگر که میتوان به GoCD (open-source)، CircleCI، Bamboo،Semaphore  و ... اشاره کرد.و در نهایت یکی از مزایای اجرای این روش این است که انتشار نسخه جدید از پروژه ویا رفع مشکلات موجود در آن و deploy کردن آن راحت تر انجام می شود و زمان کمتری را صرف میکند و دیگر لازم نیست که ساعت ها و یا روزها زمان صرف بشود تا پروژه قابل ارائه شدن به کاربران بشود.منابعhttps://www.redhat.com/en/topics/devops/what-is-ci-cdhttps://www.redhat.com/en/topics/devops/what-cicd-pipelinehttps://martinfowler.com/articles/continuousIntegration.htmlhttps://www.lambdatest.com/blog/31-best-ci-cd-tools/https://semaphoreci.com/cicdhttps://semaphoreci.com/blog/cicd-pipeline</description><category>miiimkaaaf</category><author>miiimkaaaf</author><pubDate>Thu, 11 Feb 2021 00:52:28 +0330</pubDate></item><item><title>طراحی یک custom widget در فلاتر</title><link>https://virgool.ir/@miiimkaaaf/طراحی-یک-custom-widget-در-فلاتر-qdqclvdi9nxu</link><description>بسم الله الرّحمٰن الرّحیماگر تازه با فلاتر آشنا شدین و هنوز برنامه درست و حسابی باهاش ننوشتین، این نوشته می‌تونه کمک خوبی بهتون بکنه. با این متن شما اصول اولیه طراحی یک صفحه در فلاتر + ساختن یه ویجت دلخواه + قراردادن تعدادی از اون ویجت توی یه صفحه رو یاد می‌گیرید. برای مثال ما ویجت زیر رو انتخاب کردیم که بهتون آموزش بدیم.قبل از این که مستقیما وارد طراحی بشیم، اجازه بدین توضیحاتی داشته‌باشیم برای افرادی که هیچ گونه آشنایی با فلاتر ندارن. اگر قبلا برنامه‌نویسی اندروید کار کرده باشین، احتمالا متن بیشتر به دردتون خواهد خورد.نصب و راه‌اندازیبا توجه به این که برای نصب و راه‌اندازی فلاتر تعداد زیادی متن و فیلم و عکس و ... به تمام زبان‌های دنیا وجود داره، و با یه سرچ ساده، میشه به تمام اون‌ها دسترسی داشت، ما از این قضیه می‌گذریم و به صورت پیش‌فرض در نظر می‌گیریم که شما فلاتر رو نصب کردین و آماده‌این برای کد زدن. اگه این مرحله رو نرفتین پیشنهاد می‌کنیم که این لینک رو مشاهده کنین: https://flutter.dev/docs ویجت چیست؟برنامه‌نویسی در فلاتر به زبان دارت هست. بر خلاف بسیاری از محیط‌های طراحی مثل اندروید که زبان منطق با زبان طراحی متفاوت هست، در فلاتر، زبان هر دو، دارت هست. بنابرین ما در طراحی فلاتر با آبجکت‌های زبان دارت روبرو هستیم. تمامی آبجکت‌های طراحی، از آبجکت Widget ارث‌بری دارن. بنابرین هر تکه طراحی یک صفحه در فلاتر، یک ویجت هست.انواع ویجتحالا اینجا چند تا از مهم‌ترین ویجت‌ها رو با هم بررسی می‌کنیم.Row, Column, Container, Expanded, Flexible, Stackبرای قسمت‌بندی و طراحی صفحه،Text, Image, Iconبرای نمایش محتوا در صفحه،RaisedButtonبرای ورودی گرفتن از کاربر و در نهایت می‌رسیم به دو ویجت مهم StateFullWidget و StateLessWidget.ویجت‌های قسمت‌بندی و محتوا (انتزاعی)۱. سطر یا Row: برای نمایش سطری چند ویجت. برای دوستانی که اندروید کار کردن، معادل Linear Layout با Orientation:horizontal هست.Row(&#xA;    children: [&#xA;    ...&#xA;    ]&#xA;),۲. ستون یا Column: نمایش ستونی چند ویجت. معادل Linear Layout با Orientation:vertical در برنامه نویسی اندروید است.Column(&#xA;    children:[&#xA;    ...&#xA;    ]&#xA;),۳. ظرف یا Container: خبر بد این هست که ویجت‌ها در فلاتر، بر خلاف طراحی در اندروید، قابلیت داشتن margin, padding, width, height ندارن. برای انجام این کار باید اون‌ها رو در یک Container قرار بدین. دقت کنین که کانتینر، بر خلاف Row و Column فقط و فقط یه ویجت درش قرار می‌گیره.Container(&#xA;    child: ...&#xA;),برای درک این ۳ ویجت به عکس زیر توجه کنین:۴. منبسط شده یا Expanded: ویجتی برای پر کردن فضای خالی باقی‌مانده در ویجت پدر هست. Expanded هم مثل Container فقط یه بچه داره. (یه ویجت در اون قرار می‌گیره) این ویجت معادل گذاشتن مقدار match_parent به ازای عرض و طول، در اندروید هست.Expanded(&#xA;    child: ...&#xA;),برای درک ویجت Expanded به عکس زیر توجه کنین. این عکس یک Column است که فرزند یک Expanded شده است و حداکثر مساحتی که می‌تواند اشغال می‌کند.۵. منعطف یا Flexible: این ویجت برای مدیریت اندازه دو ویجت در یک سطح هست. مثلا اگر شما می‌خواهید یک ویجت ۱٫۳ و یک ویجت دیگه ۲٫۳ صفحه رو بگیره، اون‌ها رو در Flexible قرار میدین و مقدار flex اولی رو ۱ و دومی رو ۲ می‌گذرین. دقیقا مثل weight در اندروید.Flexible(&#xA;    flex: 1,&#xA;    child: ...&#xA;),&#xA;Flexible(&#xA;    flex: 2,&#xA;    child: ...&#xA; ),برای درک Flexible عکس زیر را ببینین. این عکس دو ویجت Flexible است که در یک Row که فرزند یک ویجت Expanded است، قرار گرفته‌اند.۶. پشته یا Stack که برای روی هم گذاشتن دو ویجت استفاده میشه.Stack(&#xA;    children: [&#xA;        ...&#xA;    ]&#xA;),عکس زیر استکی شامل سه فرزند Container است.ویجت‌های نمایش محتوا۱. متن یا Text: برای نمایش متن.Text(&#39;salam&#39;),۲. عکس یا Image: برای نمایش عکس.Image(),۳. آیکون یا Icon: برای نمایش آیکون. خبر خوب اینه که خود فلاتر یه لیست کامل و جامع از آیکون‌ها داره که می‌تونین به شکل زیر ازش استفاده کنین.Icon(Icons.home),ویجت‌های ورودی گرفتندکمه یا RaisedButton: البته RaisedButton یکی از انواع دکمه هست ولی رایج‌ترین هست.RaisedButton(&#xA;    child: Text(&#39;click&#39;),&#xA;    onPressed: () {}&#xA;)برای مشاهده نمونه Text و Image و Icon و RaisedButton ‌می‌توانید عکس زیر را مشاهده کنید:دو ویجت خیلی مهم: StateFull و StateLess:این دو ویجت تعیین کننده این هستن که آیا وضعیت طراحی ما قابل تغییر هست یا نه. مثلا طراحی یه Text هیچ‌وقت تغییری نمی‌کنه یا یه آیکون. هیچ چیزی درون اون‌ها قابل تغییر نیست. همچنین یه صفحه که فقط یک متن داره، هیچ وقت تغییری نمی‌کنه. این ویجت‌ها باید StateLess باشن.اما این ویجت چی؟همون جوری که می‌بینین، این ویجت یه قلب داره که اگه کاربر کلیک کنه، باید فعال بشه و وضعیتش تغییر کنه. بنابرین ویجت کلی ما دو تا وضعیت خواهد داشت. یکی با قلب غیرفعال و یکی با قلب فعال. پس لازمه که StateFull باشه. البته چون هر ویجت Statefull هر بار با تغییر وضعیت، به طور کامل لود میشه، خیلی بهتره که کوچکترین واحد ممکن رو Statefull بکنین. مثلا در این جا، یک ویجت Statefull بسازین که فقط یه آیکون قلب داشته‌باشه.شیوه ساختن ویجت StateLess به این شکل:class MyStatelessWidget extends StatelessWidget{&#xA;    @override&#xA;    Widget build(BuildContext context){&#xA;    return Text();&#xA;    }&#xA;} و ویجت Statefull:class MyStatefullWidget extends StatefullWidget{&#xA;    @override&#xA;    _MyStatefullWidgetState createState() =&gt; MyStatefullWidgetState();&#xA;}&#xA;&#xA;&#xA;class MyStatefullWidgetState extends State&lt;MyStatefullWidget&gt; {&#xA;    @override&#xA;    Widget build(BuildContext context){&#xA;        return Container();&#xA;    }&#xA;&#xA;}که می‌توانیم با تابع setState وضعیت یک ویجت را تغییر بدهیم.طراحی ویجت مورد نظرابتدا سعی کنین ساختار کلی ویجت مورد نظر رو به دست بیارین. مثلا برای ویجت ما:همان‌طور که می‌بینید و در عکس با رنگ قرمز نشان داده شده‌است، ویجت کلی ما یک Column است که فرزندان آن به ترتیب یک ImageView، یک Row که با رنگ سبز نشان داده شده‌است و خود شامل فرزندان Text, Spacer, Icon است، یک Text و در نهایت یک Row که با رنگ سبز نشان داده شده‌است و شامل دو فرزند RaisedButton است، می‌باشد.Column:----Image----Row:------------Text------------Spacer------------Icon----Text----Row:------------RaisedButton------------RaisedButtonاگر فقط همین کلاس‌ها را پیاده‌سازی کنید، با صفحه‌ای مواجه خواهید شد که از نظر مکان متن‌ها و عکس و دکمه‌ها و آیکون، دلخواه ما نیست و همه از سمت چپ به هم چسبیده‌اند. برای حل این قضیه باید از Containerها، Paddingها و attributeهایی مثل mainAxisAlignment در Rowها و Columnها استفاده کرد. مثلا اگر mainAxisAlignment در یک سطر، Center باشد، ویجت‌های فرزند، در وسط آن سطر قرار می‌گیرند. یا اگر SpaceBetween باشد، ویجت‌ها حداکثر فاصله را از هم می‌گیرند.فقط round کردن اطراف ویجت مانده‌است که با استفاده از ویجتی مثل ClipRRect صورت می‌گیرد. همچنین برای فعال / غیرفعال کردن ویجت آیکون قلب، آن را در یک StatefullWidget تعریف می‌کنیم و دو استیت فعال و غیر فعال برای آن تعریف می‌کنیم.این کد را در گیت‌هاب می‌تونید ببینید: https://github.com/mmir98/FlutterCustomCardWidget/blob/master/CustomCardWidget/lib/CustomCardWidget.dart در این ویجت، ما ۵ ورودی برای ویجت داریم:class CustomCard extends StatelessWidget {&#xA; final String title;&#xA; final String description;&#xA; final String imgPath;&#xA; final double imageHeight;&#xA; final double imageWidth;&#xA;...حال Constructor کلاس CustomCard ما به این صورت خواهد بود:‍‍‍CustomCard(this.title, this.description, this.imgpath, {this.imageHeight, this.imageWidth});که نشان {} در اطراف imageHeight و imageWidth به معنی اختیاری بودن وارد کردن آن‌ها هنگام ساخت ویجت می‌باشد.حال برای به کار بردن لیستی از این ویجت، کافیست داده‌ای مانند زیر داشته‌باشیم:List&lt;Map&lt;String, Object&gt;&gt; data = [   &#xA;   { &#34;title&#34;: &#34;Card title 1&#34;,&#xA;     &#34;description&#34;: &#34;Some text as description for card 1 Some text as description for card 1 Some text as description for card 1 Some text as &#34;,&#xA;     &#34;img&#34;: &#34;images/card1_img.jpg&#34;&#xA;   },      &#xA;   { &#34;title&#34;: &#34;Card title 2&#34;,&#xA;     &#34;description&#34;: &#34;Some text as description for card 2&#34;,&#xA;     &#34;img&#34;: &#34;images/card2_img.jpg&#34;   &#xA;   },      &#xA;   { &#34;title&#34;: &#34;Card title 3&#34;,&#xA;     &#34;description&#34;: &#34;Some text as description for card 3&#34;,&#xA;     &#34;img&#34;: &#34;images/card3_img.jpg&#34;&#xA;   }    &#xA;];&#xA;در این‌جا به جای این که به صورت دستی داده‌ها را به شکل زیر وارد کلاس ویجت کنیم،CustomCard(&#xA;           title: data[1][&#39;title&#39;], &#xA;           description: data[1][&#39;description&#39;],    &#xA;           imgPath: data[1][&#39;img&#39;],&#xA;),&#xA;CustomCard(&#xA;            title: data[2][&#39;title&#39;], &#xA;            description: data[2][&#39;description&#39;], &#xA;              imgPath: data[2][&#39;img&#39;],&#xA; ),&#xA;CustomCard(&#xA;            title: data[3][&#39;title&#39;],&#xA;             description: data[3][&#39;description&#39;], &#xA;               imgPath: data[3][&#39;img&#39;],&#xA; ),&#xA;&#xA;&#xA;میتوانیم داده‌ها را به عنوان لیستی از ویجت‌های دلخواهی که طراحی کرده‌ایم وارد کنیم:children: &lt;Widget&gt;[&#xA;      ...data.map((e) =&gt; CustomCard(&#xA;            title: e[&#39;title&#39;],&#xA;            description: e[&#39;description&#39;],&#xA;            imgPath: e[&#39;img&#39;], &#xA;            // imageWidth: 500,  //Define a specific width and height for the image in the customCard.&#xA;            //imageHeight: 180,                      &#xA;        )).toList()&#xA;],&#xA;که در این حالت، ۳ ویجت از ویجت customCard که قبلا طراحی کردیم، خواهیم داشت.نویسندگان:محمدجواد میرتیموریمهدی فرزادیمحسن کثیری</description><category>miiimkaaaf</category><author>miiimkaaaf</author><pubDate>Fri, 04 Dec 2020 22:20:17 +0330</pubDate></item></channel></rss>