به نظر من یکی از مشکلات شایع بین مهندسین نرمافزار مشغول به کار در ایران، ولع بیش از حد به یادگیری تکنولوژیهای مختلف و رها کردن مطالعه عمیق راجع به مباحث پایهای در حوزه علوم و مهندسی کامپیوتره. البته شاید فرم بازار ایران و نحوه انجام مصاحبهها که معمولاً تکنولوژی محور انجام میشه در این قضیه بیتاثیر نباشه (هر چند در سالهای اخیر شاهد این هستیم که مصاحبههای مبتنی بر حل مساله هم در بازار انجام میشه). در حالی که در اغلب موارد مطالعه کتابهای مربوط به مهندسی نرمافزار و برنامهنویسی مثل کتاب معروف 'کد تمیز' (Clean Code) بدون تامل عمیق در مباحث پایهای علوم و مهندسی کامپیوتر الزاما از ما مهندس نرمافزار بهتری نمیسازه.
من به شخصه غالباً دو جریان شایع برای معرفی و مطالعه کتاب در بین مهندسین نرمافزار ایران مشاهده میکنم:
۱- طرفداران پر و پا قرص کتابهای آقایان رابرت سی مارتین یا همون عمو باب (Uncle Bob)، مارتین فاولر، کنت بک و ...: این دوستان بیشتر مطالعه کتابهایی از جنس Clean Code یا Clean Architecture از عمو باب یا Refactoring از مارتین فاولر و یا Test Driven Development از کنت بک رو تبلیغ میکنند.
۲- طرفداران پر و پا قرص فضای گوگلی و سیلیکون ولیوار: این دوستان بیشتر کتابهایی مثل Software Engineering at Google یا Site Reliability Engineering یا Continuous Delivery رو برای مطالعه توصیه میکنند.
البته این دو دسته همواره از هم جدا نیستند و در برخی موارد ممکنه فردی شیفته هر دو تفکر باشه ولی اگه در محیطهای شرکتهای ایرانی رو چرخی بزنید معمولا این دو گرایش برای مطالعه رو به سادگی خواهید دید. خب من دو تا خبر براتون دارم یکی خوب و یکی بد! خبر خوب: خوندن این کتابها معمولا مفیده و کیفیت شما رو به عنوان مهندس نرمافزار بالا میبره حتی به طرز قابل توجهی کلمات کلیدی خوبی برای خرج کردن در مباحث و مصاحبهها به شما میده. اما خبر بد: کتابهای خیلی مهمتری از این دو دسته وجود داره که اگه اونها رو مطالعه نکردید بهتره اول اونا رو مطالعه کنید و بعد بیاید سراغ این دسته کتابها! البته شاید بد نباشه اول تعریف من رو از مهندسی نرمافزار و مهندس نرمافزار بخونید؛ اگه پستهای من رو در لینکدین تعقیب نکردید و حوصله داشتید دو پست زیر رو در لینکدین ببینید:
۱- تعریف نرمافزار
۲- تعریف مهندسی نرمافزار و مهندس نرمافزار
اگه توجه کرده باشید در پاراگراف اول من به حوزه علوم و مهندسی کامپیوتر اشاره کردم نه فقط مهندسی. الان برای رعایت اختصار راجع به تفاوت علم و مهندسی صحبت نمیکنیم ولی از من بپذیریذ که یک مهندس خوب کامپیوتر باید به علوم پایه کامپیوتر هم تسلط نسبی داشته باشه. معمولاً کسانی که در دانشگاه رشتههای مهندسی کامپیوتر یا علوم کامپیوتر خوندند یک سری دروس میگذرونند که برخی از این دروس خیلی مهمه و از دید من به نوعی پایههای لازم برای یه مهندس نرمافزار خوب رو میسازه، اما متاسفانه تعداد زیادی از مهندسین فعال در صنعت نرمافزار ممکنه فارغالتحصیل کارشناسی کامپیوتر نباشند یا اگه هم دوره کارشناسی کامپیوتر رو گذروندند به نوعی این دروس رو به صورت جدی مطالعه نکردند.
خب، بیشتر از این بهتره حاشیه نریم و بریم سر اصل مطلب! حالا باید روی چه کتابهایی، خوب وقت بذاریم؟ از دید من هر مهندس نرمافزار باید توی ۷ حوزه (یا به نوعی درس) مطالعه خوبی داشته باشه و حداقل یه کتاب خوب خونده باشه:
۱- برنامهنویسی
۲- ساختار دادهها و الگوریتم
۳- معماری کامپیوتر
۴- پایگاه داده
۵- سیستم عامل
۶- شبکههای کامپیوتری
۷- مهندسی نرمافزار
اجازه بدید یکی یکی بهشون بپردازم و برای هر کدوم حداقل یه کتاب خوب معرفی کنم.
۱- زبان برنامهنویسی:
در هر زمینهای از نرمافزار که مشغول باشید از توسعهدهنده بکاند گرفته تا دواپس و UX یا تحلیلگر، تسلط نسبی (یا حداقل آشنایی) به یک زبان برنامهنویسی در طی کار به شما کمک قابل توجهی میکنه. حالا با توجه به موقعیت شغلی این تسلط میتونه متغیر باشه ولی اینکه یک فردی در صنعت نرمافزار مشغول باشه و با همه زبانهای برنامهنویسی بیگانه باشه اصلاً خوب نیست. حالا اینکه چه زبانی یاد بگیریم پاسخش اینه که هر زبانی که بیشتر دوست دارید. برای شروع پایتون زبان سادهتریه و اگه بخوام کتابی در این زمینه معرفی کنم من کتاب 'پایتون به روش سخت' رو پیشنهاد میکنم:
Learn Python the Hard Way by Zed Shaw
۲- ساختار دادهها و الگوریتم
زمانی که ما درس میخوندیم دو درس جدا در این زمینه داشتیم یکی ساختمان داده و یکی هم طراحی الگوریتم. الآن بعضی از دانشگاهها این دو درس رو ادغام کردند و بعضی همچنان جداگانه ارائه میدند. هدف از دونستن این دو حوزه اینه که یک مهندس نرمافزار هم تسلط خوبی به آرایش و ساختار دادهای در حافظه داشته باشه و هم با تکنیکهای مختلف حل مساله (مثلاً روشهای حریصانه) آشنایی داشته باشه. اگه شک دارید که آیا این مباحث رو به خوبی بلدید، سوالات زیر رو چک کنید:
- آیا قادر به تعیین پیچیدگی محاسباتی و فضایی یک راهحل هستید؟
- آیا فرق بین ساختارهای درخت دودویی و جداول درهمسازی رو میدونید؟
- آیا میتونید برای نگهداری یک گراف در حافظه ساختاری مناسب طراحی کنید؟
- آیا با برنامهنویسی پویا آشنایی دارید؟
- آیا میدونید مرتبسازی درجا چیه؟
اگه فکر میکنید در پاسخدهی به سوالات بالا ضعف دارید باید یه نگاه مجدد به مباحث این حوزه بندازید. پیشنهاد من کتاب آقای ویس هست:
Data Structures and Algorithm Analysis in Java by Mark Weiss
و اگه علاقه و حوصله بیشتری دارید، کتاب آقای کلینبرگ هم عالیه:
Algorithm Design by Jon Kleinberg and Eva Tardos
۳- معماری کامپیوتر
هر چقدر هم که ما توجهمون معطوف به نرمافزار باشه برای توسعه و اجرای بهینه نرمافزارها باید دانش نسبی از مفاهیم پایهای معماری کامپیوتر هم داشته باشیم. برای سنجش خودتون بد نیست سوالات زیر رو مرور کنیم:
- چقدر از ساختار حافظه اطلاع داریم؟
- فرق بین دیسک سخت و اساسدی چیه؟
- هایپرتردینگ چیه و چه تاثیری در اجرای برنامهها داره؟
- وقفههای سختافزاری چطوری هندل میشن؟
- تفاوت بین معماری RISC و CISC چیه؟
اگه فکر میکنید در پاسخدهی به سوالات بالا دچار تردید هستید بد نیست به کتاب معماری هنسی و پترسون مراجعه کنید:
Computer Architecture: A Quantitative Approach by John L. Hennessy , David A. Patterson
۴- پایگاه داده
بدون شک پایگاه داده قسمتی از اجزای سه گانه تشکیل نرمافزاره و یک مهندس نرمافزار باید دید مناسبی نسبت به ذخیره و بازیابی داده داشته باشه. مخصوصاً در حوزه توسعه و نگهداشت نرمافزار تسلط عمیق به مفاهیم پایگاه داده ضروریه. سوالات زیر رو نگاه کنید:
- فرمهای نرمالسازی چیه و به چه کاری میاد؟
- تراکنش چیه و باید چه ویژگیهایی داشته باشه؟
- انواع روشهای قفلگذاری در پایگاه داده چیه؟
- سطوح انزوا در دیتابیس چیه و هر کدوم چه ویژگیهایی دارن؟
- چه تفاوتهایی بین پایگاه دادههای مبتنی بر سند و ستونی وجود دارد و هر کدوم چه کاربردی دارن؟
اگه فکر میکند مطالعه خوبی در این حوزه نداشتید حتماً باید به فکر مطالعه جدی باشید و من کتاب آقای سیلبرشاتز رو پیشنهاد میدم:
Database System Concepts by Avi Silberschatz and etc
۵- سیستم عامل
سیستم عامل معمولاً خیلی مظلوم و مغفول میمونه! اغلب افراد فکر میکنن تسلط بر سیستم عامل یعنی بلد باشیم با لینوکس کار کنیم در حالی که مفاهیم پایه مطرح شده در سیستم عامل در حل بسیاری از مشکلات و مسائل نرمافزار نقش کلیدی دارن. سوالات زیر رو ببینید:
- آیا میدونید بنبست چیه و چه فرقی با لایولاک داره؟
- آیا اطلاع دقیقی از قفلگذاری و روشهای تضمین انحصار متقابل دارید؟
- چقدر راجع به حافظه مجازی و تاثیر اون در سیستم عامل دارید؟
- فرق بین پردازه و ریسمان رو میدونید؟
- تفاوت فایل سیستمهای متداول رو با جزئیات میدونید؟
اگه با دیدن این سوالات فکر میکنید که نیاز به مطالعه بیشتر و ترمیم در این حوزه دارید کتاب سیستم عامل آقای سیلبرشاتز (البته با سیلبرشاتز قبلی فرق داره) انتخاب خوبیه:
Operating System Concepts by Abraham Silberschatz and etc
۶- شبکههای کامپیوتری
این حوزه برای خودش یه جواریی میتونه یه رشته محسوب بشه و مباحث به شدت جذاب و مهندسی داره. اگه در زمینه راهبری سیستم و نگهداشت کار میکنید حتماً قبل از خوندن کتابهای حول دواپس و اسآرای حتما دانشتون در این حوزه رو تقویت کنید و در حالت کلی هم که به نظر من دونستن مفاهیم پایه شبکه برای یه مهندس نرمافزار خیلی راهگشاست. سوالات زیر رو برای محک ببینید:
- آیا میتونید تمام اتفاقاتی رو که از وارد کردن یه آدرس در مرورگر تا باز شدن اون صفحه رخ میده رو بیان کنید؟
- آیا تجربه کار با ساکتها رو دارید؟
- آیا راجع به مکانیزمهای کنترل ازدحام در TCP اطلاع دارید؟
- آیا میتونید فرق بین پروتکلهای BGP و OSPF رو توضیح بدید؟
- راجع به کدهای وضعیت HTTP و کاربرد هر کدوم میتونید توضیح بدید؟
اگه فکر میکنید که دانش عمیقی در این زمینه ندارید، پیشنهاد من مطالعه کتاب آقای کورُسه هست:
Computer Networking: A Top-down Approach by Jim Kurose and Keith Ross
۷- مهندسی نرمافزار
مباحث مربوط به مهندسی نرمافزار بسیار گسترده است ولی حداقل مفاهیمی مثل فرآیندهای چابک، کنترل و تضمین کیفیت، نگهداشت و ... به درد هر مهندس نرمافزار در هر لایه تولید نرمافزار میخوره. سوالات زیر رو مرور کنید:
- چرا باید از فرآیند چابک برای توسعه نرمافزار استفاده کنیم؟
- برای چی باید تست بنویسیم؟
- تعریف شما از کد با کیفیت چیه؟
- چرخه نرمافزار رو میتونید توضیح بدید؟
- برای مستندسازی از چه روشها و ابزارهایی باید استفاده کنیم؟
حتی اگه جواب سوالات بالا رو بلدید مرور یه کتاب پایهای در این زمینه کمککننده است. پیشنهاد من کتاب آقای پرسمنه:
Software Engineering: A Practitioner's Approach by Roger Pressman
قبل از اتمام این مقاله میخام چند نکته رو مطرح کنم:
- هدف از این نوشته، زیر سوال بردن کتابهای دو دسته اشاره شده در ابتدای مقاله نیست بلکه مقصود من اینه که برای مطالعه کتابهای خوب پیشرفته، اول باید زیربنای مناسبی داشته باشیم. بعید نیست اگه از کسانی مثل خود آقای مارتین فاولر هم بپرسید که مثلا 'من ضعف جدی در مفاهیم پایگاهداده دارم به نظر شما اول این ضعف رو جبران کنم یا کتاب بازآرایی کد شما رو بخونم؟' جواب خود مارتین فاولر هم این باشه که اول پایگاه داده بخون!!!
- پیشرفت به صورت اصولی قاعدتاً زمان و انرژی بیشتری میبره و شما به جای انتخاب این مسیر میتونید با مطالعه دو دسته کتابی که در اول بحث اشاره کردم کلمات کلیدی و تکنیکهای عامهپسند بیشتری کسب کنید ولی به نظر من مطالعه بیشتر بدون داشتن اطلاعات پایه الزاما نتیجه خوبی نداره شاید حتی نتیجه بدی هم بده.
- اگه فکر میکنید در اغلب این ۷ حوزه ضعف دارید جای نگرانی نیست و این به این معنی نیست که شما مهندس بدی هستید! صرفا باید وقت کافی برای ترمیم این مباحث بذارید تا تبدیل به فرد بهتری بشید.
- کتابهای اشاره شده حجیم هستند (معمولا بالای ۷۰۰ صفحه) یعنی برای مطالعه این ۷ مبحث چیزی حدود ۵۰۰۰ صفحه کتاب باید بخونید که حجم زیادی میشه اگه فرصت این کار رو ندارید یا نمیتونید انقدر انرژی بذارید حداقل سعی کنید فصلهای ابتدایی هر کتاب رو بخونید مثلا ۱۵۰-۲۰۰ صفحه. ولی در هر صورت حتی برای مطالعه ابتدایی خودتون رو برای خوندن ۱۰۰۰ صفحه آماده بکنید :)
امیدوارم این مقاله یه نقشه راه ساده برای یادگیری مباحث پایهای در زمینه مهندسی نرمافزار در اختیارتون گذاشته باشه و در پایان تاکید میکنم که این نظر منه و ممکنه راههای بهتری هم باشه. در ضمن من در یک ویدیو مفصل راجع به کتابهایی که بهتره در دوره کارشناسی کامپیوتر بخونیم، صحبت کردم که شاید دیدن اون هم خالی از لطف نباشه. این ویدیو رو میتونید در این لینک پیدا کنید:
https://www.youtube.com/watch?v=RwdvU-BSynw