مرحبًا! أنا جوزيف، طالب علوم الكمبيوتر في واترلو، وقد أنهيت مؤخرًا تدريبًا في هندسة البرمجيات في Slash من سبتمبر إلى ديسمبر 2025. باختصار، لقد استمتعت كثيرًا وأعتقد أن عليك الانضمام. شكرًا على قراءتك.

حسناً، هذه المرة حقاً. لقد تدربت سابقاً في العديد من الشركات، من الشركات الناشئة الصغيرة المتعلقة بالموسيقى إلى شركات التكنولوجيا الكبرى، لكن Slash قدمت مزيجاً فريداً من الحماس والمسؤولية لم أجده في أي مكان آخر. كان الفريق ذكيًا ومترابطًا، وتعلمت الكثير عن العديد من الموضوعات المعقدة بدءًا من صيانة Kubernetes إلى أداء قواعد البيانات. والأهم من ذلك، كان هناك بعض التحديات المثيرة للاهتمام التي تمكنت من حلها، ولهذا قررت أن أكتب مدونة عن تجربتي!

لإعطاء ملخص سريع لما تفعله Slash، فقد بدأت كمنصة مالية لأشخاص مثل رواد الأعمال وبائعي الأحذية الرياضية، ولكنها الآن شركة تكنولوجيا مالية مصرفية عامة تقدم بطاقات الشركات والتحويلات الدولية وحسابات العملات المشفرة والمزيد. لم أكن أعرف الكثير عن هذا عندما تعرفت على Slash لأول مرة. ففي النهاية، أنا لست من هواة الأحذية الرياضية، ولم أكن ملمًا بالتكنولوجيا المالية، لذا قضيت الكثير من الوقت أفكر فيما إذا كانت هذه الفرصة تستحق العناء أم لا. ولكن، كما يمكنك أن ترى من هذه المدونة، كان قراري بالانضمام إلى الشركة أحد أفضل القرارات التي اتخذتها في بداية مسيرتي المهنية.

الأسباب الرئيسية التي دفعتني في النهاية إلى اختيار Slash على الشركات الأخرى هي:

  • كانت شركة من الفئة ب – لم يسبق لي أن عملت في شركة ناشئة بهذا الحجم، وأردت أن أجرب تلك البيئة.
  • بلغت إيراداتهم السنوية 150 مليون دولار، وهو رقم مرتفع للغاية بالنسبة لشركة في المرحلة الثانية من التمويل. – فهم لا يكتفون بالبقاء على قيد الحياة أو الصمود فحسب، بل إنهم يتوسعون بنشاط. وكميزة إضافية، هذا يعني أنهم على الأرجح يتمتعون بقدرات DX جيدة وصرامة هندسية تفتقر إليها العديد من الشركات الناشئة الصغيرة.
  • كانوا ينمون بنشاط – لقد ضاعفوا إيراداتهم 6 مرات في عام واحد وقاموا مؤخرًا بجمع تمويل من السلسلة B. كانت هذه الشركة في ذروة نموها، وأردت العمل في شركة تشهد هذا النوع من الزخم.
  • إنه فريق شاب وحيوي – من خلال المقابلات التي أجريتها، استطعت أن أرى أن الناس هنا هادئون وممتعون في الحديث معهم. كنت متحمسًا للعمل مع زملاء أستطيع التواصل معهم.
  • إنها شركة صغيرة ومتواضعة – هل ذكرت أن هذا الرقم البالغ 150 مليون دولار من العائدات السنوية المتكررة (ARR) تم تحقيقه بواسطة فريق مكون من حوالي 12 مهندسًا؟ هذا يعني 12.5 مليون دولار من العائدات السنوية المتكررة (ARR). لكل مهندس، وهو أمر رائع. من الواضح أن العاملين في Slash هم من أفضل المواهب، وسأحظى بملكية كبيرة وتوجيه رائع.
  • التعويضات والمزايا التي تقدمها الشركات الصغيرة هي الأفضل في مجال التدريب الداخلي... 🤫

TLDR، اعتقدت أن البيئة والمواهب الموجودة والطاقة النابضة بالحياة في الشركات الناشئة ستوفر مكانًا رائعًا للنمو. اعتقدت أنني سأحظى بفرصة لامتلاك مشروع من البداية إلى النهاية، بدءًا من إنشاء البنية التحتية إلى التخطيط حول قابلية التوسع إلى التفكير في تصميم النظام وغير ذلك، ولذا اغتنمت الفرصة!

المشروع: الإخطارات V2

هناك شيء خاص تعلمته على الفور عن Slash – فهم يعهدون بالمشاريع المهمة إلى المتدربين ويثقون في قدرتهم على إنجازها. في أسبوعي الثاني، كلفت بمهمة تجديد نظام إخطارات رفض معاملات البطاقات. لا يبدو الأمر صعباً، أليس كذلك؟ لكن نظام الإخطارات الحالي كان يعاني من بعض المشاكل:

  • ارتباط وثيق بنظام الأحداث الداخلي لدينا، مع منطق الأعمال المدمج في جوهر الخدمة
  • مقاييس بريد إلكتروني ضعيفة وأداء أسوأ في تسليم البريد الإلكتروني بسبب المزود الذي استخدمناه
  • تجربة مطور صعبة، مما دفع المهندسين إلى تجاوز النظام تمامًا والاتصال مباشرة بواجهات برمجة التطبيقات الخاصة بالمزود

وهكذا جاءت المهمة الصعبة – لإنشاء رسائل بريد إلكتروني أفضل للرفض، كنا بحاجة إلى أكثر من مجرد تصحيح. كنا بحاجة إلى نظام إخطارات معاد تصميمه بالكامل، وأصبحت المسؤول المباشر عن التصميم والتطوير والتطبيق والتوسع للمشروع بأكمله. كان ذلك أمرًا مخيفًا للغاية... ولكنه كان أيضًا فرصة رائعة لتصميم شيء سيتعامل في النهاية مع ملايين الإخطارات. كنت متحمسًا للبدء في العمل.

من خلال دراسة نظام الإخطار السابق ومناقشة الأمر مع المهندسين، توصلت إلى بعض المبادئ التي يجب أن يلتزم بها هذا النظام الجديد:

  1. تصميم غير مرتبط بحدث معين – يجب أن تكون الخدمة قادرة على العمل في أي مكان، سواء في البرامج النصية لمرة واحدة أو معالجات الأحداث
  2. تصميم غير مرتبط بمزود معين – إن فرصة إزالة مزودي الخدمة الحاليين وإدخال مزودي خدمة جدد بسهولة وبأقل جهد ممكن ستكون فرصة لا تقدر بثمن.
  3. تصميم يركز على المطورين أولاً – لا مزيد من الإحباط. يجب أن تكون تجربة التطوير بديهية وسهلة قدر الإمكان.
  4. قابل للملاحظة وقابل للتطوير - يجب أن تتضمن الإخطارات تتبعًا كاملًا لدورة الحياة، ويجب أن نتمكن في النهاية من دعم 3 ملايين بريد إلكتروني شهريًا!

ومن هنا، ولد التصميم القائم على المعالج لـ Notifications V2. يتمحور النظام حول معالجات الإشعارات، التي تعرض وظائف المعالج الشائعة، مثل إرسال الإشعارات أو معالجة webhooks، لمزودي قنوات خارجيين محددين (مثل Resend للبريد الإلكتروني و Twilio للرسائل القصيرة).

جوهر النظام هو إشعار النية، وهو كائن عابر عام يستخدم لنقل جميع البيانات الخاصة بالإشعار مثل المزود والقناة وحجج الحمولة. يحدد كل معالج شكل نواياه الخاصة، وهذه الكائنات مكتوبة بشكل قوي وبالتالي تدعم فحوصات النوع في الوقت الثابت والتأمل الذاتي. وهذا يعني أن المطورين لا يحتاجون إلى معرفة جميع تعقيدات كل مزود – يمكنهم الاستفادة من ميزة الإكمال التلقائي في IDE والثقة في أن فحص النوع سيقوم بهذه المهمة.

This example briefly illustrates how to use the service to send a variety of email notifications for an outgoing payment. All these create functions create notification intents, and they are strongly typed to suit the provider (in this case, Resend)
const sendOutgoingPaymentNotification = async (context: {
 transactionId: string;
 amount: number;
 recipientEmail: string;
 alertEmail: string;
}) => {
 const { transactionId, amount, recipientEmail, alertEmail } = context;
 const { originalSenderId } = getOriginalSenderForTransaction(transactionId);


 await notificationsV2Service.sendNotifications([
   // We can create a one-off notification easily...
   ResendNotification.create({
     email: {
       recipient: alertEmail,
       content: {
         subject: "INTERNAL ALERT: An employee just sent an outgoing payment",
         body: `An employee just sent an outgoing payment of $${amount}.`,
       },
     },
   }),
   // Or use a React Email template for pretty emails..
   ResendNotification.create({
     email: {
       recipient: recipientEmail,
       content: YouJustReceivedPaymentTemplate.withProps({ amount }),
     },
   }),
 ]);


 // Or send to specific users, respecting their preferences + registered emails
 await notificationsV2Service.sendNotificationsToUsers({
   users: [originalSenderId],
   preference: NotificationPreferences.PaymentConfirmation,
   createIntents: (user) => [
     ResendNotification.create({
       email: {
         recipient: user.registeredEmail,
         content: PaymentConfirmationTemplate.withProps({ amount }),
       },
     }),
   ],
 });
};

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

  • يمكننا تعريف وظيفة "إرسال إشعار" أساسية تتدفق فيها النوايا عبر المستلم محظور البرمجيات الوسيطة، التي تسقط النوايا إذا كانت معلومات المستلم (البريد الإلكتروني، رقم الهاتف) موجودة على قائمة حظر مخصصة
  • يمكننا تعريف وظيفة "إرسال إلى المستخدم" أكثر تعقيدًا تتدفق فيها النوايا عبر نفس المستلم محظور البرمجيات الوسيطة وكذلك احترام تفضيلات المستخدم البرمجيات الوسيطة، التي تسقط النوايا إذا اختار المستخدم إلغاء الاشتراك في الإشعارات على تلك القناة

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


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


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


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

  • لدينا إجراء لتحديث المستلمين – بهذه الطريقة، يمكن للمسؤولين تحديث المستلمين على أنهم "محظورون بشكل دائم" أو غير محظورين، اعتمادًا على ما يحدده المزود والقناة على أنه "محظور".
  • لدينا إجراء لإعادة محاولة إرسال إشعار – على سبيل المثال، إذا تم رفض رسالة بريد إلكتروني مؤقتًا، فإننا نريد إعادة محاولة إرسالها بشكل متكرر. إذا قرر المعالج أن استجابة مزود البريد الإلكتروني كانت "رفض"، فيمكنه تشغيل هذا الإجراء.

ProcessWebhook returns the same body structure, allowing specific webhook logic to be handled by the actual provider itself.
const statusMap: Record<string, string> = {
 bounced: "failed",
 // more statuses here...
};


const ResendHandler = createHandler({
 // This is a simple example of something we could do
 processWebhook: (webhookBody: ResendWebhook) => {
   const notificationId = extractIdFromWebhook(webhookBody);


   const newInternalStatus = statusMap[webhookBody.state];
  
   const actions = newInternalStatus === "failed"
     ? [{ action: "retryNotification", notificationId }]
     : [];


   return {
     status: newInternalStatus,
     actions,
   };
 },
});

يا للهول! هذا هو معظم التدفق. على طول الطريق، واجهت العديد من التحديات الهندسية الأخرى المثيرة للاهتمام، مثل

  • دعم المحاولات المتكررة الأسية – نقوم بجدولة مهام إعادة المحاولة المستقبلية داخل Temporal اعتمادًا على عدد المحاولات التي تم إجراؤها بالفعل
  • تتبع جيد – على سبيل المثال، نقوم بتخزين معرفات التتبع، بالإضافة إلى الإشعارات ومحاولات إعادة إرسالها، في إعدادات الإشعارات كيان
  • الإرسال المجمّع – يتيح لنا دمج الإرسال الفردي والإرسال المجمّع تجنب تجاوز حدود معدلات المزود ويمنح المطورين التحكم في كيفية إرسال الإشعارات.

سأدع أي مهندسين جدد محتملين يكتشفون التفاصيل في الكود، بمجرد انضمامهم 😉

المشروع: تجميل الوجه

كان مشروع Facelift عبارة عن إعادة تصميم شاملة من قبل فريقنا لتجربة الويب Slash (انظر مدونة eng هنا بواسطة ألبرت تيان، أبو عملية شد الوجه). لن أخوض في تفاصيل Facelift (مرة أخرى، انظر المدونة الرائعة للمهندسين)، ولكن جوهره كان تقديم مكتبة مكونات جديدة + Tailwind إلى واجهة المستخدم الضخمة بالكامل. الآن، استعدادًا للإطلاق، قرر فريق المهندسين الاستمتاع قليلاً وتنظيم أسبوع هاك مركّز! لم يكن هذا أسبوع الاختراق المعتاد في المكتب – فقد ركبنا بضع سيارات، وقطعنا مسافة ثلاث ساعات إلى كابينة في باس ليك بجانب يوسمايت، وقضينا الأسبوع في البناء وإعادة الهيكلة والاستمتاع بوقتنا معًا.

خلال هذا الأسبوع، انتقلت بالكامل من العمل في الخلفية للمساعدة في تحسين المعاملات وتدفق النزاعات. كان هذا في الغالب عملاً في الواجهة الأمامية، وهو تغيير منعش عن عملي السابق، كما أنه يعني أنني عملت على معظم البنية التحتية لتصميم الواجهة الأمامية، مثل:

  • الأساسيات الأساسية: على سبيل المثال، كيفية إنشاء الألواح الجانبية والنوافذ المنبثقة والنوافذ المؤقتة
  • مكونات قابلة لإعادة الاستخدام وقابلة للتركيب: على سبيل المثال، بحث قابل للتحديد
  • مدير الجدول: مكوننا المخصص لإنشاء جداول مع سهولة الفرز والتصفية وترقيم الصفحات والبحث
  • التحقق من صحة النموذج الفرعي القوي: باستخدام Arktype ونماذج Tanstack ونظام إنشاء النماذج الخاص بنا

لم يكن تجديد الموقع يتعلق بمنطق المنتج المعقد بقدر ما كان يتعلق بمشاهدة مدى سرعة تحرك فريقنا عندما يركز ويتماشى مع مشروع جماعي واحد. كانت مشاهدة تحول الموقع بالكامل على مدار الأسبوع، إلى جانب بناء علاقات مع زملائي في الكابينة المذكورة، من أبرز أحداث فترة تدريبي. لم تنته أعمال تجديد الموقع في ذلك الأسبوع، فخلال الأسبوعين التاليين حرصنا على أن يتم الإطلاق بسلاسة من خلال العمل مع فريق الدعم لإزالة الأخطاء الصغيرة في المنتج!

المشروع: القوالب

في نهاية كل فصل دراسي، ترسل جامعتي استمارة صغيرة تحتوي على سؤال بسيط: "ما مدى ملاءمة الدورات الدراسية التي درستها لعملك؟". حسناً، خلال فترة عملي في Slash، تمكنت بالفعل من تطبيق بعض المفاهيم التي تعلمتها في الفصل الدراسي بشكل مباشر! كنا نريد أن تتوافق رسائل البريد الإلكتروني الخاصة بالمعاملات مع تصميم Facelift الجديد، لذلك كان من المنطقي أن يدعم نظام الإشعارات لدينا قوالب مخصصة. لضمان استخدام نفس الألوان والمسافات المستخدمة في واجهة المستخدم، قمنا في النهاية بإنشاء هذه القوالب في الكود باستخدام React Email، وهي مكتبة قوالب بريد إلكتروني تسمح لنا باستخدام JSX لهذه القوالب. كان هذا مثالياً بالنسبة لنا؛ نظرًا لأن فريقنا على دراية تامة بـ React JSX، تمكنا من ضمان اتساق العلامة التجارية باستخدام نفس نظام تصميم Tailwind CSS v4 عبر كل من الويب والبريد الإلكتروني.

ومع ذلك، كان هناك عيب واحد – إحدى الميزات الرئيسية لـ TailwindCSS 4 هي قدرته على استخدام ملفات CSS مخصصة بدلاً من كائن التكوين JS التقليدي، وهو ما استفاد منه فريقنا. ومع ذلك، فإن مكون Tailwind في React Email في الواقع مطلوب كائن تكوين JS.

هذا يعني أنني يجب أن أبني مترجمًا!

@import "tailwindcss";

@import "../custom-styles.css";

@custom-variant dark (&:where(.dark, .dark *):not(:where(.light, .light *)));

@theme {
  --color-*: initial;

  --spacing-base-scale-0: 0px;
  --spacing-base-scale-1: 1px;
  --spacing-base-scale-2: 2px;
  --spacing-base-scale-4: 4px;
  --spacing-base-scale-6: 6px;
  --spacing-base-scale-8: 8px;
  --spacing-base-scale-12: 12px;
  --spacing-base-scale-14: 14px;
  --spacing-base-scale-16: 16px;
  --spacing-base-scale-20: 20px;
  --spacing-base-scale-24: 24px;
  --spacing-base-scale-28: 28px;
  --spacing-base-scale-32: 32px;
  --spacing-base-scale-36: 36px;
  --spacing-base-scale-40: 40px;
  --spacing-base-scale-44: 44px;
  --spacing-base-scale-48: 48px;
  --spacing-base-scale-52: 52px;
  --spacing-base-scale-56: 56px;
  --spacing-base-scale-60: 60px;
  --spacing-base-scale-64: 64px;
  --spacing-base-scale-68: 68px;
  --spacing-base-scale-72: 72px;
  --spacing-base-scale-76: 76px;
  --spacing-base-scale-80: 80px;
  --spacing-base-scale-84: 84px;
  --spacing-base-scale-88: 88px;
  --spacing-base-scale-92: 92px;
  --spacing-base-scale-96: 96px;
  --spacing-base-scale-100: 100px;
  --spacing-base-scale-104: 104px;
// WARNING: This file is generated by a script. Do not edit it manually.
// Generated from: ./lib/tailwind.build.css
// To regenerate: yarn build:tailwind-config

import type { GenericAny } from '@slashfi/slash-base';

const plugin = require('tailwindcss/plugin');

export default {
	theme: {
		extend: {
			backgroundColor: {
				"surface-subtle": "#f9f8f7",
				"surface-neutral": "#ffffff",
				"neutral-subtle-default": "#fcfcfb",
				"neutral-subtle-hover": "#f9f8f7",
				"neutral-subtle-active": "#f9f8f7",
				"neutral-subtle-disabled": "#fcfcfb",
				"neutral-normal-default": "#f9f8f7",
				"neutral-prominent-default": "#f4f3f1",
				"neutral-muted-default": "#e9e7e3",
				"neutral-bold-default": "#958f82",
				"neutral-bold-hover": "#6d685f",
				"neutral-bold-active": "#6d685f",
				"neutral-bold-disabled": "#bdb7aa",
				"neutral-muted-hover": "#e0ddd6",
				"neutral-muted-active": "#d9d6ce",
				"neutral-muted-disabled": "#efeeeb",
				"neutral-prominent-hover": "#efeeeb",
				"neutral-prominent-active": "#efeeeb",
				"neutral-prominent-disabled": "#fcfcfb",
				"neutral-normal-hover": "#f4f3f1",
				"neutral-normal-active": "#f4f3f1",
				"neutral-normal-disabled": "#fcfcfb",
				"neutral-bolder-default": "#6d685f",
				"neutral-boldest-default": "#32312c",
				"neutral-boldest-hover": "#32312c",
				"neutral-boldest-active": "#32312c",
				"neutral-boldest-disabled": "#bdb7aa",
				"neutral-bolder-hover": "#32312c",
				"neutral-bolder-active": "#32312c",
				"neutral-bolder-disabled": "#bdb7aa",
				"interactive-neutral-subtle-default": "#4b3a1c",
				"interactive-neutral-normal-default": "#4b3a1c",
				"interactive-neutral-prominent-default": "#4b3a1c",
				"interactive-neutral-prominent-hover": "#4b3a1c",
				"interactive-neutral-prominent-active": "#4b3a1c",
				"interactive-neutral-prominent-disabled": "#4b3a1c",
				"interactive-neutral-normal-hover": "#4b3a1c",
				"interactive-neutral-normal-active": "#4b3a1c",
				"interactive-neutral-normal-disabled": "#4b3a1c",
				"interactive-neutral-subtle-hover": "#4b3a1c",
				"interactive-neutral-subtle-active": "#4b3a1c",

لوصف ذلك بشكل أكثر دقة، خلال خطوة البناء، أضفت برنامجًا نصيًا لبناء شجرة تركيب مجردة (AST) من ملفات CSS لنظام التصميم. قدمت شجرة التركيب المجردة هذه تمثيلًا منظمًا لقواعد CSS، وسمحت لي بتحليل الملف بسهولة إلى:

  • تصفية فئات CSS غير المدعومة: على سبيل المثال، لا تعمل أنماط التمرير وأدوات المؤشر في معظم برامج البريد الإلكتروني.
  • تحويل إلى نظام ألوان متوافق: استخدمنا OKLCH لتحديد ألواننا، ولكن برامج البريد الإلكتروني لا تستطيع عرضها، لذا تم تحويلها إلى HEX.
  • إنشاء كائن تكوين TS: يتم تجميع هذا في JS، ومن ثم يمكن استيراده بسهولة إلى أي مكان في قاعدة الكود.

كانت خطوة التحويل هذه طريقة سريعة لتنفيذ مصدر وحيد للحقيقة لنظام التصميم لدينا. إذا تم تعديل لون ما، فسيكون متسقًا في جميع وسائطنا - الويب أو البريد الإلكتروني - لأنه سيتم تحويله فورًا بمجرد إعادة بنائه. بالإضافة إلى ذلك، يمكن لعملاء آخرين، مثل تطبيقنا للهاتف المحمول، استخدام هذا الكائن المحول حسب الحاجة. باستخدام كائن التكوين الذي تم إنشاؤه، تمكنت من إنشاء مجموعة من مكونات React الشائعة لرسائل البريد الإلكتروني لدينا والتي تعكس مكونات الويب لدينا، مثل الطباعة و زر المكونات، مع أدوات مساعدة متطابقة تقريبًا. كل هذا ساعد في تحسين تجربة المطورين، وجعل إنشاء القوالب أقل صعوبة!

وأخيرًا، قمت أيضًا بإنشاء قوالب إخطارات تستفيد من إطار العمل الداخلي الخاص بنا، وهو بنية بيانات مخصصة قمنا بإنشائها (انظر هذه المدونة). باختصار، توفر لنا السجلات طريقة آمنة من حيث النوع لتعريف القوالب وتسلسلها وإلغاء تسلسلها من قاعدة البيانات والحفاظ على منطق الأعمال محددًا معًا. على سبيل المثال، card-authorization.notification-template.tsx يقع مباشرة بجانب كود معالج أحداث تفويض البطاقة، وهو أمر رائع لرؤية الأحداث التي تحتوي على إشعارات بسرعة! كان من الرائع أن نتمكن من استخدام السجلات في هذا المشروع – فقد أظهر ذلك التزام الفريق بكتابة كود جيد وقابل لإعادة الاستخدام.


ماذا استفدت؟

جئت إلى هنا وأنا أعتقد أن هذه ستكون تجربة فريدة من نوعها، وأنا سعيد لأنني قررت الانضمام إلى هذه الشركة – فقد علمتني Slash عن الملكية وتصميم المنصات وسرعة الهندسة أكثر من أي وظيفة شغلتها من قبل. ومن أهم الدروس التي تعلمتها ما يلي:

  • الثقة لا تقدر بثمن – Slash لا يعقد اجتماعات يومية. Slash لا يعقد اجتماعات أسبوعية أو اجتماعات لتنظيم الأعمال المتأخرة. نحن نعقد اجتماعًا واحدًا في الأسبوع، وذلك فقط لعرض الأشياء التي قمنا ببنائها على الفريق بأكمله. هذا الأمر ينجح لأن الفريق بشكل عام يتمتع بمهارات اتصال قوية ومهارات ملكية رائعة. هذا لا يعني أنه لا يوجد توجيه – فأنا أعقد اجتماعات أسبوعية فردية لتحرير نفسي – ولكن بدلاً من ذلك، Slash يثق في أنك ستبذل قصارى جهدك في العمل ويهيئ بيئة يمكنك فيها التركيز قدر الإمكان.
  • الفريق رائع – في شركاتي التعاونية الأخرى، كان زملائي محترفين، ولكن هنا، كان زملائي في العمل شعبي. من الواضح أن Slash تتمتع بثقافة رائعة مع أشخاص ممتعين وداعمين وسهل التعامل معهم - لم يكن هناك شخص واحد لم أستمتع بالعمل معه أو أشعر بالخوف منه، وهم يعاملونك تمامًا كموظف بدوام كامل. بالإضافة إلى ذلك، يمكنك الذهاب للعب كرة السلة معهم في عطلات نهاية الأسبوع 😃
  • كمتدرب، ستنمو هنا بشكل كبير مقارنة بأي مكان آخر. – في أي شركة أخرى، لم يكن المتدرب ليحصل على نظام الإخطار الأساسي بأكمله كمشروع. فالمشاكل الصعبة التي تحفز النمو كانت ستحل أو يجري حلها من قبل أحد كبار المهندسين. ما يجعل Slash فريدة من نوعها هو الجمع بين فرق العمل الصغيرة والمشاكل الحقيقية الحاسمة للأعمال وثقافة تثق حتى بالمتدربين في الأعمال المهمة.

إليكم بعض الذكريات الممتعة الأخرى من فترة التدريب هذه:

  • لقد تناولنا ما مجموعه 20 رطلاً من شرائح اللحم في أسبوع واحد... شكراً يا أسبوع الاختراق!
  • لقد هزمت زميلي المتدرب في مسابقة بلياردو، ثم تعرضت على الفور لهزيمة نكراء على يد لاعب محترف.
  • أخيرًا تمكنت من رفع لوح واحد!
  • أنا أحد المساهمين الرئيسيين في "الشراهة على نطاق المكتب" (وربما يكون ذلك مرتبطًا باكتشافي أنني أحب Shake Shack).

مرت هذه الأشهر الأربعة أسرع مما كنت أتوقع، وأنا ممتنة للخبرة التي اكتسبتها في Slash. سأتخرج قريبًا، وبغض النظر عما يخبئه لي المستقبل بعد شهر أو سنة أو عقد من الزمن، أعلم أن التدريب في Slash منحني المعرفة والثقة اللازمتين للنجاح أينما ذهبت.

إذا كنت مهتمًا بمزيد من الدردشة، لا تتردد في التواصل معي على LinkedIn! يسعدني الرد على أي أسئلة قد تكون لديكم.

Read more from us