ویرگول
ورودثبت نام
Setare Behzadi
Setare Behzadiمهندسی نرم افزار و توسعه دهنده وب | نکاتی در مورد وب که فکر میکنم میتونه واسه خیلی ها مناسب باشد رو منتشر میکنم.
Setare Behzadi
Setare Behzadi
خواندن ۵ دقیقه·۱ روز پیش

خلاصه کتاب Designing Data-Intensive Applications

فصل ۲- Query Languages for Data- قسمت۳

تفاوت Imperative و Declarative

1️⃣ Imperative یعنی «چطور انجام بده»

وقتی با زبان‌های برنامه‌نویسی معمولی مثل Python / JS / Java کار می‌کنی، داری دستورالعمل می‌دی:

اول این کار رو بکن
بعد برو سراغ بعدی
اگه شرط درست بود فلان کار
حلقه بزن، متغیر عوض کن، ادامه بده

مثلاً:

for (...) { if (...) { push(...) } }

اینجا داری الگوریتم رو دقیق می‌نویسی
کامپیوتر حق فکر کردن نداره، فقط اجرا می‌کنه.


2️⃣ Declarative یعنی «چی می‌خوام»

اما SQL اینجوری نیست. تو فقط می‌گی:

من حیواناتی رو می‌خوام که خانواده‌شون Sharks باشه

SELECT * FROM animals WHERE family = 'Sharks';

❌ نمی‌گی:

  • از کدوم ایندکس استفاده کن

  • اول کدوم رکورد رو بخون

  • حلقه بزن یا نزن

  • ترتیب چطوره

✔ فقط نتیجه مهمه، نه مسیر رسیدن بهش.


چرا این فرق خیلی مهمه؟

🧠 1. دیتابیس از تو باهوش‌تره

تو به عنوان برنامه‌نویس:

  • حجم دیتا رو دقیق نمی‌دونی

  • ایندکس‌ها ممکنه عوض بشن

  • دیتابیس ممکنه توی چند ماشین پخش شده باشه

Query Optimizer داخل DB:

  • می‌فهمه از کدوم ایندکس استفاده کنه

  • join رو با چه الگوریتمی بزنه

  • حتی ترتیب اجرا رو عوض می‌کنه

اگر imperative بنویسی، دست دیتابیس بسته‌ست.


🧱 2. پنهان شدن جزئیات پیاده‌سازی

فرض کن:

  • دیتابیس برای بهینه‌سازی، رکوردها رو جابه‌جا می‌کنه

  • ترتیب فیزیکی داده روی دیسک عوض می‌شه

SQL می‌گه:

من هیچ تضمینی روی order نخواستم

پس دیتابیس آزاده.

اما توی کد imperative:

animals[0]

ممکنه ناخواسته به ترتیب وابسته باشی
و دیتابیس نمی‌تونه ریسک کنه.


🚀 3. بهینه‌سازی بدون تغییر کد

این خیلی مهمه:

دیتابیس می‌تونه سریع‌تر بشه
بدون اینکه تو حتی یک خط Query رو تغییر بدی

چرا؟
چون الگوریتم دست دیتابیسه، نه دست تو.


⚡ 4. اجرای موازی (Parallelism)

CPUها دیگه خیلی سریع‌تر نمی‌شن؛
فقط core بیشتر دارن.

Imperative:

  • ترتیب مشخص

  • step به step

  • موازی‌سازی خیلی سخت

Declarative:

  • فقط می‌گه «نتیجه چی باشه»

  • دیتابیس می‌تونه:

    • دیتا رو تکه‌تکه کنه

    • روی چند core / چند ماشین اجرا کنه

    • آخرش نتیجه رو merge کنه


جمع‌بندی

🟢 Imperative

کنترل کامل داری، ولی مقیاس‌پذیری و بهینه‌سازی فاجعه می‌شه

🟢 Declarative (مثل SQL)

کنترل کمتر، ولی:

  • سریع‌تر

  • امن‌تر

  • مقیاس‌پذیرتر

  • آینده‌دارتر


یک جمله طلایی برای یادت:

SQL به دیتابیس می‌گه «چی می‌خوام»، نه «چطوری بهش برسی» — و همین باعث قدرتمند بودنشه.

بریم یک لِول عمیق‌تر؛ همون توضیح قبلی، ولی این‌بار با نگاه معماری و تجربه‌ی واقعی پروژه
(همونی که سینیورها بعد از یکی‌دو سیستم دردناک می‌فهمن 😄)

1️⃣ Declarative vs Imperative در ORMها (جایی که همه زمین می‌خورن)

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

تا وقتی می‌تونی، دیتابیس رو مجبور کن فکر کنه، نه اپلیکیشن رو


2️⃣ Declarative بودن یعنی «Lazy Execution»

این خیلی مهمه 👇

qs = User.objects.filter(is_active=True)

اینجا:

  • کوئری هنوز اجرا نشده

  • فقط تعریف شده

اجرا کی اتفاق می‌افته؟

list(qs) qs.first() qs.count()

این یعنی:

  • ORM می‌تونه کوئری رو merge کنه

  • فیلترها رو ترکیب کنه

  • order رو تغییر بده

Declarative ⇒ قابل بهینه‌سازی


3️⃣ وقتی Declarative رو می‌شکنی (Anti-patternهای خطرناک)

❌ loop + query

for user in users: user.posts.count()

نتیجه:

  • N+1 Query

  • دیتابیس خفه می‌شه

✔ Declarative:

User.objects.annotate(post_count=Count("posts"))

اینجا:

  • دیتابیس خودش JOIN می‌زنه

  • aggregate می‌کنه

  • با یک query برمی‌گردونه


4️⃣ Declarative در برابر Cache (Redis + DB)

اینجا می‌رسیم به سؤال سینیوری 👀

سناریو:

  • دیتابیس: PostgreSQL

  • کش: Redis

  • Query declarative

  • DB رکورد رو lock کرده (transaction)

چی می‌شه؟

  • DB: نسخه‌ی جدید رکورد داخل transaction

  • Redis: هنوز نسخه‌ی قدیمی

Declarative بودن کمک می‌کنه چون:

  • تو وابسته به order یا state نیستی

  • فقط state نهایی مهمه

الگوی درست:

  • Cache Aside Pattern

  • بعد از commit → invalidate redis

  • یا TTL کوتاه

Declarative Query کمک می‌کنه چون:

نتیجه مهمه، نه مسیر رسیدن بهش


5️⃣ Declarative ⇒ Parallel Execution (واقعی، نه شعاری)

SQL:

SELECT family, COUNT(*) FROM animals GROUP BY family;

DB می‌تونه:

  • جدول رو تکه کنه

  • هر core یه chunk رو بشماره

  • آخر merge کنه

Imperative code:

for animal in animals: ...

❌ ترتیب مهمه
❌ موازی‌سازی خطرناکه
❌ race condition


6️⃣ Declarative باعث می‌شه سیستم «آینده‌دار» باشه

فرض کن:

  • امروز دیتابیس کوچیکه

  • فردا sharding می‌کنی

  • پس‌فردا replica اضافه می‌کنی

اگر کوئری‌هات declarative باشه:

  • بدون تغییر کد scale می‌کنی

اگر imperative باشه:

  • کل بیزینس لاجیک باید rewrite بشه


7️⃣ جمع‌بندی خیلی خلاصه

🟢 Declarative:

  • SQL

  • ORM QuerySet

  • Map / Reduce

  • Elasticsearch DSL

🔴 Imperative:

  • loop

  • if

  • mutable state

  • order-dependent logic


جمله‌ای که باید حک کنی تو مغزت:

هرجا دیتا زیاد می‌شه، Imperative می‌میره و Declarative زنده می‌مونه.

Declarative Queries on the Web

این دقیقاً همون قسمتی است که مفهوم Declarative از دیتابیس میاد توی زندگی واقعی وب.

ایده‌ی اصلی این بخش چیه؟ (یک جمله‌ای)

Declarative فقط مخصوص SQL نیست؛ هرجا «چی می‌خوام» رو بگی و «چطور انجام بده» رو بسپاری به سیستم، داری declarative کار می‌کنی.

وب (CSS، XSL، حتی React) پر از declarative است.


1️⃣ سناریو ساده

سایت درباره‌ی حیوانات دریایی داریم 🐟
کاربر روی صفحه‌ی Sharks هست.

HTML:

<li class="selected"> <p>Sharks</p> </li> <li> <p>Whales</p> </li>

می‌خوای:

عنوان صفحه‌ی انتخاب‌شده آبی بشه


2️⃣ راه Declarative (CSS) ✅

li.selected > p { background-color: blue; }

این خط چی می‌گه؟

  • من دنبال <p> می‌گردم

  • که پدرش <li> باشه

  • و اون <li> کلاس selected داشته باشه

  • همونا رو آبی کن

❗ نکته مهم:

  • نگفتی loop بزن

  • نگفتی چک کن چندتا هست

  • نگفتی کی اضافه کن یا حذف کن

فقط الگو (pattern) رو گفتی.


3️⃣ چرا این فوق‌العاده‌ست؟

مزیت 1: اتوماتیک به تغییرات واکنش می‌ده

اگر:

<li class="selected"> ← حذف بشه

CSS خودش:

  • می‌فهمه rule دیگه match نمی‌کنه

  • رنگ آبی رو حذف می‌کنه

❌ هیچ کدی دوباره اجرا نمی‌کنی
✔ سیستم خودش sync می‌مونه


4️⃣ راه Imperative (JavaScript DOM) ❌

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
🤮 سخت نگهداری


5️⃣ مشکل‌های خطرناک Imperative (خیلی مهم)

❌ مشکل 1: حالت برنمی‌گرده

اگر بعداً:

li.className = ""

چی می‌شه؟

  • رنگ آبی باقی می‌مونه 😐

  • باید کد جدا برای remove بنویسی

در حالی که CSS:
✔ خودش اضافه و حذف رو مدیریت می‌کنه


❌ مشکل 2: وابستگی به API

اگر مرورگر:

  • API سریع‌تر بده

  • الگوریتم داخلی رو عوض کنه

تو باید:

  • کدت رو rewrite کنی

ولی CSS:
✔ مرورگر بهینه‌سازی می‌کنه
✔ کدت ثابت می‌مونه


6️⃣ تشبیه مستقیم با دیتابیس (اینجا مغز قفل می‌کنه 🔥)

CSS در وب ≈ SQL در دیتابیس

وب دیتابیس

CSS در وب ≈ SQL در دیتابیس
CSS در وب ≈ SQL در دیتابیس

li.selected > p

مثل:

WHERE family = 'Sharks'

7️⃣ کاربردهای واقعی Declarative در وب (خیلی مهم)

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


4️⃣ حتی QuerySelector

document.querySelector("li.selected > p")

Declarative‌تر از loop.


8️⃣ جمله‌ی مهم نهایی (حفظ کن)

«CSS هم مثل SQL یک زبان declarative است؛ من فقط الگوی نتیجه را مشخص می‌کنم و موتور اجرا خودش تصمیم می‌گیرد چطور آن را اعمال کند.»


جمع‌بندی خیلی خلاصه

🟢 Declarative:

  • کوتاه

  • قابل بهینه‌سازی

  • خودکار با تغییرات sync می‌مونه

  • آینده‌دار

🔴 Imperative:

  • verbose

  • fragile

  • پر از edge case

  • سخت نگهداری

وب
۰
۰
Setare Behzadi
Setare Behzadi
مهندسی نرم افزار و توسعه دهنده وب | نکاتی در مورد وب که فکر میکنم میتونه واسه خیلی ها مناسب باشد رو منتشر میکنم.
شاید از این پست‌ها خوشتان بیاید