جلسه شماره 109رایگان

Dependency Injection | تزریق وابستگی

00:27:46

توضیحات جلسه

🎥 این ویدیو قسمت صد و دوم از بوت‌کمپ رایگان جاوا است. 📚 در این جلسه از پلی‌لیست Design Patterns یا الگوهای طراحی، سراغ یکی از مفاهیم بسیار مهم و کاربردی در طراحی نرم‌افزار می‌رویم: Dependency Injection یا تزریق وابستگی. Dependency Injection یکی از پایه‌ای‌ترین مفاهیم در طراحی کدهای تمیز، قابل تست و قابل نگهداری است. این مفهوم کمک می‌کند وابستگی بین کلاس‌ها را بهتر مدیریت کنیم، کدهای منعطف‌تری بنویسیم و از وابستگی مستقیم و سخت بین آبجکت‌ها جلوگیری کنیم. در این ویدیو ابتدا مسئله اصلی را بررسی می‌کنیم و می‌بینیم چرا وابستگی مستقیم بین کلاس‌ها می‌تواند در پروژه‌های واقعی مشکل‌ساز شود. سپس تعریف Dependency Injection را یاد می‌گیریم و با بازنویسی مثال Car، مفهوم تزریق وابستگی را به‌صورت عملی در جاوا بررسی می‌کنیم. در ادامه با اجزای اصلی DI، مزایا، انواع Dependency Injection و همچنین شرایطی که ممکن است استفاده نادرست از آن دردسرساز شود آشنا می‌شویم. در این جلسه یاد می‌گیریم: 🧩 مشکل وابستگی مستقیم بین کلاس‌ها در برنامه‌نویسی جاوا چیست 🚗 بررسی مثال Car و درک مسئله Coupling در طراحی نرم‌افزار 📘 Dependency Injection چیست و چرا در مهندسی نرم‌افزار اهمیت دارد 🔁 بازنویسی مثال Car با استفاده از DI برای کاهش وابستگی‌ها 👥 آشنایی با اجزای اصلی Dependency Injection و نقش هر بخش در طراحی ✅ بررسی مزایای تزریق وابستگی در کدنویسی تمیز و قابل نگهداری 🧪 نقش DI در افزایش تست‌پذیری کد و ساده‌تر شدن Unit Test 🛠️ بررسی انواع Dependency Injection در جاوا 📦 آشنایی با Constructor Injection، Setter Injection و Field Injection ⚠️ بررسی شرایطی که Dependency Injection می‌تواند مشکل‌ساز شود 🧠 در پایان نیز یک جمع‌بندی کامل از مفهوم DI و کاربرد آن در پروژه‌های واقعی خواهیم داشت. اگر در حال یادگیری جاوا، طراحی نرم‌افزار، الگوهای طراحی یا مفاهیم مهمی مثل SOLID و Clean Code هستید، درک درست Dependency Injection یکی از مهارت‌های ضروری شماست. این مفهوم در فریم‌ورک‌هایی مثل Spring و Spring Boot نیز نقش بسیار مهمی دارد و یکی از پایه‌های اصلی مدیریت وابستگی‌ها در پروژه‌های حرفه‌ای جاوا محسوب می‌شود. 📌یوتیوب: youtube.com/@farzadafi 📌آپارت: aparat.com/farzadafi 📌وب سایت: https://farzadafi.ir 📌 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi وب سایت: https://farzadafi.ir هر سوالی داشته باشید می‌توانید داخل این گروه بپرسید تا من یا مربی‌هایی که در گروه حضور دارن کمکتون کنیم :) 🎯 بوت‌کمپ رایگان جاوا آموزش جاوا پروژه محور برای یادگیری عمیق جاوا و ورود حرفه‌ای به بازار کار

جزوه و مستندات

مفاهیم کلیدی

  • Dependency Injection (DI)

الگویی که در آن یک object، وابستگی‌های موردنیاز خود را از بیرون دریافت می‌کند، نه اینکه آن‌ها را داخل class خودش بسازد. این کار tight coupling را کاهش می‌دهد و کد را قابل‌تست‌تر و قابل‌استفاده‌مجددتر می‌کند.

  • Dependency

objectای که یک class برای انجام کار خود به آن نیاز دارد؛ مثل Engine برای Car.

  • Tight Coupling

وابستگی شدید بین classها؛ به‌طوری‌که تغییر در یک implementation باعث تغییر در چندین class دیگر می‌شود.

  • Loose Coupling

طراحی‌ای که در آن classها تا حد ممکن به جزئیات پیاده‌سازی وابسته نیستند و تغییر یک بخش، اثر کمی روی بخش‌های دیگر دارد.

  • Inversion of Control (IoC)

اصلی که در آن مسئولیت ساخت و مدیریت objectها از کد برنامه به framework یا container منتقل می‌شود.

  • Constructor Injection

رایج‌ترین نوع DI که در آن وابستگی‌ها از طریق constructor به class داده می‌شوند.

  • Interface-based Design

طراحی‌ای که به‌جای وابستگی مستقیم به یک class مشخص، به interface وابسته می‌شود تا امکان جایگزینی implementationها فراهم شود.

  • Engine Interface

یک قرارداد مشترک برای همه موتور‌ها که امکان استفاده از چندین implementation مختلف را فراهم می‌کند.

  • LegacyEngine

یک implementation قدیمی از Engine که نمونه‌ای از وابستگی مستقیم و قدیمی را نشان می‌دهد.

  • NewEngine

یک implementation جدید از Engine که بدون تغییر در Car قابل جایگزینی است.

  • Reusability

قابلیت استفاده مجدد از یک وابستگی در چند class مثل Car، Bike و Scooter بدون تکرار کد.

  • Testability

وقتی وابستگی از بیرون تزریق می‌شود، در تست می‌توان به‌راحتی mock یا stub جایگزین کرد.

  • Maintainability

به‌دلیل کاهش وابستگی مستقیم، تغییر implementationها ساده‌تر و کم‌هزینه‌تر می‌شود.

موارد مصاحبه ای

  • Dependency Injection چیست؟

الگویی است که در آن object وابستگی‌های خود را از بیرون دریافت می‌کند، نه اینکه خودش آن‌ها را بسازد.

  • DI چه مشکلی را حل می‌کند؟

مشکل tight coupling را کاهش می‌دهد و طراحی را انعطاف‌پذیرتر، قابل‌تست‌تر و قابل‌نگهداری‌تر می‌کند.

  • تفاوت DI و IoC چیست؟

DI یک روش برای تزریق وابستگی است، اما IoC اصل کلی انتقال کنترل ساخت و مدیریت objectها به container یا framework است.

  • چرا وابستگی مستقیم مثل new LegacyEngine() مشکل‌ساز است؟

چون Car به یک implementation خاص وابسته می‌شود و تغییر موتور، نیاز به تغییر مستقیم در Car و سایر classها دارد.

  • چرا استفاده از interface در DI مهم است؟

چون class به قرارداد وابسته می‌شود نه به جزئیات پیاده‌سازی، و این باعث جایگزینی آسان implementationها می‌شود.

  • Constructor Injection چه مزیتی دارد؟

وابستگی را اجباری و شفاف می‌کند و class را از ابتدا در حالت معتبر می‌سازد.

  • Spring چگونه DI را انجام می‌دهد؟

IoC Container beanها را می‌سازد، وابستگی‌ها را شناسایی می‌کند و آن‌ها را به classهای موردنیاز تزریق می‌کند.

  • چرا DI تست‌پذیری را بهتر می‌کند؟

چون در تست می‌توان به‌جای وابستگی واقعی، نسخه‌های mock را تزریق کرد.

  • چرا DI نگهداری کد را بهتر می‌کند؟

چون تغییر در یک وابستگی باعث تغییر گسترده در classهای مصرف‌کننده نمی‌شود.

  • چرا Car نباید خودش Engine را بسازد؟

چون ساخت وابستگی باید از منطق استفاده جدا باشد تا طراحی loosely coupled باقی بماند.

  • مزیت استفاده مجدد از یک dependency در چند class چیست؟

کاهش تکرار، کاهش هزینه تغییر و یکپارچگی بیشتر در رفتار سیستم.

سناریو کاربردی

  • سناریوی خودرو و موتور

در مثال، Car برای کار کردن به Engine نیاز دارد. اگر Car خودش LegacyEngine را بسازد، به آن پیاده‌سازی خاص وابسته می‌شود. با DI، Engine از بیرون به Car تزریق می‌شود.

  • روند حل مسئله

ابتدا یک interface به نام Engine تعریف می‌شود تا قرارداد مشترک ایجاد شود. سپس چند implementation مثل LegacyEngine و NewEngine ساخته می‌شوند. بعد Car از طریق constructor وابستگی را دریافت می‌کند. در نتیجه، می‌توان بدون تغییر در Car، موتور متفاوتی تزریق کرد.

  • استفاده با Spring

در Spring، یک کلاس تنظیمات با @Configuration و یک متد @Bean برای ساخت Engine تعریف می‌شود. سپس Car با @Component و @Autowired وابستگی خود را دریافت می‌کند. در زمان اجرا، ApplicationContext Car را از container برمی‌دارد و متد drive() را اجرا می‌کند.

  • خروجی مفهومی

New Engine Started
Car is Running

این نشان می‌دهد که Car بدون وابستگی مستقیم به پیاده‌سازی خاص موتور، با Engine تزریق‌شده کار می‌کند.

بیشتر بدانید

  • نکته طراحی

به‌جای وابستگی به classهای concrete، تا حد امکان به interface وابسته شوید.

  • نکته معماری

DI در پروژه‌های enterprise Java و مخصوصاً با Spring یک الگوی بسیار رایج است.

  • نکته تست

اگر وابستگی‌ها از بیرون تزریق شوند، در unit test به‌راحتی می‌توان mock object جایگزین کرد.

  • نکته توسعه

یک dependency مثل Engine می‌تواند در چند class مانند Car، Bike و Scooter استفاده شود، بدون اینکه منطق آن‌ها به پیاده‌سازی خاصی وابسته باشد.

  • نکته Spring

IoC Container فقط object نمی‌سازد؛ بلکه چرخه عمر beanها را هم مدیریت می‌کند.

  • نکته فایل pom.xml

برای استفاده از قابلیت‌های Spring MVC باید dependency مناسب را در pom.xml اضافه کرد.