كلمة Reflection تعني إنعكاس، كبداية تخيلوا إن الكود يقدر يناظر نفسه، ويعرف وش الحقول اللي داخله، و يتصرف مع أي كائن بدون ما يعرف نوعه مسبقًا.
الإنعكاس مفهوم يستخدم كثير، ولو مر عليكم إطار Spring Boot فأكيد جربتوا تكتبون Annotations، وتلاحظون انه يكتب كود عنكم بدون مانشوف، حرفيا الفكرة الي وراها كلها Reflection!
الانعكاس مفيد لما نبي نسوي أشياء ديناميكية بدون ما نكتب كود مخصص لكل حالة. خل نشوف أمثلة حقيقية في كل بيئة.
بعطيكم مثالين في هذي المقالة، واحد ب Swift والثاني ب Java، الهدف اننا بنجاوب سؤالين:
تخيل عندك مودل طويل يمثل بيانات لمشروع:
struct ProjectReport {
var projectName: String
var clientName: String
var status: String
var startDate: Date
var endDate: Date
var teamMembers: Int
var progress: Double
var notes: String
var budget: Double
var isOnTrack: Bool
// Etc..
}
HStack {
Text("project name: ")
Spacer()
Text("\(report.projectName)")
}
طيب حنا قلنا ان الكود يقدر يشوف نفسة صح؟ الله لو يقدر يقرا اسم المتغير ويحطه عنوان قبل كل متغير بشكل ديناميكي ولا؟ خنشوف كيف نستخدم ال Reflection بهالحاله:
struct ReflectiveForm<T>: View {
var model: T
var body: some View {
Form {
let mirror = Mirror(reflecting: model)
ForEach(mirror.children.compactMap { $0 }, id: \.label!) { child in
if let label = child.label {
HStack {
Text(label)
Spacer()
Text("\(String(describing: child.value))")
.foregroundColor(.secondary)
}
}
}
}
}
}
واستخدامها:
struct ContentView: View {
var body: some View {
ReflectiveForm(model: ProjectReport(
projectName: "منصة ذكاء السوق",
clientName: "شركة البرمجة الذكية",
status: "قيد التنفيذ",
startDate: Date(),
endDate: Date().addingTimeInterval(86400 * 30),
teamMembers: 5,
progress: 0.65,
notes: "العمل يمشي تمام لكن نحتاج مراجعة من العميل.",
budget: 75000,
isOnTrack: true
))
}
}
بتلاحظون بالمثال اننا استخدمنا mirror.children.compactMap
وقدرنا نوصل لمعلومتين: label
و value
، وسويناها بطريقه ديناميكية.
والحين متخيلين أي مودل نقدر نعطية الـ ReflectiveForm
ويبني لنا فورم فيه كل المتغيرات! 🥳
ميزة جدا جدا رهيبة وتختصر وقت في حال كنا نتعامل مع مودلز طويله دايم.
طيب قلنا ان Spring كلها تعتمد على ال Reflection، بعطيكم مثال جدا بسيط علشان نفهم بس كيف سبرنق تعتمد عليه.
الحين تخيلوا إن عندنا مودل فاتورة، وفيه متغير total ونبي نحده على انه مايقل عن 100:
public class InvoiceRequest {
@Min(100)
public double total;
}
@RestController
@RequestMapping("/api/invoice")
public class InvoiceController {
@PostMapping
public String submit(@RequestBody @Valid InvoiceRequest request) {
return "✅ Total مستوفى الشروط: " + request.total;
}
}
وارسلنا رقم اقل من 100، بيجينا response:
{
"status": 400,
"message": "total: must be greater than or equal to 100"
}
هذا كله صار بدون مانشوف، لان لو نرجع لتعريف الـ annotation بنلاحظ ان hibernate-validator تستخدم 🔗 ReflectionHelper علشان تشغل اللوجيك هذا على اي كلاس:
public class MinValidatorForDouble extends AbstractMinValidator<Double> {
@Override
protected int compare(Double number) {
return NumberComparatorHelper.compare( number, minValue, InfinityNumberComparatorHelper.LESS_THAN );
}
}
هذا مثال بس على ال min ، بس بيساعدنا نتخيل كيف كل باقي ال annotations تشتغل في كل إطار عمل Spring !
هذا أول مقالة أكتبها بالعربي في مجال التقنية، فإذا فيه أخطاء بسيطة أو تعبير مو واضح، أتمنى تعذروني 😅 وأكيد أرحب بأي ملاحظة أو تصحيح.
شكرًا لوقتك، وإن شاء الله المقالة كانت خفيفة ومفيدة 🥳