کتاب الگوهای طراحی به بیان ساده(design patterns / دیزاین پترن)

در مهندسی نرم افزار، design patterns(الگوهای طراحی) راه حل‌های قابل استفاده برای مشکلاتی هستند که معمولاً در طراحی نرم‌افزار اتفاق می افتند.

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

کتاب refactoring / ریفکتورینگ

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

در کتاب Refactoring اثر Martin Fowler نوشته شده: refactoring تکنیک مرتب/منظم سازی برای تجدید ساختار کد موجود است. تغییر ساختار داخلی کد بدون تغییر رفتار خارجی آن.

refactoring یک سرمایه‌گذاری و راه حلی برای مقابله با کد کثیف و بدهی فنی است که باعث کاهش هزینه‌های توسعه نرم‌افزار در آینده خواهد شد.



آخرین مطالب وبلاگ

الگوی طراحی مخزن در لاراول(Repository Design Pattern)

حتما چنین کدی رو قبلا دیدین:

    public function index() : JsonResponse
    {
        $cars = Car::with('facilities', 'type', 'color', 'rentalDetail')->all();
        return response()->json($cars, 200);
    }

هوم... . مورد بدی توش دیده نمیشه. یک سرویس ساده که لیست خودرو ها رو میده. اما منطق/logic توی کنترلر نوشته شده. هر چند به عقیده من آوردن منطق در کنترلر برای app های کوچک مشکلی به وجود نمیاره اما با رشد نرم افزار بیشتر و بیشتر نیاز به یک ساختار منسجم و متمرکز رو حس میکنید.

به عنوان یک روش جایگزین و بهتر میشه از الگوی طراحی مخزن یا بهتر هست بگیم Repository Design Pattern استفاده کرد. مثل همیشه ساده بگم، در این روش مسئولیت ارتباط و استخراج داده ها رو از روی دوش مدل برمیداریم و اون رو در کلاس های Repository پیاده میکنیم، داخل کنترلر هم فقط متد هاشون رو صدا میزنیم.

    public function index() : JsonResponse
    {
        $cars = $this->carRepository->get();
        return response()->json($cars, 200);
    }

این روش مزیت های زیادی داره از جمله:

- ایجاد ساختاری منسجم و متمرکز
- حذف کد های تکراری
- توسعه و نگهداری آسانتر
- کاهش خطا و خطایابی سریعتر
- از بین بردن وابستگی های بین مدل و کنترلر
- کد تمیز و واضحتر

خب به نظرم توضیحات تا همین اندازه کافی هست و بهتره بریم سراغ یک نمونه ساده از پیاده سازی این روش تا مزایایی که بهمون میده رو بیشتر درک کنید.

ادامه...

کیو انتخاب کنم کدومو جواب کنم؟

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

در درجه اول اگر به موردی علاقه دارین امتیاز ویژه ای براش در نظر بگیرید چون خیلی توی موفقیت شما موثر خواهد بود.

میرسیم به بازار کار. دغدغه مهمیه. بازار خودتون رو انتخاب کنید. نیازمندی های داخل کشور با خارج از اون کمی متفاوته. فرض رو بر داخل میگیریم. آگهی های استخدام داخل رو با توجه به علاقه و شرایطی که دارین بررسی کنید.
مثلا اگر محل زندگی شما جوری هست که مجبور به دورکاری هستید، آگهی های استخدام دورکاری رو چک کنید. نیازمندی هاشون، حقوق و دستمزد و... به انتخاب شما کمک میکنه.
فرض کنید بین یادگیری Angular و React گیر کردیم. الان که مشغول نوشتن این مطلب هستم توی یکی از سایت های کاریابی Angular صد و ده تا و React دویست و پنجاه آگهی استخدام داره.
توی مرحله بعد میریم سراغ میزان حقوق دستمزد هر کدومشون و...
همین سرچ کوچیک نشون میده امروز React Developer شانس بیشتری برای استخدام داره.
این کارو توی بازه ها و سایت های مختلف باید انجام داد(هفتگی یا ماهانه). چون گرفتن آمار در یک روز و یک منبع ممکنه شما رو به اشتباه بندازه.
حالا بعد از کلی سبک و سنگین کردن میتونید مشورت بگیرید. اینجا دیگه متوجه تعصب طرف مقابلتون خواهید شد.

دیتا تایپ مناسب برای فیلد status در پایگاه داده

گاهی داخل app نیاز به یک فیلد با مقادیر مشخصی داریم. مثل status در جدول payments که میتونه paid یا unpaid باشه. از اونجایی که در پروژه های مختلف این فیلد رو به روش های متفاوتی پیاده میکردن تصمیم گرفتم در موردش کمی بنویسم. به طور کلی سه دیتا تایپ برای این قبیل فیلد ها انتخاب میشن که در موردشون توضیح میدم.

- string/varchar: ساده ترین رویکرد انتخاب دیتا تایپ string هست. وضوح خوبی هم داره. چون هنگام توسعه با یک نگاه به سطر مورد نظرتون متوجه وضعیتش میشید. حتی میتونید توی فرانت دقیقا این رشته رو چاپ کنید(ولی نه توی app های چند زبانه). اما بسته به طول رشته طبیعتا فضایی برای ذخیره سازی در نظر گرفته میشه. هر چند موضوع فضا خیلی وقته به حاشیه رفته و کمتر کسی نگران پر شدن هارد سرورشه، اما اگر سطرهای زیادی داشته باشید هنگام پیمایش اطلاعات، کندی رو حس خواهید کرد. مورد بعدی تغییرات هست. فرض کنید پس از مدتی متوجه غلط املایی در یکی از آیتم ها میشید، تمام سطر ها باید update بشن.

- enum: چیزی که ازش به شدت متنفرم! من دوست ندارم منطق و فرآیند برنامه رو توی دیتابیس ببرم. چرا که مثلا هنگام تغییرات و یا کم و زیاد شدن آیتم ها مجبورم جدول رو هم بروز کنم.

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

انتخاب هر یک از این روش ها بستگی به شرایط و app شما داره. میتونید string رو برای پروژه های کوچک و اطلاعات کم استفاده کنید. enum توی پروژه هایی که به شما ارث رسیده(یک پروژه قدیمی که مشغول توسعه نسخه جدیدش هستید) و فرآیند ها و منطق برنامه از قبل مشخص هست هزینه تغییرات پایینی داره. tinyint هم زمانی که در یک پروژه بزرگ یا مواقعی که تغییرات زیادی هنگام توسعه اتفاق میوفته کارآمد هست.

استقرار وب اپلیکیشن golang با استفاده از docker-compose

برای deploy روش های زیادی وجود داره که اغلب وارد پیچیدگی هایی میشن. من تصمیم دارم کوتاه و ساده در موردش بنویسم و از تنظیمات جانبی اون صرف نظر میکنم.

در مرحله اول به یک http server نیاز داریم. من خودم مخالف استفاده از فریمورک های golang هستم ولی الان دم دسته و مثال رو با gin انجام میدم. شما هر طور خواستین بنویسید.

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main()  {
	router := gin.Default()
	router.GET("/", func(context *gin.Context) {
		context.JSON(http.StatusOK, gin.H{
			"status": "OK",
		})
	})

	router.Run(":8080")
}

به Dockerfile نیاز داریم. پیشفرض به پورت 8080 گوش میده و app رو اجرا میکنه(پورت http server هم روی 8080 ست شده).

FROM golang:1.13
ENV APP_NAME app
ENV PORT 8080
WORKDIR /go/src/app

CMD ./${APP_NAME}
EXPOSE ${PORT}
ادامه...

جستجو با استفاده از عبارت باقاعده(regex) در elasticsearch

توی مطلب قبلی جستجو با استفاده از wildcard query رو توضیح دادم. الگو های wildcard ساده بودن اما کار راه انداز. برای تعریف الگوهای کامل و البته پیچیده تر میشه از عبارات باقاعده یا regex هم استفاده کرد. در این صفحه میتونید ببینید داخل الستیک چه عملگر هایی از regex پشتیبانی میشه.

مثال زیر اسنادی رو که فیلد user شون با k شروع و با y تموم بشه رو match میکنه.

GET /_search
{
    "query": {
        "regexp": {
            "user": {
                "value": "k.*y"
            }
        }
    }
}

تعریف و جستجو بر اساس الگو با استفاده از wildcard query در elasticsearch

با استفاده از wildcard query میتونید الگو های ساده ای برای matching تعریف کنید. wildcard از دو عملگر پشتیبانی میکنه.

? : یک کاراکتر تکی رو match میکنه.

* : صفر یا بیشتر. هر تعداد کاراکترُ match میکنه.

مثال زیر اسنادی رو پیدا میکنه که نویسنده هاشون با حرف t شروع شده باشن.

GET /_search
{
    "query": {
        "wildcard": {
            "authors": {
                "value": "t*"
            }
        }
    }
}