«اولین پروژه برنامه نویسی» تو وقتی به نمونه کار تبدیل می شود که یک نفر دیگر بتواند آن را بدون اعتماد به حرف تو بررسی کند. سه تکه لازم است: کد روی یک مخزن عمومی با تاریخچهٔ واقعی، یک فایل README خوانا که بگوید چه چیزی را خودت نوشتی، و یک نشانی زنده که در مرورگر باز می شود و کار می کند. هر چیزی کم تر از این سه، تمرین است نه نمونه کار — و تمرین، مرز بین «دوره را گذراندم» و «این را ساختم» را نشان نمی دهد.
تفاوت تمرین و نمونه کار در یک نگاه
هر دو حالت یک پروژهٔ کوچک است؛ تفاوت در این است که کدام شان برای فرد دیگری قابل بررسی است. کارفرما یا مشتری روی صفحهٔ تو حضور ندارد؛ هرچه در رزومه بنویسی، باید پشتش چیزی باشد که خودش بتواند باز کند. جدول زیر همان تفاوت را نشان می دهد:
| تمرین کلاسی یا پروژهٔ دوره | نمونه کار قابل ارائه |
|---|---|
| روی رایانهٔ خودت می ماند؛ کسی نمی بیندش | یک نشانی زنده دارد که در مرورگر باز می شود |
| تاریخچهٔ گیت یا وجود ندارد، یا یک کامیت به نام «final» | تاریخچهٔ کامیت معنادار که روند کار را نشان می دهد |
| مرحله به مرحلهٔ دوره، متناسب با آموزش پیش رفته | خودت تصمیم گرفته ای چه چیزی ساخته شود و چرا |
| بدون توضیح: «چیست؟ چطور اجرا می شود؟» | README می گوید چیست، چطور اجرا می شود، چه چیزی کار توست |
| وقتی خطا می خورد، کسی خبردار نمی شود | تست خودکار دارد و می دانی کدام بخش سالم است |
نکتهٔ مهم این جدول، ستون سمت راست نیست؛ ستون سمت چپ است. بیش تر پروژه های تازه کارها در ستون چپ جا می مانند و همان جا تمام می شوند. اگر همین حالا یک پروژهٔ نیمه کاره روی رایانه ات داری، کاری که این مقاله می گوید را می توانی روی همان انجام بدهی؛ نیازی نیست از صفر شروع کنی. اگر هنوز زبان و مسیر را انتخاب نکرده ای، اول از شروع برنامه نویسی از صفر عبور کن و بعد برگرد.
انتخاب اولین پروژه با مقیاس درست
مشکل بیش تر تازه کارها انتخاب نکردن نیست؛ بزرگ انتخاب کردن است. «یک شبکهٔ اجتماعی مثل اینستاگرام» پروژهٔ اول نیست، پروژهٔ دهم است. معیارهای یک پروژهٔ اول درست:
- یک مسئلهٔ مشخص: پروژه باید به یک جملهٔ کوتاه جواب بدهد. اگر توضیحش سه خط می شود، برای نسخهٔ اول بزرگ است.
- یک کاربر واقعی: خودت، یک مغازهٔ محلی، یک هم کلاسی، یک گروه تلگرامی. کاربر واقعی اجازه نمی دهد پروژه در هوا معلق بماند.
- قابل تمام شدن در دو تا چهار هفته: پروژهٔ تمام شدهٔ کوچک از پروژهٔ بزرگ نیمه کاره بی نهایت قوی تر است.
- یک چیز جالب در دلش: یک کوئری پیچیده، یک الگوریتم زمان بندی، یک بخش احراز هویت. همین یک تکه است که در مصاحبه دربارهٔ آن حرف می زنی.
- محدودهٔ نوشته شده: قبل از اولین خط کد، بنویس چه چیزی در نسخهٔ اول هست و چه چیزی نیست.
همین محدودهٔ نوشته شده ساده ترین چیزی است که پروژهٔ تازه کار را نجات می دهد؛ چون هر وقت وسوسه شدی قابلیت اضافه کنی، به فایل برمی گردی و می بینی در «خارج از محدوده» نوشته شده است:
# محدودهٔ نسخهٔ ۱ — بیشتر از این ساخته نمی شود
مسئله: مغازه دار سفارش های تلفنی را روی کاغذ می نویسد و بعضی را دو بار می نویسد.
کاربر: یک نفر (خودِ مغازه دار). ثبت نام چندکاربره لازم نیست.
داخل محدوده — دقیقاً چهار قابلیت:
1. ثبت سفارش: نام مشتری، شماره تماس، اقلام، مبلغ
2. فهرست سفارش های امروز
3. تغییر وضعیت سفارش: در انتظار / آماده / تحویل شده
4. جمع مبلغ سفارش های امروز
خارج از محدوده (برای نسخه های بعدی):
پرداخت آنلاین · پیامک · اپ موبایل · ورود با گوگل · پنل مدیریت جدا · نمودار فروش
این فایل خودش یک برگهٔ امتیاز است: هر بار به «خارج از محدوده» چیزی اضافه می کنی، داری پروژهٔ اولت را بزرگ تر از توانت می کنی.
سه ایدهٔ پیشنهادی با محدودهٔ دقیق کار
سه الگو زیر را می شود با هر زبانی ساخت. هر کدام را انتخاب کردی، همان محدودهٔ نوشته شده را نگه دار:
| پروژه | حد اقل قابلیت ها | چه چیزی را ثابت می کند |
|---|---|---|
| ابزار شخصی با کاربرد روزانه مثلاً سامانهٔ پیگیری عادت یا دفتر خرج | ورود داده، فهرست، ویرایش و حذف، یک گزارش سادهٔ جمع بندی شده | کار کردن با فرم، اعتبارسنجی، ذخیره سازی، کوئری جمع بندی — چهار مهارت پایهٔ هر پروژهٔ واقعی |
| سامانهٔ نوبت دهی برای یک کسب وکار واقعی آرایشگاه، دندان پزشک، آموزشگاه | تقویم ساده، ثبت نوبت با تداخل گیری، وضعیت نوبت، فهرست روز | منطق کسب وکار: جلوگیری از تداخل دو نوبت، اعتبارسنجی سمت سرور، کار با تاریخ و ساعت |
| وب سرویس با مستندات یک API کوچک بدون رابط گرافیکی | سه تا پنج نقطهٔ پایانی، احراز هویت با کلید، صفحهٔ مستندات، پاسخ های خطای استاندارد | طراحی رابط، نسخه بندی، مستندسازی و تفکر دربارهٔ مصرف کنندهٔ کد — همان چیزی که تیم ها دنبالش هستند |
هر سه الگو یک ویژگی مشترک دارند: قابل تمام شدن اند. اگر ایدهٔ تو در هیچ کدام جا نمی شود، احتمالاً ایده بد نیست — محدوده اش بزرگ است. تا پروژه های بزرگ را به نسخهٔ اول و دوم بشکنی، هیچ وقت لینک زنده نداری.

ساخت پروژه از صفر: ساختار پوشه و اولین کامیت
ساختار پوشه را قبل از کد بچین. پوشهٔ مرتب، تفاوت یک پروژهٔ قابل بررسی با یک پوشهٔ پر از فایل را می سازد؛ کسی که مخزن را باز می کند، اول ساختار را می بیند و بعد کد را می خواند:
mkdir shop-orders && cd shop-orders
git init -b main
mkdir -p app/Models app/Http database tests public docs
# اسکلت اولیهٔ فایل ها، قبل از هر منطقی
touch docs/SCOPE.md README.md .gitignore
touch app/Models/Order.php app/Http/OrderController.php
touch database/schema.sql tests/OrderTest.php
سه چیز از همان اول باید خارج از مخزن بماند: پکیج های نصب شده، فایل های موقت، و مهم تر از همه .env — فایلی که رمز پایگاه داده و کلیدهای API در آن است. اشتباه رایج و پرهزینهٔ تازه کارها کامیت کردن همین فایل است؛ اگر باز کنی و بگذاری، حتی حذفش هم کافی نیست و باید رمزها را عوض کنی.
# .gitignore
/vendor/
/node_modules/
.env
.env.*
!.env.example
/storage/logs/*.log
/tmp/
.DS_Store
فایل .env.example برعکس، باید در مخزن باشد: همان کلیدها با مقدار خالی. کسی که پروژه را دریافت می کند، از همین فایل می فهمد چه متغیرهایی لازم است. بعد از آن، کامیت ها را کوچک و معنادار بزن تا تاریخچه قابل خواندن باشد:
git add .gitignore README.md docs/SCOPE.md
git commit -m "chore: ساختار اولیهٔ پروژه، محدودهٔ نسخهٔ ۱ و gitignore"
git add app/Models/Order.php database/schema.sql
git commit -m "feat(order): مدل سفارش و طرح جدول سفارش ها"
git add app/Http/OrderController.php
git commit -m "feat(order): ثبت سفارش با اعتبارسنجی سمت سرور"
git log --oneline
# a91f2c7 feat(order): ثبت سفارش با اعتبارسنجی سمت سرور
# 4be0d18 feat(order): مدل سفارش و طرح جدول سفارش ها
# 1c73a55 chore: ساختار اولیهٔ پروژه، محدودهٔ نسخهٔ ۱ و gitignore
آن سه خط خروجی git log، خودشان یک نمونه کار کوچک اند: نشان می دهند کار را به قدم های فهمیدنی شکسته ای. مقایسه کن با مخزنی که در آن یک کامیت به نام «upload» هست — کارفرما از آن هیچ چیزی نمی فهمد.

README که کارفرما را متقاعد می کند
در نُه مورد از ده مورد، README تنها چیزی است که از پروژهٔ تو خوانده می شود. طولانی نوشتنش لازم نیست؛ منظم بودنش لازم است. این قالب را کپی کن و جای نگهدارها را پر کن:
# سامانهٔ سفارش فروشگاه — نسخهٔ ۱
ثبت و پیگیری سفارش های تلفنی یک فروشگاه کوچک، در یک صفحه، بدون کاغذ.
**نشانی زنده:** https://demo.example.ir
**کاربر آزمایشی:** demo / رمز: demo1234
## چه چیزی کار می کند
- ثبت سفارش با اعتبارسنجی نام، شماره و مبلغ
- فهرست سفارش های امروز با مرتب سازی بر اساس مبلغ
- تغییر وضعیت سفارش: در انتظار، آماده، تحویل شده
- جمع مبلغ سفارش های امروز
## چطور اجرا می شود
دستورها در بخش «اجرای محلی» آمده است. پیش نیاز: PHP نسخهٔ ۸ و MySQL.
## تست
چهار تست برای منطق سفارش نوشته شده است. اجرا: دستور تست در بخش «اجرای محلی».
## این پروژه چه بخشی کار خودم است
طراحی جدول سفارش ها، منطق تداخل سفارش ها و اعتبارسنجی سمت سرور
را خودم نوشتم. قالب ظاهری از یک قالب آمادهٔ رایگان گرفته شده است.
## گام بعدی
افزودن گزارش هفتگی و اعلان وضعیت (نسخهٔ ۲).
بخش «این پروژه چه بخشی کار خودم است» مهم ترین خط این فایل است. اگر از یک آموزش یا قالب آماده استفاده کرده ای، همان را بنویس. صداقت در همین یک خط، اعتبارِ همهٔ بقیهٔ فایل را تعیین می کند؛ اگر کارفرما بعداً بفهمد بخشی را از دوره آورده ای و گفته ای کار خودت است، اعتماد از دست می رود که بازساختنش سخت تر از نوشتن آن خط بود. برای کامل شدن، بخش اجرای محلی باید دستورهای واقعی و قابل کپی باشد:
# اجرای محلی (این بلوک را در README بگذار)
git clone https://github.com/<username>/shop-orders.git
cd shop-orders
cp .env.example .env # سپس مقدارهای پایگاه داده را پر کن
composer install # یا: npm install
php database/migrate.php # ساخت جدول ها
php -S localhost:8000 -t public
# اجرای تست ها
./vendor/bin/phpunit --testdox
هیچ کارفرمایی وقت نمی گذارد تا بفهمد پروژهٔ تو چطور اجرا می شود. اگر با سه دستور اجرا نشود، در عمل اجرا نمی شود و همان جاست که بررسی متوقف می شود.
انتشار روی مخزن عمومی و یک نشانی زنده
کد در مخزن عمومی، دیده شدنی است؛ ولی کد به تنهایی «کار می کند» را ثابت نمی کند. اولین کاری که هر کارفرمای فنی می کند این است که لینک را باز می کند. اگر لینک نداری، کد را با فرض «هیچ وقت اجرا نشده» می خواند. برای دموی نسخهٔ اول، همان میزبان رایگان یا ارزان کافی است؛ یک دامنهٔ ساده هم لازم نیست:
git remote add origin https://github.com/<username>/shop-orders.git
git branch -M main
git push -u origin main
# یک برچسب برای نسخهٔ منتشرشده، تا کارفرما بفهمد این نقطه «آماده» است
git tag -a v1.0.0 -m "نسخهٔ ۱: ثبت و پیگیری سفارش، چهار قابلیت محدودهٔ نسخهٔ ۱"
git push origin v1.0.0
بعد از انتشار، لینک زنده را خودت تست کن — قبل از این که در رزومه بگذاری. یک دموی خراب (صفحهٔ سفید، خطای ۵۰۳، دکمهٔ بی کار) از نبودِ دمو بدتر است، چون نشان می دهد چیز منتشرشده را بررسی نمی کنی:
# پیش از فرستادن لینک، خودت بررسی کن
curl -s -o /dev/null -w "%{http_code}\n" https://demo.example.ir
# 200
# و یکی از راه های واقعی پروژه را هم امتحان کن، نه فقط صفحهٔ اصلی
curl -s https://demo.example.ir/api/orders | head -c 300
از تمرین تا نمونه کار: نسخهٔ ۲ و نسخهٔ ۳
یک پروژه را چند بار بازسازی نکن که فقط «قابلیت» اضافه شود؛ هر نسخه باید یک سطح مهندسی تازه را نشان بدهد. نسخهٔ یک: کار می کند. نسخهٔ دو: تست دارد و کدش مرتب شده. نسخهٔ سه: خودکار تست و منتشر می شود. همین سه پله از سه پروژهٔ جدا ارزش بیش تری دارد، چون هر پله چیزی را ثابت می کند که پلهٔ قبل نداشت.
شروع نسخهٔ دو، نوشتن تست برای همان قابلیت هایی است که در محدوده نوشتی. تست لازم نیست پیچیده باشد؛ باید واقعاً اجرا شود و یک رفتار را بسنجد:
<?php
// tests/OrderTest.php — سنجش منطق سفارش، بدون نیاز به مرورگر
use PHPUnit\Framework\TestCase;
final class OrderTest extends TestCase
{
public function test_order_total_is_sum_of_items(): void
{
$order = new Order(items: [120000, 80000, 50000]);
$this->assertSame(250000, $order->total());
}
public function test_rejects_order_with_empty_customer_name(): void
{
$this->expectException(InvalidArgumentException::class);
new Order(items: [1000], customerName: '');
}
}
و گام سوم، همان چیزی که بیش تر نمونه کارهای تازه کارها ندارند: خودکارسازی. یک فایل CI کوچک که با هر بار فرستادن کد، تست ها را اجرا می کند و اگر سبز بودند منتشر می کند. برای کارفرما این یعنی «کد این آدم قابل اعتماد است»، نه فقط «کد این آدم کار می کند»:
# .github/workflows/ci.yml — تست خودکار و انتشار نسخهٔ آزمایشی
name: tests
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- run: composer install --no-interaction --prefer-dist
- run: ./vendor/bin/phpunit --testdox
همین فایل، در عمل چند تست PHPUnit و یک گام نصب کامپوزر است. ارزشش در تعداد خط ها نیست؛ در این است که در صفحهٔ مخزن یک نشان سبز دیده می شود که خودش دارد دربارهٔ کار تو حرف می زند. هیچ کس نمی تواند ادعای سبز بودن یک CI را جعل کند، و همین آن را به شاهد تبدیل می کند.

جواب سؤال «سابقهٔ کاری نداری؟»
این سؤال همیشه پرسیده می شود، پس جواب آماده داشته باش. سه جملهٔ زیر قالب اند؛ با واقعیت پروژهٔ خودت پرشان کن و چیزی که انجام نداده ای را ننویس — اولین سؤال بعدی، جزئیات است:
- در رزومه: «پروژهٔ [نام پروژه]: سامانهٔ [یک جملهٔ کارکرد] برای [کاربر واقعی]؛ شامل [یک تکهٔ فنی مشخص] و تست خودکار. نشانی زنده: [لینک]»
- در پیام به کارفرما: «سابقهٔ کاری تمام وقت ندارم، ولی این پروژه را از صفر برای [کاربر] ساختم و همین حالا آنلاین است: [لینک]. اگر بخواهی، پنج دقیقه دربارهٔ تصمیم های فنی ام — از جمله [یک تصمیم مشخص] — حرف می زنم.»
- در مصاحبه: «بزرگ ترین مسئله ای که در این پروژه حل کردم [مسئله] بود. اول راهِ [راهِ اول] را امتحان کردم و به [دلیل فنی] جواب نداد؛ بعد به [راه دوم] رسیدم.»
قالب سوم قوی ترین است، چون چیزی می گوید که در هیچ رزومه ای نوشته نمی شود: مسیر تصمیم گیری. اگر پروژه ات یک شکست کوچک در دلش داشته باشد و تو بتوانی توضیحش بدهی، همان جلسهٔ مصاحبه را می برد — چون نشان می دهد وقتی چیزی جواب ندهد، متوقف نمی شوی. اگر می خواهی بدانی چرا کارفرمای فنی نمونه کار زنده را به مدرک ترجیح می دهد، این موضوع را در برنامه نویسی بدون مدرک دانشگاهی جداگانه باز کرده ام.
اشتباه های رایجی که پروژهٔ خوب را بی اثر می کند
- اسکرین شات به جای لینک. تصویر نه اجرا می شود و نه کد را نشان می دهد؛ ارزش اثباتی اش نزدیک صفر است.
- مخزن خالی یا تک کامیتی. اگر همهٔ کد در یک کامیت به نام «final» باشد، تاریخچه هیچ چیزی از کار کردن تو نشان نمی دهد.
- کد کپی شده از آموزش بدون درک. در مصاحبهٔ فنی، یک سؤال از یک بخش دلخواه کدت کافی است تا معلوم شود.
- کامیت شدن
.env. رمز پایگاه داده و کلیدهای API در تاریخچهٔ عمومی می ماند؛ حتی اگر بعداً پاکش کنی، باید همهٔ رمزها را عوض کنی. READMEدو خطی. «پروژهٔ من برای درس X» چیزی به کارفرما نمی گوید. پنج دقیقه وقت گذاشتن روی README از پنج ساعت کد اضافه کردن مؤثرتر است.- لینک زندهٔ خراب. دمویی که ۵۰۳ می دهد از نداشتن دمو بدتر است.
- پانزده پروژهٔ نیمه کاره. یک پروژهٔ تمام شده با تست و README از پانزده مخزن نیمه کاره قوی تر است.
- انتخاب زبانی که برای کار استفاده نمی کنی. نمونه کار باید همان زبان و ابزاری باشد که می خواهی با آن استخدام شوی.
اگر بین زبان ها مانده ای، معیار انتخاب را بر اساس بازار کاری که هدفت است بگذار، نه بر اساس محبوبیت کلی — مقایسهٔ انواع زبان های برنامه نویسی و کاربردشان برای همین انتخاب نوشته شده است.
جمع بندی: یک پروژهٔ کوچک، سه شاهد
هیچ کدام از این کارها استعداد نمی خواهد؛ ترتیب می خواهد. امروز تمام کاری که لازم است: یک مسئلهٔ کوچک با یک کاربر واقعی انتخاب کن، محدودهٔ نسخهٔ ۱ را در یک فایل بنویس، پوشه و مخزن را بساز، و اولین کامیت را با یک پیام معنادار بزن. تا آخر هفته، README و یک دموی زنده داشته باش. تا آخر ماه، تست و CI. نتیجهٔ نهایی سه شاهد است که خودشان حرف می زنند: مخزنی با تاریخچهٔ قابل خواندن، فایل README که مرز کار خودت را روشن می گوید، و یک نشانی زنده که کار می کند — و همین سه، همان چیزی است که جای «سابقهٔ کاری» را می گیرد.
اگر پروژه ای که می سازی برای یک کسب وکار واقعی است و می خواهی به یک سامانهٔ جدی تبدیل شود، مسیر حرفه ای اش را در طراحی سایت اختصاصی در شیراز توضیح داده ام.


ارسال نظر جدید