README-ir.md
中文版 | 日本語版 | 한국어 | Русский | Português | Italiana | English | Persian/فارسی
<p align="right"> <a href="https://www.elsewhen.com/"> </a> </p><hr>وقتی که شروع و توسعه یک پروژه جدید برای شما شبیه به حرکت در یک میدان سبز و خالی (که هیچ ساختاری ندارد) است (استعاره از شروع کردن یک پروژه یا کار جدید از ابتدا و بدون هیچ محدودیت و ساختاری است)، نگهداری از آن میتواند کابوسی پیچیده و تاریک برای شخص دیگری باشد. در اینجا لیستی از دستورالعملها آمده است که ما آنها را پیدا کردهایم، نوشتهایم و گردآوری کردهایم و فکر میکنیم که برای اکثر پروژههای جاوااسکریپت در elsewhen به خوبی عمل میکند. اگر میخواهید یک روش بهینه را به اشتراک بگذارید، یا فکر میکنید یکی از این دستورالعملها باید حذف شود، با خیال راحت آن را با ما به اشتراک بگذارید.
<a name="git"></a>
<a name="some-git-rules"></a>
مجموعهای از قوانین وجود دارد که باید آنها را به خاطر داشته باشید:
چرا:
این روش باعث میشود که تمام کارها به صورت مجزا در یک برنچ اختصاصی انجام شوند، نه در برنچ اصلی. این کار به شما امکان را میدهد تا چندین درخواست Pull Request بدون سردرگمی ارسال کنید. همچنین میتوانید به طور مکرر کد را بهروزرسانی کنید، بدون اینکه برنچ اصلی را با کد ناپایدار و ناتمام آلوده کنید. توضیحات بیشتر ...
develop انشعاب بگیریدچرا:
به این ترتیب، میتوانید مطمئن شوید که کد برنچ master تقریباً همیشه بدون مشکل build میشود و معمولاً میتوان آن را مستقیماً برای releases استفاده کرد (این کار ممکن است برای برخی پروژهها بیش از حد لازم باشد).
develop یا master پوش نکنید. بلکه یک درخواست Pull Request ایجاد کنید.چرا:
این کار به اعضای تیم اطلاع میدهد که یک feature تکمیل شده است. همچنین امکان بررسی آسان کد توسط سایرین را فراهم میکند و فضایی برای بحث درباره feature پیشنهادی ایجاد میکند.
develop محلی/local خود را قبل از پوش کردن یک feature، ابتدا بروزرسانی و مورد بازبینی تعاملی (interactive rebase) قرار دهید، سپس درخواست Pull Request ایجاد کنید.چرا:
ریبیس (Rebase) برنچ درخواستشده (
masterیاdevelop) را merge میکند و کامیتهایی که بهصورت locally انجام دادهاید ر�� به بالای تاریخچه اعمال میکند، بدون اینکه کامیت merge ایجاد کند (در صورتی که تعارضی وجود نداشته باشد). نتیجه آن یک تاریخچه تمیز و مرتب خواهد بود. توضیحات بیشتر ...
چرا:
لیست برنچهای شما را با برنچهای بیاستفاده درهم میآمیزد (شلوغ میکند). حذف برنچهای feature باعث میشود که هر برنچ تنها یکبار به برنچ اصلی (
masterیاdevelop) ادغام شود. برنچهای feature باید فقط تا زمانی که کار هنوز در حال انجام است وجود داشته باشند.
چرا:
شما قصد دارید که کد خود را به یک برنچ stable اضافه کنید. اگر testهای برنچ feature شما ناموفق باشند، احتمال زیادی وجود دارد که build برنچ مقصد نیز شکست بخورد. علاوه بر این، قبل از ایجاد درخواست Pull Request، نیاز است که بررسی سبک و استایل کد را انجام شود. این کار باعث بهبود خوانایی کد میشود و احتمال ترکیب شدن تغییرات قالببندی با تغییرات واقعی را کاهش میدهد.
.gitignore استفاده کنید.چرا:
این فایل از قبل دارای لیستی از فایلهای سیستمی است که نباید همراه با کد شما به مخزن remote ارسال شوند. علاوه بر این، پوشهها و فایلهای تنظیمات برای بیشتر ویرایشگرهای مورد استفاده و همچنین پوشههای dependency رایج را نیز مستثنی میکند.
develop و master محافظت کنید.چرا:
این کار از برنچهای آماده برای production در برابر دریافت تغییرات غیرمنتظره و غیرقابل بازگشت محافظت میکند. توضیحات بیشتر ... GitHub, Bitbucket and GitLab
<a name="git-workflow"></a>
به خاطر دلایل ذکرشده در بالا، ما از Feature-branch-workflow همراه با Interactive Rebasing و برخی عناصر Gitflow (نامگذاری و داشتن یک develop branch). استفاده میکنیم. مراحل اصلی به شرح زیر هستند:
cd <project directory>
git init
git checkout -b <branchname>
git add <file1> <file2> ...
git commit
چرا:
کامند
git add <file1> <file2> ...- شما باید فقط فایلهایی را اضافه کنید که یک تغییر کوچک و منسجم را تشکیل میدهند.
کامند
git commitیک ویرایشگر باز میکند که به شما اجازه میدهد مقادیر subject را از body در کامیت خود از هم جدا کنید.
در بخش 1.3 بیشتر درباره آن بخوانید.
نکته:
میتوانید به جای آن از دستور
git add -pاستفاده کنید که به شما این امکان را میدهد تمام تغییرات اعمالشده را یک به یک بررسی کنید و تصمیم بگیرید که آیا آنها را در کامیت وارد کنید یا نه.
git checkout develop
git pull
چرا:
این کار به شما فرصت میدهد که با conflictها در سیستم خود در حین rebasing برخورد کنید، به جای اینکه یک درخواست Pull Request ایجاد کنید که حاوی conflictها باشد.
git checkout <branchname>
git rebase -i --autosquash develop
چرا:
میتوانید از
--autosquashاستفاده کنید تا تمام کامیتهای خود را به یک کامیت ترکیب کنید. هیچکس نمیخواهد برای یک ویژگی در شاخه develop چندین کامیت داشته باشد. توضیحات بیشتر ...
git add <file1> <file2> ...
git rebase --continue
-f برای اجبار تغییرات به برنچ remote استفاده کنید. اگر شخص دیگری روی برنچ شما کار میکند، از گزینه کمتر مخرب --force-with-lease استفاده کنید.git push -f
چرا:
وقتی که rebase انجام میدهید، تاریخچه برنچ feature خود را تغییر میدهید. در نتیجه، گیت
git pushمعمولی را رد میکند. به جای آن باید از فلگ-fیا--forceاستفاده کنید. توضیحات بیشتر ...
git branch -d <branchname>
تمام برنچهای local را که در مخزن remote وجود ندارند را حذف کنید. (این کار باعث میشود که برنچهای که دیگر وجود ندارند، از مخزن local حذف شوند، در نتیجه محیط توسعه شما تمیز و مرتب باقی میماند.)
git fetch -p && for branch in `git branch -vv --no-color | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done
<a name="writing-good-commit-messages"></a>
داشتن یک راهنمای مناسب برای ایجاد کامیتها و پایبندی به آن، کار با گیت و همکاری با دیگران را بسیار آسانتر میکند. در اینجا چند قانون کلی وجود دارد:(منبع):
چرا:
گیت به اندازه کافی هوشمند است که خط اول پیام کامیت شما را بهعنوان خلاصه تشخیص دهد. در واقع، اگر بهجای استفاده از git log از git shortlog استفاده کنید، یک لیست طولانی از پیامهای کامیت خواهید دید که شامل شناسه کامیت و تنها خلاصه پیام است.
چرا:
کامیتها تا حد ممکن باید جزئی و متمرکز باشند؛ نیازی به طولانینویسی در آنها نیست. توضیحات بیشتر ...
چرا:
به جای نوشتن پیامهایی که فقط بیانگر/توصیفکننده کاری است که کامیتکننده انجام داده، بهتر است این پیامها را به عنوان دستورالعملهایی در نظر بگیرید که بیان میکنند پس از اعمال کامیت در مخزن، چه چیزی قرار است انجام شود. (توضیح مترجم: پیامهای کامیت باید بر نتیجه و هدف تمرکز کنند، نه صرفاً بر عملیات انجامشده.) توضیحات بیشتر ...
<a name="documentation"></a>
README.md استفاده کنید؛ اگر بخشهایی وجود دارد که پوشش داده نشدهاند، با خیال راحت آنها را اضافه کنید.README.md مربوطه قرار دهید..README.md را بهروز نگه دارید.<a name="environments"></a>
development، test و production تعریف کنید.چرا:
در محیطها (environments) مختلف ممکن است data، tokens، APIs، ports و... متفاوتی نیاز باشند. ممکن است بخواهید یک حالت
developmentایزوله داشته باشید که به APIهای جعلی متصل میشود و دادههای قابل پیشبینی برمیگرداند، که این کار هم تستهای خودکار و هم تستهای دستی را بسیار سادهتر میکند. یا شاید بخواهید Google Analytics را فقط در محیطproductionفعال کنید و به همین ترتیب. توضیحات بیشتر ...
چرا:
در این فایلها ممکن است tokens، passwords و دیگر اطلاعات ارزشمند وجود داشته باشند. پیکربندی/کانفیگ شما باید بهدرستی از بخشهای داخلی برنامه جدا باشد، به گونهای که کد در هر لحظه ممکن است عمومی شود.
چگونه:
فایلهای
.envرا برای ذخیره متغیرهای خود استفاده کنید و آنها را به.gitignoreاضافه کنید تا از مخزن مستثنی شوند. در عوض، یک فایل.env.exampleکامیت کنید که بهعنوان راهنما برای توسعهدهندگان عمل کند. برای محیط production، باید همچنان متغیرهای محیطی را به روش استاندارد تنظیم کنید. بیشتر بخوانید
joi برای اعتبارسنجی مقادیر ارائهشده استفاده میکند.چرا:
این کار میتواند دیگران را از ساعتها مشکلیابی/troubleshooting نجات دهد.
<a name="consistent-dev-environments"></a>
engines در فایل package.json تنظیم کنید..چرا:
این کار به دیگران اطلاع میدهد که پروژه با کدام نسخهی Node کار میکند. توضیحات بیشتر ...
nvm استفاده کنید و یک فایل .nvmrc در ریشهی پروژهی خود ایجاد کنید. فراموش نکنید که به آن در مستندات اشاره کنید.چرا:
هر کسی که از
nvmاستفاده میکند، میتواند به سادگی با اجرای کامندnvm useبه نسخهی مناسب Node سوئیچ کند. توضیحات بیشتر ...
preinstall که نسخههای Node و npm را بررسی کند، ایدهی خوبی است.چرا:
برخی وابستگیها/dependencies ممکن است در صورت نصب توسط نسخههای جدیدتر npm با خطا مواجه شوند.
چرا:
این کار میتواند یک محیط سازگار در کل فرآیند کاری شما فراهم کند، بدون نیاز به تنظیمات یا وابستگیهای پیچیده. توضیحات بیشتر ...
چرا:
این کار به شما اجازه میدهد پکیجهای خود را با همکارانتان به اشتراک بگذارید، به جای اینکه انتظار داشته باشید آنها را بهصورت گلوبالی روی سیستم خود نصب کرده باشند.
<a name="consistent-dependencies"></a>
چرا:
زیرا میخواهید که کد، در هر محیط توسعهای به همان شکل مورد انتظار عمل کند و یکسان باشد. توضیحات بیشتر ...
چگونه:
از
package-lock.jsonدر نسخه 5 ازnpmیا بالاتر، استفاده کنید.
من npm@5 ندارم:
در این صورت میتوانید از
Yarnاستفاده کنید و اطمینان حاصل کنید که این موضوع را در فایلREADME.md. پس از هر بهروزرسانی وابستگیها، lock file وpackage.jsonباید نسخههای یکسانی داشته باشند. توضیحات بیشتر ...
من اسم Yarn را دوست ندارم:
متأسفانه انتخاب دیگری ندارید. برای نسخههای قدیمیتر
npm, هنگام نصب وابستگی جدید از—save --save-exactاستفاده کنید و قبل از انتشار پروژه، فایلnpm-shrinkwrap.jsonایجاد کنید. توضیحات بیشتر ...
<a name="dependencies"></a>
npm ls --depth=0 استفاده کنید. (توضیحات مترجم: با استفاده از دستور npm ls --depth=0 در محیط خط فرمان، میتوانید فهرستی از پکیجهای سطح اول (بدون نمایش وابستگیهای زیرمجموعهای) را مشاهده کنید. این کار به شما کمک میکند تا بدانید چه بستههایی در حال حاضر در پروژهتان نصب هستند و از وضعیت آنها مطلع باشید.) توضیحات بیشتر ...depcheck توضیحات بیشتر ...چرا:
ممکن است یک کتابخانه بیاستفاده را در کد خود داشته باشید که باعث افزایش حجم نهایی برنامه شود. وابستگیهای بیاستفاده را پیدا کرده و حذف کنید.
npm-stat. توضیحات بیشتر ...چرا:
استفاده بیشتر (از پکیجها) معمولاً به معنای داشتن تعداد بیشتری از مشارکتکنندگان است که اغلب منجر به نگهداری بهتر میشود و همه اینها باعث میشود که باگها سریعتر کشف و اصلاحات سریعتر توسعه داده شوند.
npm view async استفاده کنید. توضیحات بیشتر ...چرا:
داشتن تعداد زیادی از مشارکتکنندگان زمانی مؤثر است که نگهدارندگان بتوانند اصلاحات و تغییرات را به سرعت merge کنند.
npm outdated استفاده کنید. توضیحات بیشتر ...چرا:
بروزرسانی وابستگیها (dependencies) گاهی شامل تغییرات مخرب میشوند. هر زمان که بروزرسانیها نمایش داده میشوند، حتماً release note ها را بررسی کنید. وابستگیهای (dependencies) خود را یکییکی بروزرسانی کنید، زیرا اگر مشکلی پیش بیاید، عیبیابی آن آسانتر خواهد بود. از ابزارهای کاربردی مانند موارد زیر استفاده کنید: npm-check-updates.
<a name="testing"></a>
test (برای حالت تست) ایجاد کنید.چرا:
گاهی تست end to end در حالت
productionممکن است کافی به نظر برسد، اما در موارد خاص نیاز به محیط تست جداگانهای وجود دارد. مثلاً ممکن است نخواهید اطلاعات تحلیلی در حالتproductionفعال شود و داشبورد افراد را با دادههای تست آلوده کنید. (توضیحات مترجم: چون دادههای تستی ممکن است اطلاعات واقعی را تحت تأثیر قرار دهد، مثلا باعث شلوغی و ایجاد دادههای غیرضروری شوند و یا مانع از درک دقیق اطلاعات واقعی توسط کاربران یا تیم تحلیل شوند.) مثال دیگر این است که ممکن است API شما در حالت تولید محدودیت تعداد درخواست (rate limit) داشته باشد و پس از تعداد مشخصی درخواست، فراخوانی APIها توسط تست را مسدود کند.
*.test.js یا *.spec.js قرار دهید، مانند moduleName.spec.js.چرا:
برای پیدا کردن یک تست واحد، در ساختار پوشهها جستجو و پیمایش نکنید. توضیحات بیشتر ...
چرا:
برخی از فایلهای تست مستقیماً به فایل پیادهسازی خاصی مرتبط نیستند. باید این فایلها را در پوشهای قرار دهید که احتمالاً توسط سایر توسعهدهندگان به راحتی یافت شود: پوشه
__test__. این نام__test__هم اکنون یک استاندارد است و توسط اکثر فریمورکهای تست جاوااسکریپت تشخیص داده میشود.
چرا:
هر بخش از منطق کسبوکار (business logic) باید به صورت مستقل و جداگانه مورد آزمایش و تست قرار گیرد تا مطمئن شوید که هر قسمت به درستی کار میکند. باید "تأثیر عوامل تصادفی یا فرآیندهای غیرقابلپیشبینی را در کد به حداقل برسانید" توضیحات بیشتر ...
یک تابع خالص (pure function) تابعی است که همیشه برای ورودی یکسان، خروجی یکسانی را باز میگرداند. برعکس، یک تابع ناخالص (impure function) تابعی است که ممکن است اثرات جانبی داشته باشد یا برای تولید یک مقدار به شرایط خارجی وابسته باشد، که این امر باعث میشود کمتر قابل پیشبینی باشد. توضیحات بیشتر ...
چرا:
گاهی ممکن است به یک Static type checker نیاز داشته باشید. این ابزارها، سطحی از قابلیت اطمینان را برای کد شما به ارمغان میآورند. توضیحات بیشتر ...
develop را ارسال کنید، تستها را بهصورت locally اجرا کنید.چرا:
قطعاً نمیخواهید کسی باشید که باعث شکست فرایند بیلد برنچ آمادهی production شده است. تستهای خود را پس از
rebaseو پیش از ارسال به شاخه feature-branch به مخزن ریموت اجرا کنید.
README.md پروژه را مستندسازی کنید.چرا:
این مستندات مانند یک یادداشت راهنما است که برای توسعهدهندگان دیگر، کارشناسان DevOps، یا تیم تضمین کیفیت (QA) و هر کسی که با کد شما کار میکند، مفید خواهد بود.
<a name="structure-and-naming"></a>
بد
.
├── controllers
| ├── product.js
| └── user.js
├── models
| ├── product.js
| └── user.js
خوب
.
├── product
| ├── index.js
| ├── product.js
| └── product.test.js
├── user
| ├── index.js
| ├── user.js
| └── user.test.js
چرا:
به جای داشتن لیست طولانی از فایلها، ماژولهای کوچک ایجاد کنید که هر کدام یک مسئولیت خاص را دربرمیگیرند، از جمله تست آنها و موارد دیگر. این کار باعث میشود دسترسی به فایلها سادهتر شده و بتوانید به سرعت و با یک نگاه فایلهای مورد نظر را پیدا کنید.
چرا:
این کار برای سایر توسعهدهندگان یا کارشناسان DevOps تیم شما موجب صرفهجویی در زمان میشود.
./config برای تنظیمات استفاده کنید و فایلهای پیکربندی جداگانه برای محیطها (environments) مختلف ایجاد نکنید.چرا:
زمانی که یک فایل کانفیگ را برای اهداف مختلف (مانند پایگاه داده، API و غیره) تجزیه میکنید، قرار دادن آنها در پوشهای با نام مشخص مانند
configمنطقی است. فقط به خاطر داشته باشید که برای محیطهای مختلف فایلهای جداگانه نسازید، زیرا با افزایش استقرارهای برنامه، نامهای محیط جدیدی مورد نیاز میشود و مدیریت آن پیچیده خواهد شد.
مقادیر مورد استفاده در فایلهای کانفیگ باید از طریق متغیرهای محیطی (environment variables) فراهم شوند. توضیحات بیشتر ...
./scripts قرار دهید. این شامل اسکریپتهای bash و node است.چرا:
احتمالاً به بیش از یک اسکریپت نیاز خواهید داشت، مانند production build, development build, database feeders, database synchronization و غیره.
./build قرار دهید. build/ را به .gitignore اضافه کنید.چرا:
نامگذاری آن به سلیقه شما بستگی دارد،
distنیز گزینه خوبی است. اما با تیم خود این نامگذاری را هماهنگ کنید. فایلهایی که در این پوشه قرار میگیرند معمولاً تولید شدهاند (bundled, compiled, transpiled) یا به این پوشه منتقل شدهاند. چیزی که میتوانید تولید کنید، همتیمیهای شما نیز باید قادر به تولید آن باشند؛ بنابراین نیازی به ارسال آنها به مخزن ریموت نیست، مگر اینکه هدف خاصی داشته باشید.
<a name="code-style"></a>
<a name="code-style-check"></a>
چرا:
این موضوع به تصمیم شما بستگی دارد. ما از مبدلها (ترنسپایلرها) برای بهرهگیری از مزایای سینتکس جدید استفاده میکنیم. استیج ۲ با تغییرات جزئی احتمالا بخشی از استاندارد خواهد شد.
چرا:
متوقف کردن build برنامه یکی از روشهای اعمال سبک کدنویسی در کد است. این کار از بیتوجهی به سبک کدنویسی جلوگیری میکند. این روش را برای کد سمت client و server اجرا کنید. توضیحات بیشتر ...
چرا:
ما
eslintرا ترجیح میدهیم، اما شما میتوانید انتخاب دیگری داشته باشید. این ابزار قوانین بیشتری را پشتیبانی میکند، همچنین قابلیت تنظیم و افزودن قوانین سفارشی را دارد.
چرا:
ابزار Flow سینتکسهای جدیدی را معرفی میکند که نیاز به رعایت سبک کدنویسی خاصی دارند و باید بررسی شوند.
.eslintignore برای مستثنی کردن فایلها یا پوشهها از بررسی کد استایل استفاده کنید.چرا:
برای مستثنی کردن چند فایل از بررسی سبک کدنویسی، لازم نیست کدتان را با کامنتهای
eslint-disableشلوغ کنید.
eslint-disable خود را حذف کنید.چرا:
طبیعی است که هنگام کار بر روی یک بخش از کد، برای تمرکز بیشتر روی منطق، بررسی سبک را غیرفعال کنید. فقط به خاطر داشته باشید که کامنتهای
eslint-disableرا حذف کرده و قوانین را رعایت کنید.
//TODO: استفاده کنید یا یک تیکت باز کنید.چرا:
استفاده از کامنتهای
//TODO:به شما و همکارانتان کمک میکند تا وظایف کوچک مانند بازنویسی یک تابع یا بهروزرسانی یک توضیح را به خاطر بسپارید. برای وظایف بزرگتر، از فرمت//TODO(#3456)استفاده کنید که توسط قوانین lint اعمال میشود، که شمارهی داخل پرانتز به یک تیکت باز اشاره دارد.
چرا:
کد شما باید تا حد ممکن خوانا باشد؛ هر چیزی که حواس را پرت میکند، حذف کنید. اگر یک تابع را بازنویسی کردید، تابع قدیمی را فقط کامنت نکنید، بلکه آن را حذف کنید.
چرا:
اگرچه در فرآیند build برنامه آن شوخیها ممکن است (و بهتر است بگویم باید) حذف شود، اما گاهی source code شما به شرکت یا مشتری دیگری منتقل میشود که ممکن است آنها چنین شوخیهایی را نپسندند.
چرا:
این کار (استفاده از نامهای کامل و توصیفی) باعث میشود کد خواناتر و درک آن راحتتر و سادهتر شود.
چرا:
این کار کد را خواناتر و درک آن بهتر میکند
<a name="enforcing-code-style-standards"></a>
چرا:
پروژه EditorConfig شامل یک فرمت فایل برای تعریف سبک و استالهای کدنویسی است که شامل مجموعهای از افزونهها برای ویرایشگرهای متنی است، که به ویرایشگرها این امکان را میدهد تا فرمت فایل را بخوانند و از استایلهای تعریفشده پیروی کنند. فایلهای EditorConfig خوانا هستند و بهخوبی با سیستمهای کنترل نسخه کار میکنند.
چرا:
استفاده از Git hooks بهطور قابلتوجهی بهرهوری توسعهدهندگان را افزایش میدهد. با اعمال تغییرات، انجام commit و ارسال (push) به محیطهای staging یا production، بدون نگرانی از خراب شدن build برنامه، میتوانید با اطمینان بیشتری کار کنید. توضیحات بیشتر ...
چرا:
اگرچه
prettierبهخودیخود قدرتمند است، اجرای دستی آن بهعنوان یک تسک npm برای قالببندی کد چندان کارآمد نیست. در اینجاlint-staged(وhusky) وارد عمل میشوند. درباره پیکربندیlint-stagedاینجا و پیکربندیhuskyاینجا بیشتر بخوانید..
<a name="logging"></a>
چرا:
حتی اگر فرآیند build برنامه شما میتواند (و باید) آن لاگها را حذف کند، اطمینان حاصل کنید که ابزار بررسی استایل کدنویسی شما دربارهی باقیماندههای console.log هشدار میدهد.
چرا:
این کار عیبیابی را آسانتر و دلپذیرتر میکند، چون میتوانید از قابلیتهایی مانند رنگبندی، افزودن زمان به لاگها، ثبت لاگها در فایل علاوه بر کنسول و حتی ثبت لاگها در فایلهایی که بهصورت روزانه ایجاد و بایگانی میشوند، استفاده کنید. توضیحات بیشتر ...
<a name="api"></a>
<a name="api-design"></a>
<p align="right"> </p>چرا:
هدف این است که رابطهای RESTfulی طراحی کنیم که منطقی و ساده باشند تا اعضای تیم و مشتریان بتوانند بهسادگی و بهصورت یکنواخت از آنها استفاده کنند.
چرا:
نبود هماهنگی و سادگی میتواند هزینههای یکپارچهسازی و نگهداری را به طور چشمگیری افزایش دهد؛ به همین دلیل طراحی
APIدر این داکیومنت گنجانده شده است.
چرا:
این یک طراحی بسیار شناختهشده برای توسعهدهندگان است (که اصلیترین مصرفکنندگان API هستند). علاوه بر خوانایی و سهولت استفاده، این روش به ما اجازه میدهد کتابخانهها و connectorهای عمومی بنویسیم بدون اینکه نیاز به شناخت جزئیات خاص هر API داشته باشیم.
/users.چرا:
اساساً، این کار خوانایی را بهتر کرده و URLها را هماهنگ نگه میدارد. توضیحات بیشتر ...
چرا::
استفاده از اسامی جمع در URL مناسب است، اما در سورس کد ممکن است نامحسوس و مستعد خطا باشد.
/students/245743
/airports/kjfk
GET /blogs/:blogId/posts/:postId/summary
چرا:
این URL به جای ارجاع به یک منبع (resource)، به یک ویژگی (property) اشاره میکند. شما میتوانید ویژگی مورد نظر را بهعنوان یک پارامتر در درخواست ارسال کنید تا پاسخ دریافتی مختصرتر و بهینهتر باشد.
چرا:
زیرا اگر برای هر عملیات resource از یک فعل استفاده کنید، به زودی با لیستی بزرگ از URLها مواجه خواهید شد که الگوی ثابتی ندارند و یادگیری را برای توسعهدهندگان دشوار میکنند. علاوه بر این، ما از افعال برای چیز دیگری استفاده میکنیم.
/translate?text=Hallo
چرا:
زیرا برای CRUD ما از متدهای HTTP بر روی URLهای
resourceیاcollectionاستفاده میکنیم. افعالی که درباره آنها صحبت میکنیم در واقع کنترلرهاControllersهستند. شما معمولاً تعداد زیادی از اینها را توسعه نمیدهید. توضیحات بیشتر ...
JSON است، لطفاً برای نامگذاری پراپرتیهای JSON از camelCase پیروی کنید تا یکپارچگی و سازگاری حفظ شود.چرا:
این یک راهنما و دستورالعمل برای پروژه JavaScript است، که فرض بر این است که زبان برنامهنویسی مورد استفاده برای تولید و تجزیه JSON، جاوااسکریپت میباشد.
table_name) برای نامگذاری منبع و از نام ستون (column_name) برای پراپرتیهای منبع استفاده کنید. به عبارت دیگر، نامگذاری منابع و پراپرتیهای آنها نباید مستقیماً از ساختار پایگاه داده مشتق شود؛ بلکه باید بر اساس مفاهیم و نیازهای دامنهی کاربرد طراحی شود تا از وابستگی به جزئیات پیادهسازی جلوگیری شود.چرا:
زیرا هدف شما نمایش منابع است، نه جزئیات ساختار پایگاه داده.
چرا:
فقط از اسامی در URLهای منبع استفاده کنید و از نوشتن مواردی مانند
/addNewUserیا/updateUserخودداری کنید. همچنین از ارسال عملیات منابع بهعنوان پارامتر اجتناب کنید.
چگونه:
متد
GET: برای دریافت از یک resource استفاده میشود.
متد
POST: برای ایجاد منابع (resources) جدید و زیرمنابع (sub-resources) به کار میرود.
متد
PUT: برای بهروزرسانی منابع موجود استفاده میشود.
متد
PATCH: برای بهروزرسانی جزئی منابع موجود به کار میرود؛ بهطوریکه فقط فیلدهای ارائهشده را بهروزرسانی کرده و سایر فیلدها را بدون تغییر باقی میگذارد.
متد
DELETE: برای حذف منابع موجود استفاده میشود.
id) در URL استفاده کنید.چرا:
این روش دسترسی به منابع مرتبط را آسانتر میکند.
چگونه:
درخواست
GET /schools/2/students, باید لیست تمام دانشآموزان مدرسه با شناسه ۲ را برگرداند.
درخواست
GET /schools/2/students/31, باید جزئیات دانشآموز با شناسه ۳۱ را که متعلق به مدرسه ۲ است، برگرداند.
درخواست
DELETE /schools/2/students/31, باید دانشآموز با شناسه ۳۱ را که متعلق به مدرسه ۲ است، حذف کند.
درخواست
PUT /schools/2/students/31, باید اطلاعات دانشآموز با شناسه ۳۱ را که متعلق به مدرسه ۲ است، بهروزرسانی کند.
درخواست
POST /schools, باید یک مدرسه جدید ایجاد کرده و جزئیات مدرسه تازه ایجاد شده را برگرداند. از POST بر روی URLهای مجموعهای (Collection) استفاده کنید.
v استفاده کنید (مانند v1، v2) و آن را تا حد امکان در ابتدای URL قرار دهید تا دامنه بالاتری را (برای تاثیرگذاری) داشته باشد:http://api.domain.com/v1/schools/3/students
چرا:
وقتی APIهای شما بهطور عمومی برای سایر اشخاص ثالث در دسترس هستند، اعمال تغییرات ناسازگار (breaking changes)، میتواند باعث اختلال در عملکرد محصولات یا خدماتی شود که از APIهای شما استفاده میکنند. استفاده از نسخهبندی در URL میتواند از بروز چنین مشکلاتی جلوگیری کند. توضیحات بیشتر ...
{
"code": 1234,
"message": "Something bad happened",
"description": "More details"
}
یا برای خطاهای اعتبارسنجی:
{
"code": 2314,
"message": "Validation Failed",
"errors": [
{
"code": 1233,
"field": "email",
"message": "Invalid email"
},
{
"code": 1234,
"field": "password",
"message": "No password provided"
}
]
}
چرا:
توسعهدهندگان در زمانهای بحرانی که در حال عیبیابی و حل مشکلات پس از انتشار برنامههایی که با استفاده از APIهای شما ساختهاند و در دست کاربران قرار گرفتهاند، به خطاهای خوب و خوشطراحیشده وابسته هستند.
توجه: پیامهای استثنا مربوط به امنیت را تا حد ممکن عمومی و ساده نگه دارید. به عنوان مثال، به جای اینکه بنویسید «رمز عبور اشتباه است»، میتوانید پیام «نام کاربری یا رمز عبور نامعتبر است» را بازگردانید. این کار باعث میشود که بهطور ناخودآگاه به کاربر اطلاع ندهید که نام کاربری درست است و تنها رمز عبور اشتباه است.
از این کدهای وضعیت (status codes) برای ارسال همراه با پاسخهای خود استفاده کنید تا مشخص کنید آیا همه چیز درست انجام شده است یا خیر، آیا کلاینت اشتباهی انجام داده یا مشکل از API بوده است.
_کدام یک:_
> پاسخ `200 OK` نشاندهنده موفقیت برای درخواستهای `GET`, `PUT` یا `POST` است.
> کد `201 Created` برای زمانی است که یک نمونه جدید ایجاد میشود. ایجاد یک نمونه جدید با استفاده از متد `POST` کد وضعیت `201` را برمیگرداند.
> پاسخ `204 No Content` نشاندهنده موفقیت است، اما محتوایی برای ارسال در پاسخ وجود ندارد. از آن در زمانی استفاده کنید که عملیات `DELETE` با موفقیت انجام شده است.
> پاسخ `304 Not Modified` برای به حداقل رساندن انتقال اطلاعات زمانی که گیرنده قبلاً نسخههای کششده را دارد، استفاده میشود.
> کد `400 Bad Request` برای زمانی است که درخواست پردازش نشده است، زیرا سرور نمیتواند بفهمد که مشتری چه چیزی درخواست کرده است.
> کد `401 Unauthorized` برای زمانی است که درخواست فاقد اعتبارنامههای معتبر است و باید با اعتبارنامههای مورد نیاز دوباره ارسال شود.
> کد `403 Forbidden` به این معنی است که سرور درخواست را فهمیده است، اما از اعطای مجوز خودداری میکند.
> کد `404 Not Found` نشان میدهد که منبع درخواستی پیدا نشده است.
> کد `500 Internal Server Error` نشان میدهد که درخواست معتبر است، اما سرور به دلیل برخی شرایط غیرمنتظره نمیتواند آن را انجام دهد.
_چرا:_
> بیشتر ارائهدهندگان API از تعداد کمی از کدهای وضعیت HTTP استفاده میکنند. برای مثال، API سرویس Google GData تنها از ۱۰ کد وضعیت، Netflix از ۹ کد، و Digg تنها از ۸ کد وضعیت استفاده میکنند. البته، این پاسخها معمولاً شامل بدنهای هستند که اطلاعات بیشتری را ارائه میدهد. در کل، بیش از ۷۰ کد وضعیت HTTP وجود دارد. اما اکثر توسعهدهندگان همه این ۷۰ کد را به خاطر ندارند.بنابراین، اگر شما کدهای وضعیتی را انتخاب کنید که خیلی رایج نیستند، توسعهدهندگان مجبور میشوند به جای ادامه کار روی برنامه خود، وقتشان را صرف جستجو در ویکیپدیا کنند تا متوجه شوند شما چه چیزی را سعی دارید به آنها بگویید. [توضیحات بیشتر ...](https://apigee.com/about/blog/technology/restful-api-design-what-about-errors)
تعداد کل منابع/دیتا را در پاسخ (response) خود اعلام کنید.
پارامترهای limit و offset را بپذیرید.
مقدار دادهای که یک منبع در پاسخ ارائه میدهد نیز باید مورد توجه قرار گیرد. مصرفکننده API همیشه به تمام اطلاعات مربوط به یک منبع نیاز ندارد. از پارامتر fields استفاده کنید که لیستی از فیلدها را به صورت جدا شده با کاما دریافت میکند تا مشخص کند کدام فیلدها در پاسخ گنجانده شوند:
GET /students?fields=id,name,age,class
<a name="api-security"></a>
این موارد برخی از بهترین روشهای امنیتی پایه هستند:
GET /users/123?token=asdf....چرا:
زیرا توکن یا شناسه کاربری و رمز عبور به صورت متن ساده (clear text) در شبکه ارسال میشوند (اگرچه به صورت Base64 کدگذاری شده است، اما Base64 یک کدگذاری برگشتپذیر است). بنابراین، روش احراز هویت پایه ایمن نیست. توضیحات بیشتر ...
Authorization: Bearer xxxxxx, Extra yyyyy.403 Forbidden استفاده کنید.چرا:
برای حفاظت از API در برابر تهدیدات باتهایی که ممکن است هزاران بار در ساعت API شما را فراخوانی میکنند. باید محدودیت نرخ (rate limit) را از همان مراحل اولیه پیادهسازی مد نظر قرار دهید.
چرا:
یکی از نگرانیهای اصلی کار با JSON، جلوگیری از اجرای کدهای جاوااسکریپت دلخواه از remote در مرورگر است... یا اگر از node.js در سمت سرور استفاده میکنید. بسیار مهم و حیاتی است که از یک سریالایزر JSON مناسب استفاده کنید تا دادههای ورودی کاربر به درستی کدگذاری شوند و از اجرای دادههای ورودی کاربر در مرورگر جلوگیری شود.
application/*json (هدر Content-Type) استفاده کنید.چرا:
به عنوان مثال، پذیرش نوع
application/x-www-form-urlencodedبه مهاجم اجازه میدهد یک فرم ایجاد کند و یک درخواست POST ساده ارسال کند. سرور هرگز نباید نوع محتوا (Content-Type) را فرض کند. عدم وجود هدر Content-Type یا وجود یک Content-Type غیرمنتظره باید منجر به رد محتوا توسط سرور با یک پاسخ4XXشود.
<a name="api-documentation"></a>
API Reference را در README.md template برای API پر کنید.برای هر Endpoint، موارد زیر را توضیح دهید:
Required: id=[integer]
Optional: photo_id=[alphanumeric]
Code: 200
Content: { id : 12 }
{
"code": 401,
"message": "Authentication failed",
"description": "Invalid username or password"
}
<a name="a11y"></a>
برای اطمینان از حفظ سطح مشخصی از دسترسیپذیری، از ابتدای پروژه خود مراحل زیر را انجام دهید:
چرا:
محتوای وب بهطور پیشفرض دسترسیپذیراست. ما این ویژگی را زمانی به خطر میاندازیم که امکانات پیچیده ایجاد میکنیم. در نظر گرفتن دسترسیپذیری از ابتدا بسیار آسانتر از بازپیادهسازی این ویژگیها در آینده است تا تأثیر آن را کاهش دهیم.
نکته: برخی بررسیهای مهم باید بهصورت دستی انجام شوند، مانند ترتیب منطقی تبها. ابزارهای فوق این موارد را به عنوان تستهای دستی یا راهنماییشده در کنار نتایج خودکار فهرست میکنند. در axe باید نتایج خودکار خود را ذخیره کنید تا این موارد را مشاهده کنید.
چرا:
یک لینتر بهطور خودکار بررسی میکند که سطح پایهای از دسترسیپذیری در پروژه شما رعایت شده است و راهاندازی آن نسبتاً آسان است.
چرا:
گنجاندن بررسیهای دسترسپذیری در تستها به شما کمک میکند تا هر تغییری که بر دسترسپذیری پروژه و امتیاز ممیزی تأثیر میگذارد، شناسایی کنید.
چرا:
این کامپوننتها به صورت پیشفرض از سطح بالایی از دسترسپذیری برخوردار هستند.
چرا:
لینکهایی که غیرقابل دسترس میباشند، برای دسترسپذیری موانعی ایجاد میکنند.
چرا:
لیستها باید دارای عناصر والد و عناصر فرزند باشند تا معتبر باشند. صفحهخوانها (Screen Readers) به کاربران اطلاع میدهند که وقتی به یک لیست میرسند، لیست شامل چند آیتم است.
چرا:
سرفصلها ساختار صفحه را منتقل میکنند. هنگامی که به درستی اعمال شوند، پیمایش صفحه آسانتر میشود.
چرا:
برخی افراد با بینایی کم، کنتراست پایین را تجربه میکنند؛ به این معنی که تفاوت زیادی بین مناطق روشن و تاریک وجود ندارد. همه چیز تقریباً با همان میزان روشنایی ظاهر میشود، که تشخیص خطوط، حاشیهها، لبهها و جزئیات را دشوار میکند. متنی که از نظر روشنایی بسیار نزدیک به پسزمینه باشد، ممکن است سخت خوانده شود.
چرا:
صفحهخوانها نمیتوانند تصاویر را به کلماتی تبدیل کنند که برای کاربر خوانده شود، حتی اگر تصویر فقط شامل متن باشد. در نتیجه، ضروری است که تصاویر دارای متن جایگزین کوتاه و توصیفی باشند تا کاربران صفحهخوان بهوضوح محتوای تصویر و هدف آن را درک کنند.
قوانین بیشتری درباره دسترسپذیری را میتوانید اینجا پیدا کنید.
<a name="licensing"></a>
اطمینان حاصل کنید که از منابعی استفاده میکنید که حق استفاده از آنها را دارید. اگر از کتابخانهها استفاده میکنید، به مجوزهای MIT، Apache یا BSD توجه کنید، اما اگر این کتابخانهها را تغییر میدهید، حتماً جزئیات مجوز را بررسی کنید. استفاده از تصاویر و ویدئوهای دارای حق کپیرایت (Copyrighted) ممکن است مشکلات قانونی ایجاد کند.
منابع: RisingStack Engineering, Mozilla Developer Network, Heroku Dev Center, Airbnb/javascript, Atlassian Git tutorials, Apigee, Wishtack
Icons by icons8