Hossam Assadallah-حسام اسدالله

Hossam Assadallah-حسام اسدالله Oracle APEX Architect
Designing Scalable ERP & POS Systems
PL/SQL Performance • Clean Architecture • Integrations
Founder @ GooAdmin
(1)

17/08/2026

قصة حب مع الـ❤️❤️❤️ Dynamic Action

الـ Developer قال: “خلاص، هعمل كل حاجة بالـ Dynamic Actions، أنضف من الـ JavaScript.”

عمل واحد، اشتغل، فرح. بعدين عمل تاني وتالت ورابع على نفس الـ Item… لحد ما بقى عنده سبعة DAs شغالين مع بعض، زي واحد داخل يخطب ولاقى سبع دلالات بيتكلموا في نفس اللحظة.

DA بيقول “اعرضه”، التاني بيقول “امسحه”، التالت بيعمل Refresh للـ Region قبل ما التاني يخلص كلامه. فتح الـ Console لقى:

“Cannot read property ‘value’ of null”

يعني: بيدور على Item، DA قبله مسحه من الصفحة من ساعة.

الدرس؟ الـ Dynamic Action زي الصاحب اللي بيساعدك، واحد كفاية. لو سبعة هيتخانقوا على مين يمسك الحاجة الأول، وإنت اللي هتفرقهم🤣🤣🤣🤣🤣

16/08/2026

استخدام Global Temporary Table بدل Collection في APEX

١. إنشاء الجدول (مرة واحدة بس، في الـ schema)
CREATE GLOBAL TEMPORARY TABLE gtt_invoice_lines (
invoice_no VARCHAR2(20),
item_code VARCHAR2(50),
qty NUMBER,
price NUMBER,
line_total NUMBER GENERATED ALWAYS AS (qty * price),
session_id NUMBER DEFAULT SYS_CONTEXT('USERENV','SESSIONID')
)
ON COMMIT PRESERVE ROWS;

CREATE INDEX idx_gtt_item ON gtt_invoice_lines(item_code);

موجودة طول الـ session (زي الـ Collection بالظبط)، لو استخدمت ON COMMIT DELETE ROWS هتتمسح مع كل commit.
• كل session بتشوف بياناتها هي بس تلقائيًا، Oracle بتعزل البيانات per-session على مستوى الـ storage segment، فمش محتاج تفلتر بـ session_id يدويًا زي ما بتعمل مع الـ Collection (لكن ينفع تضيفه كـ safety net).

٢. الإدراج بدل APEX_COLLECTION.ADD_MEMBER
INSERT INTO gtt_invoice_lines (invoice_no, item_code, qty, price)
VALUES (:P1_INVOICE_NO, l_item_code, l_qty, l_price);
بدل
APEX_COLLECTION.ADD_MEMBER(
p_collection_name => 'INVOICE_LINES',
p_c001 => l_item_code,
p_n001 => l_qty
);

٣. العرض في الصفحة (Interactive Report / Grid)

استخدم الجدول مباشرة كمصدر للـ Region بدل APEX_COLLECTIONS:

مش محتاج WHERE collection_name = 'INVOICE_LINES' ولا seq_id.

٤. التحقق (Validation) على مستوى الجدول
ALTER TABLE gtt_invoice_lines
ADD CONSTRAINT chk_qty_positive CHECK (qty > 0);

٥. الترحيل ثم التنظيف
INSERT INTO real_invoice_lines (invoice_no, item_code, qty, price)
SELECT invoice_no, item_code, qty, price FROM gtt_invoice_lines
WHERE invoice_no = :P1_INVOICE_NO;

DELETE FROM gtt_invoice_lines WHERE invoice_no = :P1_INVOICE_NO;
COMMIT;

نقطة مهمة في APEX تحديدًا: الـ GTT بياناتها بترتبط بالـ database session، والـ APEX session مش دايمًا نفس الـ DB session بين الصفحات (يعتمد على connection pooling). عمليًا في معظم إعدادات APEX العادية (mod_plsql / ORDS مع session state protection) البيانات بتفضل متسقة، بس لو شغال على بنية فيها connection pooling عدواني، اختبر السيناريو ده كويس قبل ما تعتمد عليه بالكامل — دي أكبر ميزة كانت الـ Collection بتحلها تلقائيًا وهنا لازم تتأكد بنفس

14/08/2026

كنت مستعجل، وده كان أول غلط.

عميل طلب مني feature بسيط: يرفع ملف Excel، النظام يعالجه، ويعرضله preview قبل ما يتأكد الحفظ. حاجة كلاسيكية، عملتها قبل كده مية مرة. فاخترت الحل السريع: APEX Collection. تعمل Create، تحط البيانات، تعرضها في Interactive Report، وخلاص.

اشتغل تمام في الاختبار. اشتغل تمام مع أول 5 عملاء. المشكلة ظهرت بعد أسبوعين، لما عميل رفع ملف فيه 3000 صف.

الصفحة بقت بطيئة بشكل محرج. مش بطيئة شوية، بطيئة لدرجة إن العميل بعتلي رسالة يسأل هل النظام "واقع".

فضلت أراجع الكود ساعتين مقتنع إن المشكلة في الـ SQL بتاعي. غيرت الـ query، ضفت indexes وهمية، لغيت كل حاجة ممكنة. لحد ما رجعت لأساسيات الـ Collection نفسها، ولقيت المشكلة قدامي.

جدول WWV_FLOW_COLLECTIONS$ اللي بتتخزن فيه الـ Collections مش جدول عادي. كل الأعمدة فيه generic، C001 لحد C050 كلهم varchar2، N001 لحد N005 number، وهكذا. يعني مفيش data type حقيقي، ومفيش index حقيقي غير الـ SEQ_ID. ومع كده، الجدول ده shared بين كل الـ sessions النشطة في الـ APEX instance كله، مش بس session العميل.

يعني مع 3000 صف، أنا مش بس بستعلم على بيانات العميل، أنا بستعلم على جدول فيه بيانات مئات المستخدمين التانيين اللي شغالين على نفس الـ instance في نفس اللحظة.

الحل كان بسيط لما فهمت المشكلة صح: استبدال الـ Collection بـ Global Temporary Table حقيقي، بأعمدة ودية معرّفة صح، وindex على اللي محتاجه. الأداء رجع طبيعي في نفس اليوم.

الدرس مش إن الـ Collections سيئة، هي أداة ممتازة لحالات صغيرة ومؤقتة زي wizard steps أو shopping cart بسيط. المشكلة إنها بتتحول لعادة، وبتتستخدم في حالات مش مصممة لها أصلاً، وساعتها بتدفع التمن في الإنتاج مش في التطوير.

إنت بتستخدم إيه لتخزين البيانات المؤقتة في تطبيقاتك؟ Collections ولا Temporary Tables ولا حل تاني خالص؟

#برمجة

13/08/2026

فيه ناس بتفتكر إن “التفكير البرمجي” معناه إنك تكتب كود، بس الحقيقة إنه طريقة إنك تفكك بيها أي مشكلة معقدة لحتة أصغر وأبسط، تلاقي الباترن اللي بيتكرر فيها، وتحط خطوات واضحة عشان توصل لحل. زي ما بالظبط بتعمل لما بتكتب SQL معقد أو تصمم Schema لأوردر ماركت، إنت مش بتكتب أسطر، إنت بتفكك مشكلة العالم الحقيقي لخطوات منطقية.

اللي بيميز المبرمج المحترف مش إنه عارف لغة برمجة معينة، ده حاجة بتتعلمها في شهرين. اللي بيميزه إنه اتعود يسأل الأسئلة الصح: إيه المدخلات؟ إيه المخرجات؟ إيه الحالات الشاذة اللي ممكن تكسر النظام؟ فين نقطة الفشل؟ ده بالظبط اللي بيفرق بين حد بيلزّق كود من ستاك أوفرفلو، وحد بيبني نظام يقدر يستحمل الضغط.

وأنا شايف إن الطريقة الوحيدة إنك تنمّي العقل ده، مش إنك تحفظ سينتاكس، ده إنك تشتغل على مشاكل حقيقية، وتقع، وتصلح، وتفهم ليه الحل اللي اخترته كان غلط من الأساس. كل باج واجهتك في حياتك المهنية درّبك تفكر بطريقة مختلفة عن اللي قبله.

إنت لو مبرمج، إيه أكتر حاجة علمتك تفكر بمنطقية أكتر في شغلك؟

#برمجة

12/08/2026

لو لسه مفكر تتعلم Node.js ولا لأ... الجواب: ابدأ النهارده.

مش عشان Node.js "أحسن لغة"، لكن عشان الفكرة اللي هتفهمها منها هتغيرلك طريقة تفكيرك في البرمجة كلها. هتتعلم إزاي تفكر في العمليات كأحداث مش كخطوات مرتبة، وهتفهم إزاي تتعامل مع آلاف الطلبات المتزامنة بعقلية بسيطة بدل تعقيد الخيوط التقليدي.

الحلو في Node.js إنه سهل البداية. مش محتاج سيرفر ضخم ولا إعدادات معقدة، مجرد npm init وابدأ تكتب. أول API بسيط ممكن تشغله في نص ساعة، وده بيدّيك إحساس إنجاز سريع بيخليك مكمل.

وسوق الشغل بيسأل عليه بقوة، خصوصًا مع React وExpress وTypeScript، فإنت مش بس بتتعلم مهارة، بتفتح باب حقيقي.

ابدأ بمشروع صغير: API بسيط لإدارة قائمة مهام، أو بوت تليجرام، أي حاجة تلمسها بإيدك. الخطأ الشائع إن الناس بتفضل تقرا نظري كتير قبل ما تكتب سطر واحد. اكسر العادة دي من أول يوم.

مين فيكم بدأ فعلًا في Node.js؟ شارك أول مشروع عملته، ولو لسه مش بادئ، إيه اللي واقف قدامك؟

#برمجة

11/08/2026

كنت واقف في نص المشروع، بين نظامين بيتكلموا نفس اللغة (REST) بس مش نفس العقلية.

من ناحية، كنت بابني تكامل الفوترة الإلكترونية مع مصلحة الضرائب باستخدام Node.js، وكل Endpoint كنت بكتبه بإيدي، من الـ routing لحد التوقيع الرقمي CAdES-BES، ولحد التعامل مع كل خطأ ممكن يرجع من السيرفر.

من ناحية تانية، كنت شغال على بوابة HR كاملة فوق أوراكل APEX، وكل اللي محتاجه إني أعمل ORDS Module واحد، وأربطه بجدول أو Procedure، وخلاص عندي Endpoint جاهز شغال، بيتكلم مباشرة مع الداتابيز من غير ما أكتب سطر تحقق واحد يدوي.

الفرق مش في "أنهي أسرع"، الفرق في "مين بيمسك المسؤولية".

في Node.js، إنت المسؤول عن كل حاجة، الـ Validation، الـ Auth، الـ Error Handling، شكل الـ Response، حتى لو غلطت في تفصيلة صغيرة زي مسافة زيادة في String قبل التوقيع، النظام كله ممكن يقع، وده حصل معايا فعلاً وقفت عليه أيام لحد ما لقيت السبب.

في ORDS جوه APEX، الداتابيز نفسها بتمسك جزء كبير من المسؤولية دي. الـ PL/SQL بتاعك بقى هو منطق العمل، وORDS بس بيغلفه في REST، فإنت بتكسب سرعة تنفيذ رهيبة، بس بتدفع التمن في المرونة، لو حبيت تغيّر شكل الـ Response أو تضيف طبقة معقدة من الـ Business Logic اللي مش مرتبطة بالداتابيز، هتلاقي نفسك بتلف حوالين القيود.

الدرس اللي طلعت بيه: مفيش حل "أحسن" على طول، فيه حل مناسب للمشكلة اللي قدامك. لو النظام قلبه الداتابيز والعمليات معقدة جوه أوراكل، ORDS هيوفرلك وقت مش هتصدقه. لو النظام محتاج مرونة كبيرة وتكامل مع خدمات خارجية كتير، Node.js هيدّيك التحكم اللي محتاجه، حتى لو التمن مجهود إضافي.

إنت بتختار إزاي بين الاتنين في مشاريعك؟ ولا بتستخدمهم مع بعض؟

#برمجة #أوراكل

08/08/2026

الساعة واحدة ونص بالليل، والعميل بيتصل مضايق: "فرع المهندسين باع أوردر، وفرع مدينة نصر باع نفس الصنف كأنه لسه موجود".

المشكلة مكانتش في المنطق التجاري، كانت في التزامن. كل فرع بيبعت تحديثاته للسيرفر كل فترة، وفي اللحظة اللي بين البيع والتحديث، فرع تاني بيشتغل على بيانات قديمة من غير ما يحس.

جربنا الحل السهل: Polling، يعني كل فرع يسأل السيرفر كل كام ثانية "فيه جديد؟". اشتغل، بس بتكلفة موارد عالية وتأخير مستمر. إحنا كنا بنلاحق المشكلة مش بنحلها.

الحل الحقيقي كان قلب المنطق: بدل ما الفرع يسأل، خلي السيرفر يبلّغ. باستخدام WebSocket في Node.js، فتحنا قناة اتصال دائمة بين كل فرع والسيرفر، فلحظة ما بيع يحصل، كل الفروع تعرف فورًا.

وعشان النت مش دايمًا مستقر، ضفنا Pending Queue محلي بيحتفظ بالعمليات وقت الانقطاع، ويزامنها تلقائي أول ما الاتصال يرجع. النظام بقى Local-first، شغال حتى من غير نت.

الدرس: أي نظام Real-time لازم من أول يوم تسأل نفسك "لو النت وقع، هيحصل إيه؟". لو مش عارف الإجابة، النظام لسه مش جاهز للواقع.

إنتم واجهتوا مشكلة تزامن زي دي؟ حليتوها إزاي؟

07/08/2026

من كام شهر وإحنا في Gooshylx بنشتغل على حاجة مختلفة عن أي حاجة عملناها قبل كده.

مش برنامج جديد بالمعنى المعتاد، ومش تطبيق حاطين فيه AI عشان نقول “عندنا AI”.

كنا قاعدين بنسأل نفسنا سؤال بسيط: إيه اللي هيحصل لو بيانات شركتك بقت تقدر تتكلم معاك؟

من السؤال ده طلع “أمين”

أمين ببساطة هو المساعد اللي هتتكلم معاه زي ما بتتكلم مع حد شغال معاك في الشركة. تسأله عن المبيعات، المشتريات، العملاء، المخزون، شؤون العاملين الحسابات الضرائب مرتبات إلخ… أي تحليل محتاجه… وهو يرد عليك من بياناتك الحقيقية، مباشرة.

المشكلة اللي كنا شايفينها من زمان إن أي نظام جديد بتشتغل عليه، إنت اللي بتتعلمه — تتعلم مكان كل زرار، وكل تقرير فين، وإزاي تستخرج المعلومة. إحنا حبينا نقلب الموضوع: بدل ما إنت تتعلم النظام، خلي النظام هو اللي يفهمك.

وأنا فخور إني أقولكم إن أمين هيبدأ يطلع للسوق يوم 15 أغسطس 2026.

مش بس Launch لتطبيق. دي أول خطوة في تجربة إحنا شخصياً متحمسين لها جداً، وحابين نشارككم فيها من أول يوم.

05/08/2026

Gooshylx tech

Address

Hurghada Ras Gharib Road, الغردقة, البحر الاحمر, مصر
Hurghada

Alerts

Be the first to know and let us send you an email when Hossam Assadallah-حسام اسدالله posts news and promotions. Your email address will not be used for any other purpose, and you can unsubscribe at any time.

Contact The Business

Send a message to Hossam Assadallah-حسام اسدالله:

Shortcuts

Share