وقتی با زبانهای برنامهنویسی معمولی مثل Python / JS / Java کار میکنی، داری دستورالعمل میدی:
اول این کار رو بکن
بعد برو سراغ بعدی
اگه شرط درست بود فلان کار
حلقه بزن، متغیر عوض کن، ادامه بده
مثلاً:
for (...) { if (...) { push(...) } }
اینجا داری الگوریتم رو دقیق مینویسی
کامپیوتر حق فکر کردن نداره، فقط اجرا میکنه.
اما SQL اینجوری نیست. تو فقط میگی:
من حیواناتی رو میخوام که خانوادهشون Sharks باشه
SELECT * FROM animals WHERE family = 'Sharks';
❌ نمیگی:
از کدوم ایندکس استفاده کن
اول کدوم رکورد رو بخون
حلقه بزن یا نزن
ترتیب چطوره
✔ فقط نتیجه مهمه، نه مسیر رسیدن بهش.
تو به عنوان برنامهنویس:
حجم دیتا رو دقیق نمیدونی
ایندکسها ممکنه عوض بشن
دیتابیس ممکنه توی چند ماشین پخش شده باشه
Query Optimizer داخل DB:
میفهمه از کدوم ایندکس استفاده کنه
join رو با چه الگوریتمی بزنه
حتی ترتیب اجرا رو عوض میکنه
اگر imperative بنویسی، دست دیتابیس بستهست.
فرض کن:
دیتابیس برای بهینهسازی، رکوردها رو جابهجا میکنه
ترتیب فیزیکی داده روی دیسک عوض میشه
SQL میگه:
من هیچ تضمینی روی order نخواستم
پس دیتابیس آزاده.
اما توی کد imperative:
animals[0]
ممکنه ناخواسته به ترتیب وابسته باشی
و دیتابیس نمیتونه ریسک کنه.
این خیلی مهمه:
دیتابیس میتونه سریعتر بشه
بدون اینکه تو حتی یک خط Query رو تغییر بدی
چرا؟
چون الگوریتم دست دیتابیسه، نه دست تو.
CPUها دیگه خیلی سریعتر نمیشن؛
فقط core بیشتر دارن.
Imperative:
ترتیب مشخص
step به step
موازیسازی خیلی سخت
Declarative:
فقط میگه «نتیجه چی باشه»
دیتابیس میتونه:
دیتا رو تکهتکه کنه
روی چند core / چند ماشین اجرا کنه
آخرش نتیجه رو merge کنه
🟢 Imperative
کنترل کامل داری، ولی مقیاسپذیری و بهینهسازی فاجعه میشه
🟢 Declarative (مثل SQL)
کنترل کمتر، ولی:
سریعتر
امنتر
مقیاسپذیرتر
آیندهدارتر
SQL به دیتابیس میگه «چی میخوام»، نه «چطوری بهش برسی» — و همین باعث قدرتمند بودنشه.
بریم یک لِول عمیقتر؛ همون توضیح قبلی، ولی اینبار با نگاه معماری و تجربهی واقعی پروژه
(همونی که سینیورها بعد از یکیدو سیستم دردناک میفهمن 😄)
ORM چی کار میکنه؟
ORM (مثل Django ORM، SQLAlchemy، Hibernate):
ظاهراً imperative مینویسی
ولی در واقع داری Declarative Query میسازی
مثلاً:
User.objects.filter(age__gt=18, is_active=True)
این الگوریتم نیست
این فقط تعریف یک Query است.
❌ هنوز اجرا نشده
❌ هنوز دیتا نخونده
✔ فقط یک AST / Query Plan ساخته
users = User.objects.all() active_users = [u for u in users if u.is_active]
مشکل:
همه دیتا کشیده شده
فیلتر رفته توی اپلیکیشن
دیتابیس هیچ شانسی برای بهینهسازی نداره
✔ نسخه درست:
User.objects.filter(is_active=True)
قانون طلایی ORM
تا وقتی میتونی، دیتابیس رو مجبور کن فکر کنه، نه اپلیکیشن رو
این خیلی مهمه 👇
qs = User.objects.filter(is_active=True)
اینجا:
کوئری هنوز اجرا نشده
فقط تعریف شده
اجرا کی اتفاق میافته؟
list(qs) qs.first() qs.count()
این یعنی:
ORM میتونه کوئری رو merge کنه
فیلترها رو ترکیب کنه
order رو تغییر بده
Declarative ⇒ قابل بهینهسازی
for user in users: user.posts.count()
نتیجه:
N+1 Query
دیتابیس خفه میشه
✔ Declarative:
User.objects.annotate(post_count=Count("posts"))
اینجا:
دیتابیس خودش JOIN میزنه
aggregate میکنه
با یک query برمیگردونه
اینجا میرسیم به سؤال سینیوری 👀
دیتابیس: PostgreSQL
کش: Redis
Query declarative
DB رکورد رو lock کرده (transaction)
DB: نسخهی جدید رکورد داخل transaction
Redis: هنوز نسخهی قدیمی
Declarative بودن کمک میکنه چون:
تو وابسته به order یا state نیستی
فقط state نهایی مهمه
Cache Aside Pattern
بعد از commit → invalidate redis
یا TTL کوتاه
Declarative Query کمک میکنه چون:
نتیجه مهمه، نه مسیر رسیدن بهش
SQL:
SELECT family, COUNT(*) FROM animals GROUP BY family;
DB میتونه:
جدول رو تکه کنه
هر core یه chunk رو بشماره
آخر merge کنه
Imperative code:
for animal in animals: ...
❌ ترتیب مهمه
❌ موازیسازی خطرناکه
❌ race condition
فرض کن:
امروز دیتابیس کوچیکه
فردا sharding میکنی
پسفردا replica اضافه میکنی
اگر کوئریهات declarative باشه:
بدون تغییر کد scale میکنی
اگر imperative باشه:
کل بیزینس لاجیک باید rewrite بشه
🟢 Declarative:
SQL
ORM QuerySet
Map / Reduce
Elasticsearch DSL
🔴 Imperative:
loop
if
mutable state
order-dependent logic
هرجا دیتا زیاد میشه، Imperative میمیره و Declarative زنده میمونه.
این دقیقاً همون قسمتی است که مفهوم Declarative از دیتابیس میاد توی زندگی واقعی وب.
Declarative فقط مخصوص SQL نیست؛ هرجا «چی میخوام» رو بگی و «چطور انجام بده» رو بسپاری به سیستم، داری declarative کار میکنی.
وب (CSS، XSL، حتی React) پر از declarative است.
سایت دربارهی حیوانات دریایی داریم 🐟
کاربر روی صفحهی Sharks هست.
HTML:
<li class="selected"> <p>Sharks</p> </li> <li> <p>Whales</p> </li>
میخوای:
عنوان صفحهی انتخابشده آبی بشه
li.selected > p { background-color: blue; }
من دنبال <p> میگردم
که پدرش <li> باشه
و اون <li> کلاس selected داشته باشه
همونا رو آبی کن
❗ نکته مهم:
نگفتی loop بزن
نگفتی چک کن چندتا هست
نگفتی کی اضافه کن یا حذف کن
فقط الگو (pattern) رو گفتی.
اگر:
<li class="selected"> ← حذف بشه
CSS خودش:
میفهمه rule دیگه match نمیکنه
رنگ آبی رو حذف میکنه
❌ هیچ کدی دوباره اجرا نمیکنی
✔ سیستم خودش sync میمونه
var liElements = document.getElementsByTagName("li"); for (var i = 0; i < liElements.length; i++) { if (liElements[i].className === "selected") { var children = liElements[i].childNodes; for (var j = 0; j < children.length; j++) { if (child.tagName === "P") { child.setAttribute("style", "background-color: blue"); } } } }
برو همه liها رو بگیر
دونهدونه loop بزن
شرط بذار
بچههاشو بگرد
اگه p بود، style ست کن
🤮 طولانی
🤮 fragile
🤮 سخت نگهداری
اگر بعداً:
li.className = ""
چی میشه؟
رنگ آبی باقی میمونه 😐
باید کد جدا برای remove بنویسی
در حالی که CSS:
✔ خودش اضافه و حذف رو مدیریت میکنه
اگر مرورگر:
API سریعتر بده
الگوریتم داخلی رو عوض کنه
تو باید:
کدت رو rewrite کنی
ولی CSS:
✔ مرورگر بهینهسازی میکنه
✔ کدت ثابت میمونه
CSS در وب ≈ SQL در دیتابیس
وب دیتابیس

li.selected > p
مثل:
WHERE family = 'Sharks'
1️⃣ CSS
Styling
Responsive design
Dark mode
@media (max-width: 768px) { ... }
2️⃣ React / Vue / Angular
{isSelected && <Sharks />}
تو نمیگی:
createElement
appendChild
removeChild
Declarative UI 😎
3️⃣ XPath / XSL
تبدیل XML
گزارشگیری
PDF generation
document.querySelector("li.selected > p")
Declarativeتر از loop.
«CSS هم مثل SQL یک زبان declarative است؛ من فقط الگوی نتیجه را مشخص میکنم و موتور اجرا خودش تصمیم میگیرد چطور آن را اعمال کند.»
🟢 Declarative:
کوتاه
قابل بهینهسازی
خودکار با تغییرات sync میمونه
آیندهدار
🔴 Imperative:
verbose
fragile
پر از edge case
سخت نگهداری