من أكثر المشاكل التقنية التي تبدو غريبة في البداية أن يعمل التطبيق بشكل طبيعي على جهاز المطور، ثم يبدأ بإظهار الأخطاء فور رفعه إلى الخادم.
العبارة الشهيرة هنا:
> "لكنه يعمل عندي."
وغالبًا المشكلة ليست في الكود نفسه، بل في **البيئة التي يعمل فيها الكود**.
## أين تبدأ المشكلة؟
لنفترض أنك تطور تطبيق Python يستخدم ملفًا محليًا:
```python
with open("config.json") as file:
config = json.load(file)
```
على جهازك يعمل الكود بدون أي مشكلة.
لكن بعد رفع التطبيق إلى Linux Server يظهر:
```text
FileNotFoundError: [Errno 2] No such file or directory: 'config.json'
```
أول رد فعل قد يكون:
"الملف موجود فعلًا."
وهنا تبدأ المشكلة الحقيقية.
الملف موجود، لكن البرنامج لا يبحث عنه بالضرورة في المكان الذي تتوقعه.
---
## المسار النسبي ليس مسارًا ثابتًا
عندما تكتب:
```python
open("config.json")
```
أنت لا تقول للبرنامج:
> افتح `config.json` الموجود بجانب هذا الملف البرمجي.
بل تقول:
> افتح `config.json` بالنسبة إلى **مجلد التشغيل الحالي**.
وهذا فرق مهم.
مثلًا، إذا كان المشروع:
```text
project/
├── app.py
├── config.json
└── services/
└── users.py
```
وشغلت التطبيق من:
```bash
cd project
python app.py
```
فسيبحث Python عن:
```text
project/config.json
```
لكن إذا شغلت التطبيق من مكان مختلف:
```bash
cd /var/www
python /var/www/project/app.py
```
فقد يبحث عن:
```text
/var/www/config.json
```
وليس:
```text
/var/www/project/config.json
```
الكود نفسه لم يتغير.
**الذي تغير هو Current Working Directory.**
---
## الحل الأفضل: ابنِ المسار اعتمادًا على موقع الملف
بدل الاعتماد على مكان تشغيل البرنامج، اجعل المسار مرتبطًا بموقع الكود نفسه.
في Python يمكن استخدام `pathlib`:
```python
from pathlib import Path
import json
BASE_DIR = Path(__file__).resolve().parent
CONFIG_FILE = BASE_DIR / "config.json"
with CONFIG_FILE.open("r", encoding="utf-8") as file:
config = json.load(file)
```
الآن أصبح البرنامج يعرف مكان `config.json` بناءً على مكان الملف البرمجي، وليس بناءً على المكان الذي شُغّل منه التطبيق.
وهذا يجعل السلوك أكثر استقرارًا عند التشغيل محليًا أو عبر:
* Gunicorn
* systemd
* Docker
* Cron
* CI/CD
* بيئة استضافة مختلفة
---
## لكن لماذا تظهر المشكلة عند النشر فقط؟
لأن بيئة التطوير المحلية غالبًا تكون أبسط.
أنت تعرف:
```text
أين المشروع
أين الملفات
من أي مجلد تشغله
أي Python تستخدم
أي متغيرات بيئية موجودة
```
لكن الخادم قد يشغّل التطبيق بطريقة مختلفة تمامًا.
مثلًا باستخدام `systemd`:
```ini
[Service]
WorkingDirectory=/var/www/myapp
ExecStart=/var/www/myapp/venv/bin/gunicorn app:app
```
هنا أصبح `WorkingDirectory` جزءًا من سلوك التطبيق.
إذا تغير هذا المسار، أو لم يتم تحديده أصلًا، فقد تبدأ المسارات النسبية في التصرف بطريقة مختلفة.
---
## ليست المشكلة في الملفات فقط
نفس الفكرة تنطبق على متغيرات البيئة.
قد يعمل التطبيق عندك لأن جهازك يحتوي على:
```text
DATABASE_URL
SECRET_KEY
API_KEY
```
لكن الخادم لا يحتوي عليها.
فتجد:
```python
os.getenv("DATABASE_URL")
```
يعيد:
```python
None
```
ثم يظهر الخطأ لاحقًا في مكان مختلف تمامًا.
وهنا الخطأ الظاهر قد لا يكون هو السبب الحقيقي.
لذلك عند ظهور مشكلة بعد النشر، لا تسأل فقط:
> "أين الخطأ في الكود؟"
بل اسأل:
> "ما الذي يختلف بين البيئتين؟"
---
## قاعدة بسيطة تختصر كثيرًا من وقت التصحيح
عندما يعمل التطبيق محليًا ويفشل في الإنتاج، قارن هذه الأشياء أولًا:
```text
Python version
Dependencies
Environment variables
Current working directory
File paths
File permissions
Database configuration
Operating system
Network access
Service configuration
```
في كثير من الحالات ستجد أن الكود لم يكن هو المشكلة أصلًا.
---
## الخلاصة
البرمجيات لا تعمل داخل الكود فقط.
هي تعمل داخل **بيئة تنفيذ كاملة**.
ولهذا فإن عبارة:
> "يعمل عندي"
لا تعني أن البرنامج صحيح، كما أن:
> "لا يعمل على السيرفر"
لا تعني أن الكود خاطئ.
الفرق بين المطور الذي يضيع ساعات في البحث والمطور الذي يجد السبب بسرعة هو قدرته على النظر إلى النظام كاملًا:
**الكود + البيئة + طريقة التشغيل + الموارد + الإعدادات.**
وأحيانًا يكون سبب الخطأ مجرد سطر صغير مثل:
```python
open("config.json")
```
لكن المشكلة الحقيقية كانت في افتراض أن البرنامج سيُشغّل دائمًا من المكان الذي تتوقعه.