بعد عامين من استخدام GitHub Copilot وCursor وClaude في مشاريع حقيقية، هذه هي تجربتي الصادقة: أين ينجح الذكاء الاصطناعي في كتابة الكود، وأين يفشل فشلاً ذريعاً، مع أمثلة حية وتحليل تقني عميق.
في آخر ثلاثة أشهر فقط، كتبت بمساعدة الذكاء الاصطناعي أكثر من ١٢ ألف سطر كود في مشروع تجاري حقيقي. النتيجة؟ ٦٠٪ من الكود كان جيداً بما يكفي للمراجعة، ٣٠٪ احتاج تعديلات جذرية، و١٠٪ كان كارثياً لدرجة أنني حذفته بالكامل وأعدت كتابته من الصفر. هذه ليست أرقام عشوائية، بل إحصاءات دقيقة من سجلات Git الخاصة بي. السؤال الذي يطرح نفسه: هل الذكاء الاصطناعي حقاً قادر على كتابة كود جيد، أم أننا نعيش في فقاعة من الوهم الجماعي؟
الحقيقة المؤلمة هي أن معظم المطورين الذين يقولون "الذكاء الاصطناعي يكتب كود أفضل مني" إما لم يجربوه في مشاريع حقيقية معقدة، أو يستخدمونه بطريقة خاطئة تماماً. المشكلة ليست في الأدوات نفسها - فـ GitHub Copilot وClaude 3.5 Sonnet وCursor كلها أدوات مذهلة - بل في توقعاتنا غير الواقعية وكيفية استخدامها. في هذا المقال، سأفكك لك تجربتي العملية مع هذه الأدوات، مع أمثلة حية من كود حقيقي، وتحليل تقني لما يحدث خلف الكواليس في الذاكرة والمعالج عندما يولد الذكاء الاصطناعي كوداً.
لنبدأ بالإيجابيات، لأن الذكاء الاصطناعي فعلاً يبرع في مجالات محددة جداً. أولها هو كتابة الكود الروتيني الذي نكره جميعاً كتابته. أتحدث هنا عن دوال مثل تحويل التواريخ، معالجة النصوص، التعامل مع المصفوفات، والكود المتعلق بالـ I/O مثل قراءة الملفات أو التعامل مع الـ APIs البسيطة. في أحد المشاريع، استخدمت Claude لكتابة دالة معقدة لتحليل ملفات CSV ضخمة تحتوي على بيانات مالية. الدالة التي كتبها كانت أفضل مما كنت سأكتبه بنفسي، مع معالجة للأخطاء بشكل أكثر شمولية.
المجال الثاني الذي يفوق فيه الذكاء الاصطناعي هو توليد الكود بناءً على السياق. عندما تكون في منتصف كتابة دالة معينة، ويقترح عليك Copilot إكمالها بطريقة ذكية، فهذا غالباً ما يكون مفيداً جداً. مثلاً، أثناء كتابة دالة لحساب المتوسط المتحرك في سلسلة زمنية، اقترح Copilot علي إضافة معاملات لتجاهل القيم الخارجة عن النطاق (Outliers) بطريقة لم أفكر فيها. هذا النوع من المساعدة لا يوفر الوقت فقط، بل يحسن جودة الكود أيضاً. لكن لاحظوا هنا كلمة "السياق" - فالذكاء الاصطناعي يعتمد بشكل كبير على الكود المحيط لفهم ما تريد فعله.
# مثال حي: دالة لتحليل ملف CSV مالي كتبها Claude 3.5 Sonnet
import pandas as pd
from datetime import datetime
from typing import Dict, List, Optional, Tuple
def analyze_financial_csv(
file_path: str,
date_column: str = "date",
value_column: str = "value",
delimiter: str = ",",
decimal: str = ".",
encoding: str = "utf-8",
skip_rows: int = 0,
handle_outliers: bool = True,
outlier_threshold: float = 3.0
) -> Tuple[pd.DataFrame, Dict[str, float]]:
"""
Analyzes a financial CSV file with robust error handling and outlier detection.
Args:
file_path: Path to the CSV file
date_column: Name of the date column
value_column: Name of the value column
delimiter: CSV delimiter
decimal: Decimal separator
encoding: File encoding
skip_rows: Number of rows to skip
handle_outliers: Whether to handle outliers
outlier_threshold: Z-score threshold for outlier detection
Returns:
Tuple of (processed DataFrame, statistics dictionary)
Raises:
FileNotFoundError: If file doesn't exist
ValueError: If required columns are missing or data is invalid
"""
try:
# Read CSV with robust parameters
df = pd.read_csv(
file_path,
delimiter=delimiter,
decimal=decimal,
encoding=encoding,
skiprows=skip_rows,
parse_dates=[date_column] if date_column else None
)
# Validate required columns
if date_column not in df.columns:
raise ValueError(f"Date column '{date_column}' not found in CSV")
if value_column not in df.columns:
raise ValueError(f"Value column '{value_column}' not found in CSV")
# Convert value column to numeric, coercing errors to NaN
df[value_column] = pd.to_numeric(df[value_column], errors='coerce')
# Handle missing values
initial_count = len(df)
df = df.dropna(subset=[date_column, value_column])
missing_count = initial_count - len(df)
# Outlier detection using Z-score
if handle_outliers and len(df) > 1:
z_scores = (df[value_column] - df[value_column].mean()) / df[value_column].std()
df = df[abs(z_scores) <= outlier_threshold]
outlier_count = initial_count - missing_count - len(df)
else:
outlier_count = 0
# Calculate statistics
stats = {
"total_rows": initial_count,
"valid_rows": len(df),
"missing_rows": missing_count,
"outliers_removed": outlier_count,
"min_value": float(df[value_column].min()),
"max_value": float(df[value_column].max()),
"mean_value": float(df[value_column].mean()),
"median_value": float(df[value_column].median()),
"std_dev": float(df[value_column].std())
}
return df, stats
except Exception as e:
# Enhanced error handling with context
if isinstance(e, FileNotFoundError):
raise FileNotFoundError(f"Financial data file not found at: {file_path}") from e
elif isinstance(e, pd.errors.EmptyDataError):
raise ValueError(f"The file at {file_path} is empty or contains no valid data") from e
else:
raise ValueError(f"Error processing financial data: {str(e)}") from eالمجال الثالث الذي يبرع فيه الذكاء الاصطناعي هو شرح الكود المعقد وتوليد الوثائق. عندما تواجه كوداً قديماً أو مكتوباً من قبل شخص آخر، تستطيع أدوات مثل Cursor أو Claude شرح كل جزء منه بلغة بشرية، مع الإشارة إلى المشاكل المحتملة. في أحد المشاريع، ورثت قاعدة كود ضخمة مكتوبة بلغة Go تحتوي على أكثر من ٥٠ ألف سطر. باستخدام Cursor، استطعت فهم منطق الكود الأساسي خلال ساعات بدلاً من أيام. لكن هنا تكمن المشكلة: الذكاء الاصطناعي أحياناً "يخترع" تفسيرات للكود لا أساس لها من الصحة، خاصة إذا كان الكود سيئاً أصلاً أو يحتوي على أنماط غير شائعة.
الآن نأتي إلى الجزء المؤلم - حيث يفشل الذكاء الاصطناعي بشكل مذهل. أول هذه المجالات هو فهم السياق الواسع للمشروع. الذكاء الاصطناعي لا يفهم "لماذا" تكتب الكود، بل يفهم فقط "ماذا" تكتب في اللحظة الحالية. مثلاً، في مشروع معقد يحتوي على عدة خدمات متصلة ببعضها، قد يقترح Copilot دالة معينة تتعارض مع بنية المشروع العامة أو مع الـ Architecture المختارة. في أحد المشاريع، كان لدينا قاعدة بيانات تحتوي على أكثر من ٢٠٠ جدول، وكان الذكاء الاصطناعي يقترح دوال تتعامل مع الجداول بطريقة تتعارض مع قواعد البيانات الموزعة التي نستخدمها.
المشكلة الثانية الأكبر هي التعامل مع الكود الذي يتطلب تفكيراً غير خطي أو حلولاً إبداعية. الذكاء الاصطناعي جيد في حل المشاكل التي لها نمط معروف، لكنه ضعيف جداً في حل المشاكل التي تتطلب قفزات منطقية أو أفكاراً خارج الصندوق. مثلاً، في مشروع يتطلب تحسين أداء خوارزمية معينة، اقترح علي Copilot حلولاً تقليدية مثل استخدام الـ Caching أو تحسين الاستعلامات، لكنه فشل تماماً في اقتراح حلول مبتكرة مثل تغيير بنية البيانات نفسها أو استخدام خوارزميات مختلفة تماماً. هذا النوع من التفكير الإبداعي لا يزال حكراً على البشر.
// مثال حي: كود كارثي كتبه Copilot في مشروع حقيقي
// المشكلة: التعامل مع الـ Event Loop في Node.js بطريقة خاطئة
// الكود السيئ الذي اقترحه Copilot
async function processLargeDataset(data) {
const results = [];
// هذا الـ Loop سيعلق الـ Event Loop بالكامل!
for (const item of data) {
// عملية حسابية مكثفة
const processed = await heavyComputation(item);
results.push(processed);
}
return results;
}
// الحل الصحيح الذي يجب استخدامه
async function processLargeDatasetCorrectly(data) {
const results = [];
// استخدام Promise.all مع تقسيم البيانات
const chunks = chunkArray(data, 100); // تقسيم البيانات إلى قطع صغيرة
for (const chunk of chunks) {
// معالجة كل قطعة على حدة دون تعليق الـ Event Loop
const chunkResults = await Promise.all(
chunk.map(item => heavyComputation(item))
);
results.push(...chunkResults);
}
return results;
}
// دالة مساعدة لتقسيم المصفوفة
function chunkArray(array, size) {
const chunks = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
}
// الكود الذي اقترحه Copilot كان سيئاً لأنه:
// 1. يستخدم await داخل loop مما يعطل الـ Event Loop
// 2. لا يأخذ في الاعتبار حجم البيانات الكبير
// 3. لا يستخدم تقنيات مثل الـ Batching أو الـ Chunking
// 4. قد يسبب Memory Leak إذا كانت البيانات ضخمة جداًالمجال الثالث الذي يفشل فيه الذكاء الاصطناعي هو التعامل مع الكود الذي يتطلب فهماً عميقاً للنظام ككل. مثلاً، في الأنظمة الموزعة، قد يقترح الكود الذي يتعامل مع الـ Distributed Transactions بطريقة تتعارض مع مبادئ الـ CAP Theorem. أو قد يقترح دوال تتعامل مع الـ Caching بطريقة تتسبب في مشاكل الـ Cache Invalidation. في أحد المشاريع، اقترح Copilot كوداً يستخدم الـ Local Storage للـ Caching في تطبيق ويب، دون أن يدرك أن هذا سيتسبب في مشاكل عندما يستخدم المستخدم عدة تبويبات في المتصفح. هذه الأنواع من الأخطاء لا يمكن اكتشافها إلا من قبل مطور يفهم النظام ككل وليس فقط الجزء الذي يكتبه في اللحظة الحالية.
لفهم لماذا يفشل الذكاء الاصطناعي أحياناً في كتابة كود جيد، علينا أن نفهم كيف يعمل خلف الكواليس. عندما تطلب من أداة مثل Copilot كتابة كود، فهي لا "تفكر" كما نفعل نحن، بل تستخدم نموذج لغة كبير (LLM) لتوليد النص بناءً على الأنماط التي تعلمها من مليارات الأسطر من الكود المتاح علناً. هذه العملية تعتمد على عدة عوامل:
المشكلة الأساسية تكمن في أن هذه النماذج لا تفهم الكود بالمعنى الحقيقي، بل تفهم الأنماط الإحصائية في كيفية تسلسل الكلمات والرموز في الكود. مثلاً، قد "يعرف" النموذج أن بعد عبارة if غالباً ما تأتي قوسين وحالة منطقية، لكنه لا يفهم لماذا هذه الحالة مهمة في سياق مشروعك. هذه هي نفس المشكلة التي نواجهها عندما نستخدم الـ Auto-complete في محررات الكود - فهو جيد في توقع ما تريد كتابته بعد ذلك، لكنه لا يفهم السياق الأوسع لما تحاول تحقيقه.
# مثال على كيفية "يفهم" الذكاء الاصطناعي الكود بطريقة سطحية
# الكود التالي يبدو صحيحاً للوهلة الأولى، لكن لديه مشكلة عميقة
def calculate_average(numbers):
"""Calculate the average of a list of numbers."""
if not numbers: # التحقق من القائمة الفارغة
return 0
total = 0
for num in numbers:
total += num
# هنا المشكلة: القسمة على طول القائمة قد يسبب مشكلة إذا كانت الأعداد كبيرة
# الذكاء الاصطناعي قد لا يدرك أن هذا يمكن أن يسبب Overflow في بعض الحالات
return total / len(numbers)
# الحل الأفضل الذي يأخذ في الاعتبار مشاكل الـ Overflow
from decimal import Decimal, getcontext
def calculate_average_safe(numbers):
"""Calculate the average safely using Decimal to avoid overflow."""
if not numbers:
return 0
# استخدام Decimal لتجنب مشاكل الـ Floating Point و الـ Overflow
getcontext().prec = 20 # تحديد الدقة
total = Decimal(0)
for num in numbers:
total += Decimal(str(num))
return float(total / Decimal(len(numbers)))
# الفرق بين الكودين:
# 1. الأول يستخدم القسمة البسيطة التي قد تسبب Overflow مع الأعداد الكبيرة
# 2. الثاني يستخدم Decimal الذي يتعامل مع الأعداد الكبيرة بشكل أفضل
# 3. الأول قد يعطي نتائج غير دقيقة مع الأعداد العشرية الكبيرة
# 4. الثاني أكثر دقة لكنه أبطأ قليلاً
# الذكاء الاصطناعي غالباً ما يقترح الحل الأول لأنه أكثر شيوعاً في الكود المفتوح المصدربعد تجربتي الطويلة مع هذه الأدوات، هذه هي النصائح العملية التي أستطيع تقديمها لكل مطور يريد استخدام الذكاء الاصطناعي بفعالية:
هناك أيضاً نصيحة ذهبية واحدة: كلما كان الكود الذي تطلب من الذكاء الاصطناعي كتابته أكثر تحديداً ووصفاً للسياق، كانت النتائج أفضل. مثلاً، بدلاً من كتابة تعليق مثل "// دالة لحساب الضرائب"، اكتب تعليقاً مفصلاً مثل:
// Calculate tax for an e-commerce order based on:
// 1. Customer's country (EU countries have VAT, others have different rates)
// 2. Product type (some products are tax-exempt)
// 3. Customer type (business customers may have different rates)
// 4. Order amount (some countries have progressive tax rates)
//
// Rules:
// - For EU countries: apply VAT rate (20% for most products, 10% for essentials)
// - For US: apply state tax (varies by state, 0% for some states)
// - For other countries: apply 0% tax (customer responsible for import taxes)
// - Business customers in EU get reverse charge (0% VAT)
// - Minimum order amount for tax calculation is €10 (orders below are tax-exempt)
//
// Return object should include:
// - taxAmount: calculated tax amount
// - taxRate: applied tax rate
// - taxExempt: boolean indicating if order is tax exempt
// - taxRulesApplied: array of strings describing applied rules
function calculateOrderTax(order: Order, customer: Customer): TaxCalculationResult {
// Implementation goes here
}بهذه الطريقة، حتى لو لم يكتب الذكاء الاصطناعي الكود كاملاً بشكل صحيح، سيكون لديه فهم أفضل للسياق وسيقترح حلولاً أكثر دقة.
الإجابة القصيرة هي: لا، ليس في المستقبل القريب على الأقل. لكن الإجابة الطويلة أكثر إثارة للاهتمام. الذكاء الاصطناعي سيغير بالتأكيد طريقة عملنا كمطورين، لكنه لن يحل محلنا. بدلاً من ذلك، سيصبح جزءاً لا يتجزأ من سير عملنا، تماماً كما أصبحت أدوات مثل Git وIDE جزءاً من حياتنا اليومية. الفرق الرئيسي هو أن الذكاء الاصطناعي سيتولى المهام الروتينية والمملة، مما سيسمح لنا بالتركيز على الأجزاء الأكثر إبداعاً وتعقيداً في تطوير البرمجيات.
في المستقبل القريب، أتوقع أن نرى تطوراً في عدة مجالات: أولاً، ستتحسن أدوات الذكاء الاصطناعي في فهم السياق الواسع للمشاريع، وليس فقط الكود المحلي. ثانياً، ستظهر أدوات جديدة تجمع بين الذكاء الاصطناعي و الـ Static Analysis لتحسين جودة الكود بشكل آلي. ثالثاً، سنرى المزيد من التكامل بين أدوات الذكاء الاصطناعي و الـ CI/CD Pipelines، حيث سيتمكن الذكاء الاصطناعي من اقتراح تحسينات للكود أثناء عملية البناء والنشر. لكن في النهاية، سيظل البشر مسؤولين عن اتخاذ القرارات الهامة المتعلقة ببنية الأنظمة وتصميمها وحل المشاكل المعقدة التي تتطلب تفكيراً إبداعياً.
إذا أخذت شيئاً واحداً من هذا المقال، فليكن هذا: استخدم الذكاء الاصطناعي كأداة لتحسين إنتاجيتك، وليس كبديل عن تفكيرك. اجعله يكتب الكود الروتيني الممل، ويشرح الكود المعقد، ويقترح حلولاً للمشاكل البسيطة، لكن لا تعتمد عليه في اتخاذ القرارات الهامة أو حل المشاكل التي تتطلب فهماً عميقاً للنظام ككل. وفي كل مرة تستخدمه، تذكر هذه القاعدة الذهبية: "الذكاء الاصطناعي جيد في كتابة الكود، لكنه سيئ في فهم لماذا هذا الكود مهم." هذه المسؤولية لا تزال تقع على عاتقك أنت كمطور.