Orion Techs | اُریون تکز🖤
Статистикаاینجا اُریونه ، کامیونیتی برای تمام دنبال کنندگان آینده. امیر آقایاری هستم برنامه نویس فول استک و به صورت تخصصی مهندسی بک اند رو جلو میبرم یادگیری ها و تجاربی که کسب میکنم رو براتون میزارم راه ارتباطی: @maqhbul
- Последний пост
- 13 авг.
- Последнее чтение
- 15 авг.
- Постов за неделю
- 5
- Всего постов
- 23
- Тип
- открытый
- Язык
- персидский
- Категория
- Картинки
- В каталоге с
- 13 авг.
- 1/24сутки в ленте
- 94
- 1/48двое суток
- 107
- 1/72трое суток
- 116
Оценка по просмотрам недавних постов: пост набирает почти всё за первые сутки.
Посты
ISP دپندنسی های غیر ضروری رو حذف میکنه (چون باعث میشه متد های غیر ضروری رو در کانترکتمون نداشته باشیم و اینترفیسمون کوچک تر باشه) از اونور اگه اینترفیسمون بزرگ تر باشه ابستکرشنمون رو بد میکنه از اونور کوهیژن میگه که چیزایی که به هم مرتبط هستند رو کنار هم بزار ISP هم میگه که اینترفیس رو طوری طراحی کن که کانترکت های مرتبط کنار هم باشند و مصرف کننده چیزای غیر مرتبط را نگیرد پس یه ارتباط مستقیم خفن اینحا داریم تو بحث کامپوزیشن هم با استفاده از ISP میشه یک کلاس رو از چند اینترفیس کوچیک ساخت حالا هروقت اینترفیس دیزاین کردید از خودتون بپرسید : ایا تمام مصرف کنندگان این اینترفیس واقعا به تمام متد های آن نیاز دارند؟ حالا چهار اصل قبلی رو کنار هم بزاریم SRP: مسئولیت هارا جدا کن OCP: قابلیت جدید را با اکستنشن اضافه کن LSP: ایمپلمنتشن باید کانترکت را رعایت کند ISP: کانترکت را بیش از حد برای مصرف کننده بزرگ نکن
خب خب رسیدیم به اصل چهارم ISP interface segregation principle این اصل دقیقا ادامه lsp هستش که درموردش حرف زدیم و به کوهیژن و کانترکت و اینترفیس و ابسترکشن وصل میشه اصل تفکیک اینترفیس : Clients should not be forced to depend on methods they do not use. هیچ مصرف کننده ای نباید مجبور باشد به متد هایی وابسته شود که به انها نیازی ندارد مثال : interface Worker { work(): void; eat(): void; sleep(): void; } class RobotWorker implements Worker { work() {} eat() { throw new Error("Robot doesn't eat"); } sleep() { throw new Error("Robot doesn't sleep"); } } اینجا ربات ورکر مجبور شده اینترفیسی را پیاده کند که قابلیت های غیر مرتبط دارد اینجا مشکل اینه که اینترفیس ما بزرگه و ما ۳ مفهموم متفاوت رو تو یه کانترکت گذاشتیم درحالی که مسئولیت مشترکی ندارند دیزاین بهتر : interface Workable { work(): void; } interface Eatable { eat(): void; } interface Sleepable { sleep(): void; } ISP نمیگه که اینترفیس باید کوچک باشه بلکه میکه که اینترفیس باید باید برای مصرف کننده ای که از ان استفاده میکنه ، مناسب و متمرکز باشه ممکنه ۵ تا متد داشته باشیم اما ISP رعایت شده باشه از اون طرف هم ممکنه ۲ تا داشته باشیم و نقض شده باشه اینجا کار برمیگره به همون کوهیژن که درموردش حرف زدیم
بچهها یه تفاوت مهم npm که خیلیها روش کار نمیکنن: npm i با npm ci فرق داره! ✅ npm i (یا npm install) • برای کار روزمره و توسعه خوبه • انعطافپذیره • ممکنه package-lock.json رو تغییر بده • اگه node_modules باشه، فقط تغییرات رو اعمال میکنه ✅ npm ci مخفف clean install هستش • مخصوص CI/CD و Docker و production ساخته شده • اول node_modules رو کامل پاک میکنه • فقط از روی package-lock.json نصب میکنه (هیچ تغییری بهش نمیده) • اگه package.json و lockfile با هم یکی نباشن، خطا میده و متوقف میشه • معمولاً سریعتر و قابلاعتمادتره خلاصه: توی سیستم خودت → npm i توی گیتهاب اکشن، داکر یا سرور → npm ci این کار باعث میشه همه جا دقیقاً همون نسخهها نصب بشه و باگهای عجیب کمتر پیش بیاد.
درود بچه ها یه چنل زدم که هر شب، خلاصه و نکتههایی که از کتابهای مهندسی و معماری نرمافزار و موضوعات مرتبط ، مطالعه میکنم رو باهاتون شیر میکنم امیدوارم به دردتون بخوره https://t.me/OriginalAbouei
درود امروز میخوایم ببینیم Liskov Substitution Principle چطور با مفاهیم پایهای و مهم دیگه درارتباطه LSP و Interface / Contract با تعریف اینترفیس در واقع یک قرارداد رفتاری میسازیم. LSP تضمین میکنه که سابتایپ فقط شکل اینترفیس رو کپی نکنه، بلکه کانترکت اون رو هم کامل رعایت کنه. اگر این قرارداد نقض بشه، کلاینتهایی که به اینترفیس وابستهان خراب میشن. LSP و Abstraction ابسترکشن یعنی جزئیات غیرضروری رو پنهان کنیم و یک مفهوم درست ارائه بدیم. اگر ابسترکشن اشتباه باشه (مثل فرض کردن اینکه همه پرندهها پرواز میکنن)، LSP خیلی سریع میشکنه. پس وقتی LSP نقض میشه، اغلب مشکل از طراحی ضعیف ابسترکشن است. LSP و Polymorphism پلیمورفیسم یعنی کار کردن با چند نوع مختلف از طریق یک ابسترکشن مشترک. هدفش داشتن یک اینترفیس با چندین Implementation قابلجایگزینی است. LSP دقیقاً شرط لازم برای پلیمورفیسم سالم است؛ بدون اون، جایگزینی فقط ظاهری میمونه و در عمل رفتار برنامه رو خراب میکنه. LSP و Inheritance ارثبری ابزار اصلی پیادهسازی سابتایپهاست. LSP به ما میگه چه موقع ارثبری درست است و چه موقع خطرناکه. اگر کلاس فرزند نتونه بدون تغییر رفتار مورد انتظار جایگزین والد بشه، ارثبری اشتباه استفاده شده و بهتره به سمت Composition بریم. LSP و Open-Closed Principle (OCP) OCP میگه کد باید برای توسعه باز و برای تغییر بسته باشه. LSP کمک میکنه بدون تغییر کد موجود، رفتار جدید اضافه کنیم (با سابتایپهای جدید). بدون LSP، اضافه کردن سابتایپ جدید معمولاً مجبورمون میکنه کد قبلی رو دستکاری کنیم و OCP میشکنه. LSP و Composition over Inheritance وقتی LSP رعایت نشه، معمولاً ارثبری مشکلساز شده. در این حالت Composition (ترکیب) انتخاب بهتری است، چون وابستگی رفتاری رو کمتر میکنه و جایگزینی امنتری میده. LSP و Encapsulation کپسولهسازی جزئیات داخلی رو پنهان میکنه. اگر سابتایپ جزئیات یا پیشفرضهای کلاس پایه رو نقض کنه (مثلاً exception جدید بندازه یا خروجی غیرمنتظره بده)، هم Encapsulation و هم LSP میشکنه.
بعد داکرایز کردن پروژه و نوشتن اینتگرشن تست ها خداییش دیگه خسته شدم و یونیت تست هارو گذاشتم برای بعد و اینکه نمیخواستم این تست هارو به ai بسپرم چون این پروژه یه جورایی مسیر یادگیریه منه و کمترین استفاده از ai روتوش داشته حالا امروز رفتم سراغ ci/cd و گیت هاب اکشنز و اینا و قسمت ci رو تقریبا تا یه حدودایی اوکی کردم CI : Continuos Integration در این روش هر بار که تغییر جدید تو کد ایجاد میشه به طور خودکار میاد فرایند هایی مثل تست و بررسی بیلد و اینارو قبل از رسیدن به پروداکشن اوکی میکنه
حاجی سلام امروز رسیدیم به اصل سوم SOLID: LSP — Liskov Substitution Principle اگر B زیرنوع A است، باید بتوانیم B را هرجا که A انتظار میرود جایگزین کنیم، بدون اینکه رفتار مورد انتظار سیستم خراب شود (همون رابطه چایلد و پرنت رو میگه). یه مثال معروف 😂 پرنده -> پرواز میکنه پنگوئن -> پرنده است، ولی پرواز نمیکنه پس اگر Bird را طوری طراحی کنیم که همهی پرندهها مجبور به fly() باشند، قراردادمان از اول اشتباه طراحی شده. بهتره قابلیتها رو جدا کنیم: interface Bird { eat(): void; } interface FlyingBird { fly(): void; } class Eagle implements Bird, FlyingBird { eat() {} fly() {} } class Penguin implements Bird { eat() {} } اینجا هر کلاس فقط قراردادی رو قبول میکنه که واقعاً میتونه بهش عمل کنه. حالا تو بک اند فرض کن داریم: class FileStorage { upload(file: Buffer) {} download(id: string) {} delete(id: string) {} } class ReadOnlyStorage extends FileStorage { upload(file: Buffer) { throw new Error("Upload is not supported"); } } در ظاهر inheritance داریم: ReadOnlyStorage IS-A FileStorage اما: function backupFile(storage: FileStorage) { storage.upload(file); } backupFile(new ReadOnlyStorage()); سیستم دهنش سرویس میشه چرا؟ چون ReadOnlyStorage واقعاً نمیتونه جای FileStorage قرار بگیرد. مشکل از ReadOnlyStorage نیست مشکل از انتخاب اشتباه inheritance و کانترکت پایه است. بهتره کانترکت ها رو بر اساس قابلیتها جدا کنیم: interface ReadableStorage { download(id: string): Promise<Buffer>; } interface WritableStorage { upload(file: Buffer): Promise<void>; } interface DeletableStorage { delete(id: string): Promise<void>; } حالا: class S3Storage implements ReadableStorage, WritableStorage, DeletableStorage {} class ReadOnlyStorage implements ReadableStorage {} نکتهی مهم LSP: اگر در Child مجبور شدی رفتار Parent رو: throw Error return null return false یا به شکلی خنثی کنی احتمالاً داری LSP رو نقض میکنی. پس همیشه از خودت بپرس: «آیا این Child واقعاً میتونه بدون تغییر رفتار سیستم، جای Parent قرار بگیره؟» اگر جواب نه بود، احتمالاً abstraction یا inheritance اشتباه طراحی شده.
به زیبایی نوشته بود که اگه احتمال بردت ۱۰۰ درصده پس فدای سرت که سرعت کمه
https://www.geeksforgeeks.org/node-js/node-js-event-loop/
https://www.geeksforgeeks.org/node-js/node-js-event-loop/
درود دوستان امروز با یه کتابخونه خیلی کاربردی آشنا شدم که اگه سمت بک اند کار میکنید قطعا به درد شما هم میخوره Awilix یه کتابخونه سبک برای دیپندسی اینجکشنی که قبلا تو چنل درموردش حرف زدیم البته با نود جی اس و تایپ اسکریپت که البته خیلی هم به نظر اعتیاد اور هستش این کتابخونه چیکار میکنه ؟ بدون اینکه بیاییم دکوریتور یا annotation بنویسیم خیلی راحت میتونیم سرویس و کلاس هامون رو به هم متصل کنیم و کدمون رو تمیز و قابل تست نگه داریم یه کتابخونه هستش که دیپندسی هات رو سر و سامون میده و میتونی باهاش دیپندسی هات رو تو اکسپرس تقریبا مثل نست مدیریت کنی
open / closed principle اصل دوم solid تعریف رسمی : Software entities should be open for extension, but closed for modification. موجودیت های نرم افزار باید برای گسترش باز باشند و برای تغییر بسته باشند فرض کن یه ساختمان ساختی میخوای یه اتاق اضافه کنی دوتا راه داری یا باید ساختمونو بریزی دوباره بسازی یا اینکه بدون ریختن ساختمون بیای بهش اتاق اضافه کنی این اصل همیشه دومی رو میگه (مثال جالبی نبود) فرض کنید اینو داریم : class PaymentService { pay(type:string){ if(type==="zarinpal"){ } if(type==="stripe"){ } } } حالا میگن پیپال هم اضافه کن اینجا چی میشه ؟ تغییر کلاس ، تست دوباره ، دیپلوی دوباره ، احتمال باگ که این ینی ocp نقض شده پس چیکار کنیم؟ اول بیاییم یه اینترفیس میسازیم برای gateway پیمنت که قراره یه pay داشته باشه بعد اون gataway هایی رو که داریم از از روی اینترفیسمون implement میکنیم مثل زرینپال و استرایپ و.. حالا فقط اون گیتوی رو به پیمنت سرویس تزریق میکنیم حالا اگه فردا مثلا گوگل پی هم اضافه شد میاییم بازهم از روی اینترفیس ایمپلمنت میکنیم اینجا ما کد تغییر ندادیم بلکه سیستم رو گسترش دادیم یعنی خود ocp نکته مهم : ocp هیچ وقت نمیگه ک کد قبلی رو تغییر نده بلکه میگه که : در نقاطی که احتمال تغییر زیاد هستش طراحی رو طوری انجام بده که تغییرات اینده بیشتر با اضافه کردن کد انجام بشه نه با تغییر دادن کد
بعضی وقتا فکرت خستس میشینی پشت سیستم همینطوری نگا میکنی بدون اینکه بدونی میخواستی چیکار کنی یه جور گم شدن خاصیه اخرشم میبندی میای اینور تا به خودت بیای
قسمت سوم و اخر SRP تا اینجا فهمیدیم که srp میشه یک دلیل برای تغییر در srp مسئولیت رو با تعداد متد ها نمیسنجیم مسئولیت هارا با چنج پترن و اکتور میسنجیم حالا امروز میریم سراغ همون یوزر سرویسی که قبلا مثالش رو زدیم کلاسمون این متد هارو داره: ریجستر ، لاگین ، چنج پسورد اپدیت پروفایل و دلیت اکانت حالا اینجا srp نقض شده نه به این دلیل که ۵ متد داریم بلکه به این دلیل که وقتی از دید مهندسی نکاه کنیم متد های ریجستر و لاگین و چنج پسورد مربوط میشن به authentication و دوتای دیگر به یوزر منیجمنت حالا طراحی بهتر چطوریه ؟ بیاییم قسمت های مربوط به auth رو در auth service و قسمت های مربوط به یوزر منیجمنت رو در یوزر سرویس بنویسیم یه نکته مهم : همیشه قرار نیست به خاطر srp همیشه کلاس ها یا سرویس های کوچک داشته باشیم و نکته دیگه اینکه قرار نیست برای هر متد یک سرویس بنویسیم ارتباط srp با DDD : هر دو تقریبا یک فلسفه مشترک دارند : چیزهایی که با هم تغییر میکنند، کنار هم بمانند؛ چیزهایی که مستقل تغییر میکنند، از هم جدا شوند srp در مقیاس کلاس هستش ddd در مقیاس سیستم
امروز درگیر داکرایز کردن پروژه بودم و مشغول نوشتن داکر فایل و docker compose بودم که بعد از کلی درگیری و جنگ دعوا با پروژه بالاخره تونستیم پروژه رو بیلد کنیم
امروز درگیره یه اروری بودم در کل بخوام بگم تو میدلور ولیدیشنم گذاشته بودم object.assign(req , parsed.data) منطقشم این بود ک دیتای پارس شده رو مستقیم روی req بریزم درصورتی که تو دیتام کوئری هم داشتم مشکل اینه که تو نسخه ۵ به بالاتر اکسپرس req.query یه getter هستش و setter نداره ینی در تیکه کد بالا که داریم سعی میکنیم مقدار یک getter رو عوض کنیم ارور میده من خودم ترجیح دادم که برای رفع این مشکل این قسمت هارو جدا جدا ست کنم چون دیگه پروژم خیلی جلو رفته و حوصله تغییر کنترلر هام رو نداشتم ولی روش بهتر و اصلیش اینه که برای کوئری یه پراپرتی اختصاصی داشته باشیم میبینی مثلا میزنیم req.user برا کوئری هم مثلا بزنیم req.validateQuery و روی اون پراپرتی کارامونو بکنیم که هم خوانایی رو بالا میبره هم از تداخل با دیگر پراپرتی تا حلوگیری میکنه و ..
تا اینجا فهمیدیم SRP : یک دلیل برای تغییر بر فرض مثال یک سرویس یوزر داریم که چهار متد ریجستر ، لاگین، چنج پسورد ، اپدیت پروفایل را دارد اکثر افراد میگن که این سرویس srp را نقض کرده چون ۴ تا متد داره اما باید ببینیم که چه چیزی باعث تغییر این کلاس میشود ؟ مثل : تغییر قوانین هرکدام از متد ها فرض کنیم شرکت تصمیم میگیره که رمز عبور از فردا حداقل ۱۲ کاراکتر باشه کدوم متد ها تغییر میکنن؟ ریجستر و چنج پسورد شاید لاگین هم تغییر کند اما اپدیت پروفایل نه ینی حتی داخل یک کلاس هم ممکنه بعضی متد ها باهم تغییر کنند و بعضی نه به قول uncle bob که میگه : یک کلاس باید فقط به یک Actor پاسخگو باشد منظور از اکتور شخص ، تیم یا نقش تجاری که درخواست تغییر میدهد مثلا تیم مالی ، تیم مارکتینگ و.. اگر دو تیم مختلف درخواست تغییر داده باشند اینجا srp نقض شده پس تعداد متد ها مهم نیست این الگوی تغییرات هستش که مهمه به نظرتون چند اکتور میتونن به یوزر سرویس درخواست تغییر بدن ؟
solid مجموعه ای از ۵ اصل برای کاهش کوپلینگ و افزایش کوهیژن و اسان تر کردن تغییرات هستش به بیان دیگه ینی چطوری کدی بنویسیم که با رشد پروژه به هم نریزه اصل اول : single resposibility principle چه مشکلیو حل میکنه ؟ کانفیلکت ها روی گیت ، مرج های سخت ، تست های سخت و شکسته ، باگ های جدید ، ترس از تغییر و کسترش پروژه رابرت سی مارتین تعریف مسئولیت رو اینطوری میگه ک : یک ماژول (به ماژول دقت کنید) فقط باید یک دلیل برای تغییر داشته باشد که این جمله کل srp هستش اما منظورش از یک دلیل چیه ؟ فک کن یه سرویس پیمنت داری حالا فردا چه چیزی باعث تغییر این سرویس میشه ؟ مثلا تغییر کارمزد ، مثلا اضافه شدن یه داخ پرداخت جدید ،... همه ی این تغییر ها در رابطه با یک موضوع هستند پس srp رعایت شده ولی مثلا اگه به پیمنت سرویسمون بیاییم یه متد سند ایمیل اضافه کنیم الان چیشد ؟ دوتا موضوع متفاوت و دو دلیل برای تغییر پس srp اینجا شکسته شده برای فهم و درک و پیاده سازیه بهتر اینطوری فک کنید که پروژتون خیلی بزرگه پس هر قسمت از پروژه بر عهده ی یه تیم جداست مثلا به تیم مسئولیت auth رو داره یه تیم مسئولیت storage رو داره پس ساختار پروژه باید طوری باشه که تیم auth فایل های مربوط به تیم storage رو دچار تغییر نکنه پس موقع نوشتن یک کلاس میگیم که کدوم تیم ها ممکنه این فایل رو تغییر بدن ؟ اگر بیشتر از یک تیم شد ینی دو دلیل اینجا برای تغییر داریم پس srp نقض شده srp میگه که مسئولیت هارو جدا کن ارتباطش با کوهیژن چیه؟ کوهیژن میگفت که همه چی باید مرتبط به هم باشه پس ینی یک دلیل برای تغییر باشه ارتباطش با کوپلینگ چیه ؟ کوپلینگ میگفت که وابستگی هات رو کمتر کن و اونایی که نیاز داری رو از بیرون بگیر اگه srp رو رعایت کنید خود به خود وابستگی ها هم کمتر میشن چون مسئولیت ها بیشتر و ساختار هامون متمرکز تر میشن ارتباطش با باندری ؟ باندری میکفت که هر بخش وارد مسئولیت بخش دیگه نشه srp هم همین رو در مقیاس یک کلاس میگه ارتباط با composition؟ وقتی مسئولیت ها جدا شن اون وقت میتونی اونارو کنار هم ترکیب کنی
видео или голосовое, без подписи
console.log❌ Logger✅ پروژه های پروداکشن ردی : اول کاری بگم ک کنسول لاگ رو معمولا برای دیباک و لاگ های موقتی استفاده میکنیم اما لاگ اصلی چیه لاگر ها رو حالا یا خودمون مینویسیم یا از کتابخونه های خفن استفاده میکنیم لاگر به نوعی حافظه برنامه ما هستش وقتی که برنامه مون درحال اجرا هستش اگه اتفاقی بیوفته این لاگ ها هستن که به ما نشون میدن چی بوده مثلا پروژت نصف شب به مشکل خورده و نمیدونی ازکجا بوده میای این لاگ هات رو نگا میندازی این لاگ ها هستن که نشون میدن تو کدوم مرحله کدت دچار مشکل شده برای چیا به درد میخورن : دیباگ ، مانیتورینگ ، بررسی مشکلات پروداکشن ، امنیت ، ثبت رویداد ها حالا چرا کنسول لاگ نه ؟ هیچ سطح بندی ندارد ، جستجو و فیلتر کردن سخته، ابزار های مانیتورینگ نمیتونن به خوبی ازش استفاده کنن و.. شما از کدوم کتابخونه استفاده میکنید؟