اذهب إلى المحتوى

لوحة المتصدرين

  1. عبد النور محمد

    • نقاط

      7

    • المساهمات

      95


  2. Ali Haidar Ahmad

    Ali Haidar Ahmad

    الأعضاء


    • نقاط

      7

    • المساهمات

      1068


  3. سامح أشرف

    سامح أشرف

    الأعضاء


    • نقاط

      5

    • المساهمات

      2934


  4. Amer Abdallah

    Amer Abdallah

    الأعضاء


    • نقاط

      5

    • المساهمات

      150


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 09/09/21 في كل الموقع

  1. بفرض أن لدي قالب كالقالب التالي: <div>Hello {{name}}!</div> <p>This is your first visit, {{name}}?</p> ألن يكون من المفيد تحديد قيمة المتغير name من داخل القالب نفسه. لذلك أنا أبحث عن شيء مثل هذا: {% name = "Amer" %} <div>Hello {{name}}!</div> <p>This is your first visit, {{name}}?</p> هل يوجد شيء مثل هذا في جانغو Django يمكنني من عمل متغيرات داخل القالب نفسه؟
    3 نقاط
  2. سأقوم بنصيحتك من وجهة نظر عملية: هناك طريقتين للتعلم، من الأعلى للأسفل و العكس، أي الإبتداء من الجبر، الإحصاء و الإحتمالات و بالإضافة للخوارزميات و هيكلية البيانات، و من ثم يمكنك الإطلاع على تعلم الألة و علم البيانات. أو يمكنك الإبتداء من تعلم الألة، علم البيانات و من ثم محاولة فهم كل خوارزمية من خوارزميات تعلم الألة و طريقة عملها، و في التعامل مع البيانات، يمكن اللجوء لهيكلية البيانات، إذ أنها تعطيك الطريقة الأمثل من حيث الوقت و مساحة الذاكرة و غيرها من الخصائص التي تجعلك تختار طريقة عن غيرها. في كل الأحوال هناك عدد من الأشياء يمكنك أخذها بعين الإعتبار لتحديد الطريقة المناسبة لك: إن كنت تركز على إنشاء تطبيقات صغيرة فقط للتعلم يمكنك التعامل مباشرة مع الدوال الجاهزة في علم البيانات وهي التي تقوم بكل المهمات الصعبة مثل تحويل البيانات إلى مستوى أعلى kernel move the data to higher dimension. بالطريقة السابقة يمكنك إنشاء تطبيقات مختلفة مثل التعرف على الصور و توقع القيم المستقبلية لأسعار الأسهم، تقسيم العملاء إلى فئات و غيرها. الشركات المتوسطة و الصغيرة يركزون على إنتاج تطبيقات أكثر من جودتها بالتالي الطريقة السابقة تنفع في هذه الحالة (بالضرورة لا أعني التعميم فقد يوجد بعض الجهات التي تركز على جودة البرامج المقدمة). الشركات الكبيرة تركز على منهجية و طريقة الحل، و تبحث على حلول مستدامة و بالتالي يهمها تقليل التكلفة الناتجة من زمن التنفيذ و المساحة التخزينية، بالأخص في حالة التعامل مع البيانات الضخمة. في حال أردت التعلم للمواصلة في المجال الأكاديمي أنصحك بالبدء من الأساسيات ثم المواصلة، لأنك في هذه الحالة تحاول إيجاد افضل الحلول و ليس أي حل يعمل. في حال كنت تريد عمل تطبيقات متوازنة أو موزعة أنصحك بالبدء بالأساسيات لانها ستساعدك في حال التوسع او إنشاء تطبيقات على خدمات سحابية. في كل الأحوال الخيار يعتمد على ماذا تريد و الطريقة الأنسب لتعملك أنت شخصياً، كل شخص سيعطي الإجابة من وجهة نظره، لا توجد إجابة صحيحة أو خطأ أو إجابة مثالية، هي فقط عرض للخبرات و أنت من يحدد ما الذي سيفيدك. أتمنى أن تكون قد أستفدت.
    3 نقاط
  3. لدي العديد من البيانات على شكل dataframe، واريد أن أجد طريقة أقوم بعمل إضافة لهم append مرة واحدة عوضاً عن عمل append لكل واحدة مفردها: df.append(df) لنفرض أن لدي dataframes أسماؤهم d1,d2,d3,d4,d5 جربت الطريقة التالية لاضافتهم مرة واحدة لكن لم تفلح: df = rbind(d1,d2,d3,d4,d5) كيف يمكنني فعل هذا؟
    2 نقاط
  4. لدي بيانات على الشكل التالي: time result 1 01:00 +52A 2 02:00 +62B 3 03:00 +72C 4 04:00 -82D 5 05:00 -92E وأريد أن أجعلها تظهر على الشكل التالي: time result 1 01:00 52 2 02:00 62 3 03:00 72 4 04:00 82 5 05:00 92 حاولت استخدام الدالة .str.lstrip('+-') لكن يظهر لي الخطأ التالي: TypeError: wrapper() takes exactly 1 argument (2 given) كيف يمكنني عمل هذا؟
    2 نقاط
  5. لدي مشروع في material-ui و nextjs و أحاول جعل شريط التنقل الخاص بي يعمل مع nextjs: import * as React from 'react'; import AppBar from '@material-ui/core/AppBar'; import Link from "next/link"; import {Tab, Tabs} from "@material-ui/core"; export default function NavBar() { return ( <AppBar position="static"> <Tabs> <Tab label="Timer"><Link href="timer" /> </Tab> <Tab label="Home" to="/" component={Link} /> </Tabs> </AppBar> ); } لكن عملية بناء المشروع تفشل ؟
    2 نقاط
  6. لدي مشروع هيكلته كالاتي assets node_modules src package.json package-lock.json webpack.config.js وهذا اعدادات webpack const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const webpack = require('webpack'); module.exports = { entry: { app: './src/index.js' }, devServer: { // contentBase: './dist', contentBase: __dirname + "/assets/", hot: true, }, plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ title: 'Output Management' }), new webpack.NamedModulesPlugin(), new webpack.HotModuleReplacementPlugin() ], output: { path: __dirname + "/assets/", filename: 'bundle.js', chunkFilename: '[name].js' }, }; ولدي هذا الخطا داخل أدوات المطور Content not from webpack is served from C:\Users\PC-user\WebstormProjects\untitled/assets/
    2 نقاط
  7. لدي مشروع مكتمل والأن أريد التحويل من بيئة التطوير لبيئة ال production ليصبح الموقع اسرع كيف يمكنني ذلك const webpack = require('webpack'); const config = { entry: ['babel-polyfill', './src/index.js'], output: { filename: 'bundle.js', }, devServer: { inline: true, port: 8080, historyApiFallback: true, }, plugins: [ new webpack.DefinePlugin({ 'process.env': { API_KEY: 'API_KEY', GOOGLE_MAPS_KEY: 'GOOGLE_MAPS_KEY', GOOGLE_GEOLOCATION_KEY: 'GOOGLE_GEOLOCATION_KEY', }, }), ], module: { loaders: [ { test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel-loader', query: { presets: ['es2015', 'react'], }, }, { test: /\.css$/, loader: 'style!css', }, ], }, }; module.exports = config;
    2 نقاط
  8. لدي هذا الكود وعندما أحاول كتابة شئ في الinput تأتينى تلك الرسالةA component is changing an uncontrolled input of type text to be controlled error in ReactJS const Form=()=>{ const [form,setForm]=useState({}) return( <> <input value={form.name} name="name" onChange={(e)=>setForm({...form,name:e.target.value})} /> </> ) }
    2 نقاط
  9. ابغا احد يشرح لي scientific notation او مرجع دورت شي وضح ماحصلت ومافهمت
    2 نقاط
  10. سنواصل في هذا المقال استعراض ما تبقّى من مُكوّنات المُخطّط 4- العلاقة مع الزبائن Customer Relationshipفي السابق كانت الشركات تركّز بشكل كبير على المنتجات وتنظر للزبائن على أنّهم إجمالي الطلب أو أرقام المبيعات بدون أيّة مراعاة للعنصر الإنسانيّ لديهم. أما اليوم ومع اشتداد حدّة المنافسة في الصناعات بدأت الشركات تميّز نفسها بإعطاء العامل الإنسانيّ البشريّ في الزبائن أهمية قصوى. وهنا بدأت تظهر عدّة أشكال للعلاقات مع الزبائن لخدمتهم: 1- العلاقة الشخصيّةوهنا تقوم الشركة بالتواصل بشكل شخصيٍّ سواء وجهًا لوجه أم عبر وسائل الاتصال مع كلّ زبون، هذا النوع من العلاقات يبرز في الخدمات بشكل كالمصارف حيث يكون موظف خدمة العملاء متواجدًا ليقدّم مساعدة شخصية لكل زبون بناءً على طلبه. 2- الخدمة الذاتيّةحيث لا تقدّم الشركة أيّ موظفين لمساعدة الزبائن، بل تقدّم لهم الأدوات اللازمة لخدمة نفسهم بنفسهم. 3- الخدمة الآليّةتحلُّ الآلات والأنظمة محلَّ الموظف الشخصيّ لمساعدة العملاء وبناء العلاقة معهم، مثل الصرّاف الآليّ حيث يمثّل المصرف ويتعامل مع خدمات مؤتمتة بدون أن يعطي اهتمامًا خاصًا لعميل دون آخر. 4- مجتمعتنشئ الشركة مثل منتدى يساعد به العملاء بعضهم البعض من حيث حلّ المشاكل أو الردّ على الاستفسارات. 5- المحتوى المساعدحيث العملاء ينشرون محتوى يساعد العملاء الآخرين في اتخاذ القرار مثل تقييمات أو تعليقات على منتج معين وإبراز إيجابياته وعيوبه. 6- الشبكات الاجتماعيةلم يعد بالإمكان تجاهلها وعدم التواجد على الشبكات الاجتماعية لبناء العلاقة مع العملاء، تحرص الشركات على التواجد بكثافة أكبر على الشبكات التي يتواجد بها شرائح عملائها. ليس الغرض هنا التسويق أو البيع بل بناء العلاقة الدائمة. تمرُّ العلاقة ما بين الزبون والشركة في ثلاثة مراحل أساسية: أولًا تعمل الشركة على جذب العملاء الجدد وهنا تستخدم استراتيجيات العلاقات الخاصة بجذب أكبر عدد ممكن من العملاء. ثانيًا الحفاظ على الزبائن الحاليين وأخيرًا زيادة المبيعات من خلال الزبائن الحاليين. فمثلًا عندما تبدأ شركة اتصالات العمل في بلد ما فإنها تنتهج استراتيجية علاقات توسعيّة في مختلف القطاعات وتقديم شرائح خدمات تلبّي احتياجاتها من أجل جذب أكبر عدد ممكن من العملاء الجدد. وبعد مرور عدّة سنوات لم يعد بالإمكان جذب المزيد وتشتدّ حدّة المنافسة مع شركات اتصالات أخرى فتبدأ العلاقة تأخذ منحى الحفاظ قدر الإمكان على العملاء الحاليين من الانتقال للشركات المنافسة وأخيرًا تعمل الشركة على تقديم عروض من شأنها أن تجعل الزبائن الحاليين أن يقنعوا زبائن في شركات منافسة التحوّل لمنتجاتهم وهنا يحدث النمو في المبيعات. 5- مصادر الإيرادات Revenue Streamالطريقة التقليدية التي تحقّق فيها الشركات الإيرادات كانت عن طريق بيع المنتج أو الخدمة بمقابل مادي محدد هو السعر. لكن اليوم أصبحت هناك عدة طرق جديدة لتحقيق الإيرادات خاصة بشكل غير مباشر وإن تطلّب الأمر تقديم المنتج بالكامل مجانًا. في قسم مصادر الإيرادات نضع الطرق المستخدمة في تحقيق الإيرادات من مخطط نموذج العمل التجاري. وقد نعتمد طريقة واحدة أو عدّة طرق بحيث تكون كل نوع من شرائح العملاء نستهدفها بطريقة مختلفة لتحقيق مصادر الإيرادات. ومن الأمثلة عن الطرق الأخرى لتحقيق الإيرادات غير البيع: 1- Freemiumوهنا يتمُّ تقديم الحد الأدنى من العرض المقدّم أو القيمة المقترحة بشكل مجاني تمامًا لشريحة العملاء، وعند طلب قيمة إضافية يتمُّ فرض مبلغ مالي معين. مثل خدمات التخزين السحابي التي تعطيك مساحة تخزينيّة محدّدة مجانًا، وإن أردت المزيد مع مزايا أكثر عليك دفع مبلغ مالي محدد سنويًا. 2- رسوم الاستخدامهنا يدفع العميل عند كل استخدام للمنتج أو الخدمة، مثلًا خدمات شركات الاتصالات فعند إجراء كل اتصال أو إرسال رسالة عليك دفع مبلغ مالي معين. 3- رسوم الاشتراكهنا يدفع العميل مبلغ مالي ثابت خلال فترة من الزمن لقاء التمتّع بحقِّ استخدام الخدمة أو المنتج طوال فترة زمنية معيّنة. مثل النوادي الرياضية حيث يفرض عليك دفع مبلغ شهري بغضِّ النظر عن عدد الجلسات الرياضية. 4- رسوم الترخيصبعض المنتجات لا تبيعك الشركة كامل المنتج إنّما رخصة استخدامه، وهنا تدفع مرة واحدة على عكس رسوم الاستخدام، مثل نظام التشغيل ويندوز فأنت تدفع لقاء الاستخدام و لا تملك كامل المنتج. 5- التأجيربعض المنتجات تلزم العملاء فترة محدودة من الزمن لذا لا جدوى من شرائها بالكامل، هنا تقوم الشركة بتأجيرها لهم لقاء مبلغ مالي معيّن خلال الفترة وبعد الانتهاء يعود المنتج إلى ملكية الشركة. مثل مكتبة تستأجر آلة تصوير مستندات خلال فترة العام الدراسي. 6- الشراء ضمن التطبيقاتحيث تقدّم الشركة التطبيق أو اللعبة مجانًا بالكامل ولكن تكون هناك عناصر مدفوعة ضمنها، قد تكون ملزمة أو اختيارية الشراء وبهذا تشبه نوعًا ما Freemium إلا أنك عند الدفع لن تحصل على قيمة جديدة أعلى. 7- الإعلاناتوهي الطريقة الأكثر انتشارًا اليوم حيث تقدّم التطبيق أو اللعبة أو أي منتج آخر بنسختين، الأولى تكون مجانية بالكامل ويعتمد على بيع الإعلانات بداخلها لتحقيق الدخل، والثانية تكون مدفوعة وهي الطريقة التقليدية حيث مبادلة منتج بسعر. 6- الموارد الأساسيّة Key Resourcesكل مشروع تجاري يحتاج لموارد أساسيّة حتى يقوم، وهذه الموارد تختلف في تصنيفها بحسب طبيعتها. في هذا القسم من مخطط نموذج العمل التجاري نضع فقط أهم الموارد الأساسيّة اللازمة لإنجاح نموذج العمل، أي لا نضع الموارد الثانويّة بل فقط الأساسيّة والتي بدونها لا يمكن إطلاق المشروع وتقديم العرض المقدّم. يمكن تصنيف هذه الموارد بحسب طبيعتها، هناك الموارد البشريّة كالعمال والمهندسين أو الخبراء الأساسيين، والموارد الماديّة أي الفيزيائيّة كالآلات وخطوط الإنتاج والمواد الأوليّة وكلّ شيء ملموس وضروري للإنتاج، والموارد المعنويّة مثل براءات الاختراع التي تعدّ أساسية في المنتج وكذلك التراخيص اللازمة وحتى العلامات التجارية وغيرها، والموارد الماليّة خاصة إذا كان المشروع يشكّل المال قسما هاما من خدماته كالمصارف. ولا مشكلة إن كانت هذه الموارد مملوكة للمشروع أو مستأجرة، بكل الأحوال يجب وضعها في مخطط نموذج العمل. 7-الأنشطة الأساسيّة Key Activitiesإن عملية خلق القيمة أو العرض المقدّم هي نتيجة تدوير وتشغيل الموارد الأساسيّة من خلال تنفيذ أنشطة أساسية عليها. أي لو كان لديك كشك يبيع عصير الليمون فإن عملية عصر الليمون أي إنتاج المنتج هي واحدة من أهم الأنشطة الأساسية للحصول على العرض المقدّم الذي يتمّ بيعه. بشكل رئيسي هناك ثلاثة أنواع من الأنشطة الرئيسيّة الأساسيّة التي يتم تطبيقها في الأعمال: 1- الإنتاجالإنتاج وكل الأنشطة الفرعيّة التي تتعلّق به وحتى التسويق والمبيعات. 2- حلّ المشاكلوهذه في الخدمات حيث لا تنتج الخدمة بل ستكون عندما تحلّ مشاكل الآخرين كالمحاسبين والمحامين 3- المنصّاتحيث تقتصر وظيفتك الأساسيّة على التوصيل بين طرفين أو أكثر وتمارس أنشطتك الدوريّة المتعلّقة بهذه المنصّة من تطوير وتحسين. من المهم أن ننتبه إلى ذكر الأنشطة الأساسيّة هنا كما سنذكر الموارد الأساسيّة في المكوّن السابق, حيث أنّ بعض الأنشطة يفترض أنها تتواجد في كافة الشركات كالتسويق إلا أنه ثبت بالفعل وجود عدد كبير من الشركات وبخاصة الناشئة ولا تمارس أي جهد تسويقي حتى لا يوجد لديها قسم تسويق في الشركة، لذا لا نذكر النشاط التسويقي هنا لأنه ليس أساسيا ويعمل مخطط النموذج ويتمّ تقديم العرض المقدّم بدونه. 8- هيكل التكاليف Cost Structureبشكل عام تقسّم تكاليف أيّ مشروع إلى نوعين، ثابتة ومتغيرة، الثابتة هي التكاليف التي لا تزيد بازدياد الإنتاج مثل تكلفة شراء العقار أو تكلفة خطوط الإنتاج من آلات، أما المتغيّرة هي التي تتغيّر بتغيّر حجم الإنتاج مثل المواد الأولية الداخلة في عملية الإنتاج. وهنا تضع الشركة كافة التكاليف التي تحتاجها الأنشطة الرئيسة في العمليات المطبّقة على الموارد الأساسية من أجل الحصول على العرض المقدّم. وعادة ما ترتبط التكاليف بالأنشطة لأنّ لكلّ نشاط تكلفة لازمة للقيام بالنشاط على أكمل وجه. ومن الأمثلة على أهمية مخطط نموذج العمل في تجنيب الشركات دفع تكاليف لا حاجة لها، شركة ناشئة كانت لديها خدمة تقوم بإجراء مسح على الأراضي الزراعية ومن خلال مقارنات الصور وعدّة خوارزميات يمكنها التنبؤ بأمراض معيّنة قد تصيب المحصول بالتالي هذا التنبؤ يساعد على تجنّب وقوع الكارثة. ومن أجل تنفيذ هذه الخدمة كان يتطلّب الحصول على طائرات زراعيّة يتمّ تركيب كاميرات مخصصة عالية السرعة عليها من أجل التقاط الصور من السماء وهو ما يعني ضرورة شراء طائرة أو أكثر وهي تكاليف ثابتة عالية يجب وضعها في هيكل التكاليف. وأثناء عملية إعداد مخطط نموذج العمل التجاري توجهوا إلى شرائح العملاء وهم المزارعون أصحاب الأراضي التي قد تصيبها الأمراض وبالفعل كانت لديهم حاجة لمثل هذه المعلومات التنبؤية بغض النظر عن طريقة الحصول عليها، وهنا قدّموا معلومة هامة وهي أنّه بدلًا من شراء طائرة يمكن الاعتماد على طائرات شركات رشّ المبيدات الحشرية واستئجارها منهم بالتالي لا داعي لتكبّد كلّ تلك التكاليف الثابتة العالية. 9- الشركاء الأساسيون Key Partnersلأنّ أيّ مشروع تجاري يتواجد في سوق وبيئة مفتوحة فإنه يحتّم عليه التواصل مع أطراف تساعده أو تكون ضرورية لوجوده. يجب أن نميّز أنّ الشركاء الذين يتمّ التعاون معهم في بدايات حياة الشركة يختلفون عن الشركاء في مراحل متقدمة من حياتها. ومن الشركاء الضروريين جميع الهيئات الحكومية أو الدولية التي يفترض الحصول على ترخيص منها أو التواصل المستمر للبقاء تحت رقابتها، مثل رخصة من وزارة التربية لإنشاء مدرسة خاصة أو وزارة الصحة لإطلاق منتج دوائي معين. وأبسط أشكال الشراكات التعاقد مع موردين أو إدارة سلسلة التوريد خاصة في مجال الإنتاج حيث أنّ الشركة تعمل على الإنتاج وتعتمد على موردين خارجيين لتوريد المواد الأولية ، وكذلك على موزعين لتصريف الإنتاج وبيعه في حالة عدم الرغبة بالاعتماد على نفسها وفتح منافذ البيع الخاصة بها. في حين أنّ الأمور تتعاقد أكثر مستقبلًا للدخول في تحالفات استراتيجية مع شركات غير منافسة كما فعلت مايكروسوفت مع نوكيا و سوني مع إيركسون، أو الشراكات الاستراتيجية مع المنافسين كما بين آبل و سامسونج حيث أنّها أكبر من مجرد علاقة مورد و مشترٍ، أو المشاريع المشتركة كما بين نوكيا وسيمنس. في المقال القادم سنستعرض نموذجًا عمليّا عن المُخطّط.
    1 نقطة
  11. غالبًا ما أجد نفسي أرغب في الحصول على الكائن الأول من queryset في جانغو Django، أو إعادة None إذا لم يكن هناك أي كائن. هناك العديد من الطرق للقيام بذلك والتي تعمل جميعها. لكني أتساءل أيهما صاحب أفضل أداءً. users = User.objects.filter(role = 'admin') if users.count() > 0: return users[0] else: return None هل ينتج عن هذا استدعائين لقاعدة البيانات؟ هذا يبدو مضيعة للوقت مقارنة بالكود التالي (أعتقد أنه أسرع)؟ users = User.objects.filter(role = 'admin') if len(users) > 0: return users[0] else: return None الخيار الآخر هو إستخدام جملة Try ... Except: users = User.objects.filter(role = 'admin') try: return users[0] except IndexError: return None هذا يولد استدعاء قاعدة بيانات واحدة ، وهو أمر جيد. ولكن يتطلب إنشاء كائن استثناء (من الصنف IndexError) في كثير من الأحيان، وهو أمر يتطلب الكثير من الذاكرة، خصوصًا مع عدد كبير من الزيارات المتزامنة. كيف يمكنني القيام بذلك من خلال استدعاء قاعدة بيانات واحد فقط وأسرع طريقة ممكنة؟
    1 نقطة
  12. يمكنك أيضاً استخدام مفهوم ال array slicing: Entry.objects.all()[:1].get() والتي من الممكن استخادمها مع filter: Entry.objects.filter()[:1].get() من الضروري أن تضع get لكي تحصل على object، وإلا ستحصل على QuerySet.
    1 نقطة
  13. لاحظ أن في جميع الطريق السابقة، يتم جلب كل الكائنات التي لديها الخاصية role بقيمة admin، بينما يتم إستخدام فقط الأول كائن، ولا حاجة لطلب كل الكائنات الأخرى من قاعدة البيانات، لذلك يوفر Django التابع first والذي يقوم بجلب أول كائن فقط من قاعدة البيانات، وفي حالة لم يستطع العثور على أي منها سوف يقوم بإرجاع None، وهو ما ترغب به بالضبط. يتم إستخدام التابع first على النحو التالي: users = User.objects.filter(role = 'admin').first() كما يوفر Django التابع last والذي يقوم بنفس وظيفة التابع first بإستثناء أنه يعيد آخر كائن من قاعدة البيانات وليس الأول. users = User.objects.filter(role = 'admin').last() كما يمكنك جلب كل الكائنات من قاعدة البيانات (في حالة كنت بحاجة إليها في وقت لاحق)، وفي نفس الوقت تستطيع إستخدام التابع first بالشكل التالي: users = User.objects.filter(role = 'admin').all() firstUser = users.first() بهذه الطريقة سيكون لديك كل كائنات النموذج User وفي نفس الوقت تستطيع الحصول على أول كائن منهم بدون عمل إستعلام جديد في قاعدة البيانات، وفي حالة لم يتم العثور على أي كائنات سوف يتم إعادة None.
    1 نقطة
  14. يجب أن يحتوي التطبيق على مجلد Templatetags على نفس المستوى مثل Models.py و views.py .. إلخ. وإذا لم يكن هذا موجود فعليَاً، قم بإنشائه ولا تنس ملف __init__.py لضمان معاملة المجلد على أنه حزمة بايثون. أولاً قم بإنشاء ملف باسم event.py داخل المجلد Templatetags مع الكود التالي(بعد إضافة وحدة Templatetags، ستحتاج إلى إعادة تشغيل الخادم قبل أن تتمكن من استخدام ال tags أو filters في القوالب) : from django import template as tem reg = tem.Library() @reg.simple_tag def define(val=None): return val ثم في القالب الخاص بك يمكنك تعيين قيم إلى ال context كالتالي: {% load event %} {% if item %} {% define "Edit" as action %} {% else %} {% define "Create" as action %} {% endif %} Would you like to {{action}} this item?
    1 نقطة
  15. يوفر Django طريقة لعمل متغيرات محلية local variables داخل القالب نفسه بشكل إفتراضي من خلال كلمة with على النحو التالي: {% with name="World" %} <div>Hello {{name}}!</div> <p>This is your first visit, {{name}}?</p> {% endwith %} لاحظ أن المتغير سوف يعمل داخل نطاق العنصر with فقط، لذلك إن كنت في حاجة لمتغير يعمل في كل القالب فسوف تحتاج إلى إحاطة القالب بالعنصر with بالكامل. وإن كنت تستخدم قوالب jinja، فيمكنك عمل نفس الشيء من خلال الكود التالي: {% set name="Amer" %} <div>Hello {{name}}!</div> <p>This is your first visit, {{name}}?</p>
    1 نقطة
  16. يمكنك استخدام with كالتالي {% with name="World" %} <html> <div>Hello {{name}}!</div> </html> {% endwith %}
    1 نقطة
  17. هذا هو الموديل الخاص بي import mongoose from 'mongoose' const flashcardItemSchema = new mongoose.Schema({ term: { type:String, required: true, min:1 }, description: { type:String, required:true, min:1 } }); const FlashcardItem = mongoose.model("flashcardItem", flashcardItemSchema); const flashcardSetSchema = new mongoose.Schema({ title: { type: String, min: 1, }, flashcards:[flashcardItemSchema], }) const FlashcardSet = mongoose.model('flashcardSet', flashcardSetSchema ) export {FlashcardItem, FlashcardSet} عند تشغيل المشروع أحصل على cannot overwrite "mongoose" model once compiled
    1 نقطة
  18. شكرا لك على هذه النصيحة, المشكلة حقا توجد في المتصفح لقد قمت بتجربة الـ responsive بالطريقة التي ذكرتها و لاحظت أن الأمر يعمل, شكرا جزيلا مرة أخرى شكرا جزيلا لك أيضا, المشكلة موجودة في المتصفح ليس الكود قمت بتجربة ال responsive بطريقة أخرى في المتصفح و عمل معي الأمر
    1 نقطة
  19. ما الفرق في الداتابيز بين استخدام الnumeric واستخدام الfloat وشكراً
    1 نقطة
  20. الfloat معرفة حسب معايير IEEE-754 والتي تنص علي أن يتم حجز عدد من الbits من أجل الرقم وعدد من الbits من أجل الأس , حيث يتم كتابة الرقم علي الصورة الأتية 10.25=1025e-2 حيث e-2 تعني 10 مرفوعة للقوة سالب 2 بينما في الnumeric أو التي تسمى Fixed-point Decimals (النقطة الثابتة العشرية) يتم حجز عدد الbits المستخدمة في كلاً من الرقم قبل العﻻمة العشرية والرقم بعد العﻻمة العشرية من قبل تعيين قيمتهم حسناً, ما الفرق إذاً؟ الfloat أسرع في حسابه ولكن دقته أقل, وبالمناسبة هذ نفس النوع الذي يتم إستخدامه في الc/c++ المكاتب القياسية, فيمكنك تجربة الكود الأتي float x = 0.1; float y = 0.2; printf("x+y = %.20f\n", x+y); printf("0.3 = %.20f\n", 0.3); وعند النظر إلى الناتج نجد أ،: الناتج المتوقع: x+y = 0.300000 0.3 = 0.300000 بينما الناتج الحقيقي: x+y = 0.30000001192092895508 0.3 = 0.29999999999999998890 بينما في الnumeric تكون دقته عالية ولكن يكون أبطأ في حسابه من الfloat وبوجه عام فإن الfloat دقته تكون كافية ومرضية إلا في حالة أن تكون تتعامل مع بيانات حساسة مثل الحسابات العلمية أو حسابات البنوك
    1 نقطة
  21. الفكره في صوره كبيره و ازرار كل زر له صوره محدده و عند الضغط تضهر في الصوره الكبيره صوره كبيره 1 و 10 صور صغيره عند الضغط تضهر في الصوره الكبيره
    1 نقطة
  22. كيف اخلي صوره ثابته و في زرbuntton كل زر صوره و عند الضغط علي button1 صوره1/ button2 صوره 2/وbutton 3 صوره 3
    1 نقطة
  23. يمكن استخدام Default Values كخاصية للعنصر input وهي مسؤولة عن عملية التهيئة الأولى وتتجنب حدوث خطأ <input defaultValue="Bob" value={form.name} name="name" onChange={(e)=>setForm({...form,name:e.target.value})} /> وإن أردت وضع قيمة افتراضية ضمن value يمكن استخدام المعامل ؟؟ nullish coalescing بدل or || value={name ?? ''} checked={bool ?? false}
    1 نقطة
  24. انا صرت سنة ثانية الحمد لله بس في صعوبة شوي بعتبار اغلب الامر دنا نتعلمها لحالنا. واما بالنسبة للتعلم طبعا الجافا: C# و ولكن الاساسيات فقط
    1 نقطة
  25. لدي كود بهذا الشكل const numbers = values .map((val, index) => { return (index + 1); }) .toString(); ولدي اعدادات ل prettier بملف اسمه .prettierrc ويحتوي على { "trailingComma": "es5", "tabWidth": 2, "useTabs": false, "singleQuote": true, "printWidth": 1200, "bracketSpacing": true, "jsxBracketSameLine": true } والمطلوب هو جعل الكود بهذا الشكل const numbers = values.map((val, index) => {return (index + 1);}).toString();
    1 نقطة
  26. هل يوجد خيار اخر غير Prettier مناسب لهذا الاحتياج ؟
    1 نقطة
  27. عندما أقوم بعرض صفحة باستخدام عارض قوالب جانغو Django ، يمكنني تمرير متغير قاموس Dictionary يحتوي على قيم مختلفة لمعالجتها في الصفحة باستخدام الطريقة التالية: {{ myDict }} هل هناك طريقة للوصول إلى نفس المتغير في JavaScript (ربما باستخدام DOM ، لا أعرف كيف يجعل جانغو Django المتغيرات قابلة للوصول)؟ أريد أن أكون قادرًا على البحث عن التفاصيل باستخدام بحث AJAX استنادًا إلى القيم الموجودة في المتغيرات التي تم تمريرها إلى JavaScript من خلال جانغو Django.
    1 نقطة
  28. لدي هذا الكود app.post("/user",(req,res)=>{ if(req.body.user.email==undefined) res.status(404).send("err") user=new User(req.body.user) user.save() .then(()=>res.json("user created")) }) ولكن عند التشغيل يأتيني هذا الخطأ [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    1 نقطة
  29. يمكن الحصول على تنسيق كالمطلوب بتغيير بسيط بالشيفرة بدون اي تغيير بالاعدادات عبر حذف الكلمة return من التابع وحذف الأقواس { } مع حذف الفاصلة المنقوطة ثم تنفيذ أمر تنسيق prettier const numbers = values .map((val, index) => (index + 1) ) .toString(); // بعد تنفيذ أمر التنسيق const numbers = values.map((val, index) => index + 1).toString();
    1 نقطة
  30. ليكن لدينا المثال التالي: df """ col1 col2 col3 col4 b ali 33 Up wq c ali 23 we qw a dac 23 we we e gsg 12 we ew f cds 66 ew ds g sdac 95 sdac dc i cd 55 adsc r j das 35 cda r k ads 12 cd vc d ad 88 cda Bhgu """ 1. فرز صفوف داتافريم بناءً على عمود معين: df.sort_values(by = 'col1') """ col1 col2 col3 col4 d ad 88 cda Bhgu k ads 12 cd vc b ali 33 Up wq c ali 23 we qw i cd 55 adsc r f cds 66 ew ds a dac 23 we we j das 35 cda r e gsg 12 we ew g sdac 95 sdac dc """ 2. اعتماداً على عدة أعمدة: df.sort_values(by = ['Name', 'Age']) 3. فرز الصفوف بناءً على عمود معين وترتيب تنازلي: df.sort_values(by = 'col', ascending = False) 4. لجعل عملية الفرز تتم على البيانات الأصلية نستخدم inplace: df.sort_values(by = 'Name', inplace = True) ليكن لدينا مثال آخر: Arabic Math Science English Ankit 75 50 60 70 Rahul 75 55 65 75 Aishwarya 75 35 45 25 Shivangi 75 90 60 70 Priya 76 90 70 60 Swapnil 90 80 70 60 Shaurya 65 10 30 20 1. فرز الأعمدة بناءً على سطر محدد: df.sort_values(by = 'Priya', axis = 1) """ English Science Arabic Math Ankit 70 60 75 50 Rahul 75 65 75 55 Aishwarya 25 45 75 35 Shivangi 70 60 75 90 Priya 60 70 76 90 Swapnil 60 70 90 80 Shaurya 20 30 65 10 """ وأخيراً يمكنك اختيار خوارزمية البحث التي تريدها من خلال الوسيط kind وهذه هي الخيارات المتوفرة: {‘quicksort’, ‘mergesort’, ‘heapsort’, ‘stable’}, default ‘quicksort’ لاستخدامها: DataFrame.sort_values(... ... kind='quicksort' .. . . ) ,ولتطبيق عملية ما قبل أن يطبق الفرز يمكن استخدام الوسيط key وتمرير الدالة المناسبة له.
    1 نقطة
  31. لحل مشكلة process is not defined يمكن أن نضيف plugin التالية: plugins: [ new webpack.ProvidePlugin({ process: 'process/browser', }), ] ونقوم بتثبيتها كالتالي: npm install process كما يمكن استعمال الplugin التالية webpack.DefinePlugin بدل من webpack.EnvironmentPlugin : webpack.config.js module.exports = { plugins: [ new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), 'process.env.MY_ENV': JSON.stringify(process.env.MY_ENV), ... and so on ... }) ], } وتأكد من تضمين حزمة dotenv const dotenv = require('dotenv').config({ path: __dirname + '/.env' }) في أول ملف webpack.config.js لتثبيتها: npm i dotenv
    1 نقطة
  32. يمكنك تمرير المكون من MaterialUI كإبن للمكون Link import Link from 'next/link' import { Link as StyledLink } from '@material-ui/core'; // .. return ( <Link href="/" passHref> <StyledLink>Home</StyledLink> </Link> ) لاحظ تمرير الخاصية passHref وهي تجعل المكون يمرر الرابط للمكون الإبن
    1 نقطة
  33. إذا كان الخطأ يظهر عند محاولة تثبيت حزمة MySQL-python من خلال الأمر التالي: pip install MySQL-python فيمكنك تثبيتها بطرق أخرى، مثل إستخدام easy_install على النحو التالي: easy_install MySQL-python في حالة كان الخطأ الذي يظهر لديك بعد تثبيتها هو من نوع EnvironmentError كالتالي: EnvironmentError: mysql_config not found فسوف تحتاج إلىى تثبيت بعض البرمجيات الإضافية على النحو التالي: sudo apt-get install python-mysqldb libmysqlclient-dev python-dev
    1 نقطة
  34. من خلال resample يمكننا القيام بماتطلبه: import pandas as pd df = pd.DataFrame({ 'date': pd.to_datetime( ['2016-11-15','2016-11-16','2016-11-18']), 'values':['a','b','c']}) df """ date values 0 2016-11-15 a 1 2016-11-16 b 2 2016-11-18 c """ #resample استخدام df.set_index(df.date, inplace=True) df.resample('D').sum().fillna(0) """ values date 2016-11-15 a 2016-11-16 b 2016-11-17 0 2016-11-18 c """ ولتسهيل العملية يمكنك استخدام التابع التالي. حيث نمرر له ال dataframe والعمود الخاص بالتاريخ والطريقة التي نريد فرز العمود على أساسها والقيمة المراد وضعها للتواريخ المفقودة وهي تعتمد على دالة ال reindex التي سبق ذكرها في الإجابات السابقة: def fill_in_missing_dates(df, date_col_name = 'date',date_order = 'asc', fill_value = 0, days_back = 30): df.set_index(date_col_name,drop=True,inplace=True) df.index = pd.DatetimeIndex(df.index) d = datetime.now().date() d2 = d - timedelta(days = days_back) idx = pd.date_range(d2, d, freq = "D") df = df.reindex(idx,fill_value=fill_value) df[date_col_name] = pd.DatetimeIndex(df.index) return df
    1 نقطة
  35. يمكنك أن تقوم بذلك من خلال regular expressions كالتالي: import re def makeSlug(myString): # قم بإزالة جميع الأحرف بخلاف الكلمات (كل شيء باستثناء الأرقام والحروف) myString = re.sub(r"[^\w\s]", '', myString) # استبدل كل المسافات البيضاء بشرطة سفلية underscore myString = re.sub(r"\s+", '_', myString) return s print(makeSlug("How can this be achieved")) # Output: How_can_this_be_achieved الطريقة السابقة تقوم بإزالة كل الحروف والرموز (ماعدا الأرقام والحروف اللاتينية) وتستبدل كل المسافات بعلامة شرطة سفلية underscore _ كما أن Django يحتوي على دالة slugify بالفعل التي تقوم بعمل عنوان slug من خلال أي نص، على النحو التالي: from django.template.defaultfilters import slugify slugify("How can this be achieved") # How-can-this-be-achieved كما يفضل أن تستخدم الشرطات dashes - لأنه، لفترة طويلة، تعاملت محركات البحث مع الشرطات كفواصل للكلمات، وبذلك تحصل على نتيجة أفضل في عمليات البحث عن كلمات متعددة long keywords.
    1 نقطة
  36. سؤالك له علاقة بالتصميم أكثر من ايجاد حل برمجي للمشكلة، عند قص الصورة بشكل دائري فإن أي عناصر خارج اطار الدائرة (اللون الرمادي) سوف تختفي، يجب اختيار صور عناصرها البصرية الأساسية تقع ضمن حدود الدائرة، كما لو أنك تعين صورة لملفك الشخصي على أي منصة تواصل فستواجه نفس المشكلة
    1 نقطة
  37. الحل الأسرع هو استخدام .asfreq (). لأنه لا يتطلب إنشاء فهرس جديد لاستدعاءه داخل .reindex (). # "broken" (staggered) dates dates = pd.Index([pd.Timestamp('2012-05-01'), pd.Timestamp('2012-05-04'), pd.Timestamp('2012-05-06')]) s = pd.Series([1, 2, 3], dates) print(s.asfreq('D')) 2012-05-01 1.0 2012-05-02 NaN 2012-05-03 NaN 2012-05-04 2.0 2012-05-05 NaN 2012-05-06 3.0 Freq: D, dtype: float64
    1 نقطة
  38. يمكنك استخدام Series.reindex لضمان عدم تجاهل التواريخ التى عدد الأحداث بها 0 حيث أن groupby تقوم فقط بالاحتفاظ بالقيم التى عددها 1 أو أكثر ، أنظر الكود التالي: import pandas as pd idx = pd.date_range('09-01-2021', '09-30-2021') s = pd.Series({'09-02-2021': 2, '09-03-2021': 10, '09-06-2021': 5, '09-07-2021': 1}) s.index = pd.DatetimeIndex(s.index) s = s.reindex(idx, fill_value=0) print(s) وتكون النتيجة كالتالي: 2021-09-01 0 2021-09-02 2 2021-09-03 10 2021-09-04 0 2021-09-05 0 2021-09-06 5 ... لاحظ أن القيم التى = 0 لم يتم إلغاؤها.
    1 نقطة
  39. تابع معي: import numpy as np import pandas as pd np.random.seed(0) # بدايةً نقوم بتعريف الداتافريم بشكل صحيح لأنه كان يحتوي بعض الأخطاء df = pd.DataFrame({'city': ['Cairo', 'Dohha', 'Riyadh', 'Dubai'] * 3, 'office_id':[x*2 for x in range(1, 7)]*2 , 'sales': [np.random.randint(100000, 999999) for _ in range(12)]}) df """ city office_id sales 0 Cairo 2 405711 1 Dohha 4 535829 2 Riyadh 6 217952 3 Dubai 8 252315 4 Cairo 10 982371 5 Dohha 12 459783 6 Riyadh 2 404137 7 Dubai 4 222579 8 Cairo 6 710581 9 Dohha 8 548242 10 Riyadh 10 474564 11 Dubai 12 835831 """ #office_id و city نطبق عملية التجميع على أساس العمود # نحصل الآن على المدن مع كل المكاتب الموجودة فيها مع مبيعات كل مكتب city_office = df.groupby(['city', 'office_id']).agg({'sales': 'sum'}) city_office """ sales city office_id Cairo 2 405711 6 710581 10 982371 Dohha 4 535829 8 548242 12 459783 Dubai 4 222579 8 252315 12 835831 Riyadh 2 404137 6 217952 10 474564 """ # لكننا نريد حساب النسبة المئوية لمبيعات كل مكتب ضمن مدينة معينة أي يجب أن نحسب النسبة مقارنةً بباقي مبيعات المكاتب ضمن المدينة # بذا يجب علينا إنشاء داتافريم آخر ليحسب لنا مجموع مبيعات كل المكاتب ضمن كل مدينة # الآن ننظم مبيعات كل مكتب City = df.groupby(['city']).agg({'sales': 'sum'}) City """ sales city Cairo 2098663 405711+710581+982371 Dohha 1543854 Dubai 1310725 Riyadh 1096653 """ #city على القيمة المقابلة له من جدول sales الآن نعود للداتافريم السابق ونقوم بقسمة كل قيمة في عمود ال # وبالتالي نحصل على النسبة المطلوبة # نحتاج فقط لاستخدام للقسمة والضرب ب100 في عمود المبيعات city_office.div(City, level='city') * 100 """ sales city office_id Cairo 2 19.331879 = (405711/2098663)*100 6 33.858747 10 46.809373 Dohha 4 34.707233 8 35.511259 12 29.781508 Dubai 4 16.981365 8 19.250033 12 63.768601 Riyadh 2 36.851857 6 19.874290 10 43.273852 """
    1 نقطة
  40. يمكنك فعل ذلك باستخدام التحويل transformation, ربما يكون الحل الأسهل والأسرع حيث يمكنك فعل ذلك باستخدام سطر واحد فقط كالتالي df['%'] = 100 * df['sales'] / df.groupby('city')['sales'].transform('sum') لو أردت طباعة النتيجة print(df.sort_values(['city', 'office_id']).reset_index(drop=True)) city office_id sales % 0 Cairo 2 195197 9.844309 1 Cairo 4 877890 44.274352 2 Cairo 6 909754 45.881339 3 Dohha 1 614752 50.415708 4 Dohha 3 395340 32.421767 5 Dohha 5 209274 17.162525 6 Riyadh 1 549430 42.659629 7 Riyadh 3 457514 35.522956 8 Riyadh 5 280995 21.817415 9 Dubai 2 828238 35.696929 10 Dubai 4 719366 31.004563 11 Dubai 6 772590 33.298509
    1 نقطة
  41. يجب أن تنتبه أن df.iloc, df.loc, df.at يتم تنفيذهم مع حالة كان index بإستخدام الكلمات كما في المثال او الأرقام، df.iloc تعمل فقط في حال كان integer index. أما df.loc و df.at يمكن أن يعملان في حالة كنت تريد الإضافة بإستخدام إسم العمود مع integer index. في حالة كان index غير معرف فإن كل من df.loc , df.at يقومان بالإضافة في dataframe بصورة مباشرة و لكن df.iloc تقوم بإنشاء خطأ، لاحظ المثال التالي: import numpy as np, pandas as pd df = pd.DataFrame(index=np.arange(3), columns=['x','y','z']) df['x'] = ['A','B','C'] df.at[2,'y'] = 400 # الأسطر و الأعمدة غير موجودة في البيانات الأساسية بالتالي يتم إضافتهم df.at['D','w'] = 9000 df.loc['E','q'] = 499 # هذه الطريقة تقوم بإستخدام عبارة شرطية لفلترة البيانات و من قم الإضافة df.at[df1['x']=='B', 'y'] = 10000 df.loc[df1['x']=='B', ['z','w']] = 10000 # إضافة قيم بإستخدام index df.iloc[[1,2,4], 2] = 9999 df.loc[[0,'D','E'],'w'] = 7500 df.at[[0,2,"D"],'x'] = 10 df.at[:, ['y', 'w']] = 8000 df
    1 نقطة
  42. الفرق المحوري بين الدالتين أن size يمكن أن تحتوي على NaN اما count فلا،أنظر المثال التالي للتوضيح أكثر: In [1]: df = pd.DataFrame({'x':[0,1,2,2], 'y':[1,2,4,np.NaN], 'z':np.random.randn(4)}) df Out[46]: a b c 0 0 1 1.067627 1 1 2 0.458084 2 2 NaN -2.238091 3 2 4 1.256943 In [2]: print(df.groupby(['x'])['y'].count()) x 0 1 1 1 2 1 In [3]: print(df.groupby(['x'])['y'].size()) x 0 1 1 1 2 2 لاحظ أنه في count لم يقم بعَد ال NaN بينما قام بعَدها في size.
    1 نقطة
  43. إليك جميع الطرق مع مقارنة بزمن التنفيذ بينها: import numpy as np import pandas as pd df = pd.DataFrame(np.random.rand(100, 100)) %timeit df.iat[50,50]=50 # ✓ %timeit df.at[50,50]=50 # ✔ %timeit df.set_value(50,50,50) # سوف يتم إلغاءها في قادم النسخ %timeit df.iloc[50,50]=50 %timeit df.loc[50,50]=50 """ 7.06 µs ± 118 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) الأفضل 5.52 µs ± 64.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) الأفضل 3.68 µs ± 80.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 98.7 µs ± 1.07 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) 109 µs ± 1.42 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) """ كما يمكنك تعديل القيم بالشكل التالي: import pandas as pd df = pd.DataFrame(index=['A','B','C'], columns=['D','E']) df.D["C"]=2
    1 نقطة
  44. اذا كنت تريد التعديل على ال dataframe بحيث تقوم بعمل نسخة معدلة مع ابقاء النسخة الأصلية غير معدلة يمكنك عمل التالي: df.xs('C')['D']=20 اما اذا أردت التعديل على ال dataframe الأصلية فيمكنك استخدام الكود التالي: df.at['C', 'D'] = 20 وكذلك يمكنك استخدام set_value كالتالي: df.set_value('C', 'D', 20)
    1 نقطة
  45. يمكنك استخدام option_context لطباعة كافة ال dataframe كالتالي: with pd.option_context('display.max_rows', None, 'display.max_columns', None): print(df) اذا كنت تستخدم jupyter-notebook يجب أن تستخدم display(df) بدلا من print(df) كذلك يمكنك استخدام الكود التالي: print(df.to_string()) وهذا أيضا سيقوم بطباعة كافة ال dataframe على الشاشة
    1 نقطة
  46. إذا قمتِ بكتابة كود CSS في ملف خارجي أو حتى في عنصر style فيجب التأكد من أنه لا توجد خصائص أخرى تقوم بتغير خلفية عنصر div، أما في الحالة الثانية (كتابة خصائص CSS بداخل عنصر div) فإن الكود الصحيح هو: <div style="background-color: #080;">Content Here</div> مع العلم أن عنصر div لن يظهر إلا إن تم وضع طول وعرض له أو كان يتحوي على محتوى (نصوص أو صور أو عناصر أخرى)، غير ذلك لن يظهر عنصر div لأن طوله يساوي 0.
    1 نقطة
  47. هي طبقة تنتمي إلى فئة الطبقات المتكررة RNN (Recurrent Neural Networks) إن ال LSTM التي أطلقها Hochreiter في ورقته البحثية عام 97 ماهي إلا تطوير لشبكة ال RNN التقليدية (في كيراس وتنسرفلو SimpleRNN) التي كنت قد تحدثت عنها في سؤال سابق (تجد رابطه في الأسفل). الاختلاف كان في النقاط الأساسية التالية: 1.قدرة النظام على تخزين المعلومات لمدة أطول وبالتالي معالجة أكبر مشكلة والعيب الأساسي لل SimpleRNN وهو تضائل الاشتقاقات أي عدم قدرتها على تذكر معلومات التسلسل مع التقدم بالخطوات الزمنية أي بشكل مبسط أكثر "مثلاً عدم قدرتها على تذكر الكلمات السابقة أي مثلاً في نص طوله 50 كلمة عندما تصل للكلمة رقم 40 ستنسى ماهي الكلمة رقم 10 أي لن تتذكرها جيداً وبالتالي هذا يؤثر على فهمها للسياق وبالتالي نتائج أضعف ولاسيما في المجالات التي تركز على فهم السياق مثل الترجمة ". 2.قدرة النظام على مقاومة الضجيج (ليست ذات الصلة بالتنبؤ بإخراج صحيح). في كيراس وتنسر فلو هي عبارة عن كلاس له الشكل التالي: tf.keras.layers.LSTM( units, activation="tanh", recurrent_activation="sigmoid", use_bias=True, dropout=0.0, return_sequences=False ) حيث أن units هي عدد الخلايا أو الوحدات في الشبكة، أما الوسيط الثاني هو تابع التنشيط المستخدم، أما الثالث فيحدد فيما إذا كنت تريد إضافة الانحراف b الذي أشرنا له في الأعلى (دوماً true)، الوسيط الرابع هو وسيط ال dropout لتحديد نسبة الخلايا التي سيتم إسقاطها في الشبكة (بين 0 و 1) الوسيط الأخير لتحديد شكل الإخراج ففي حال قمت بضبطه على True سوف يكون الخرج 3D حيث يقوم بإعادة كامل التسلسل أما في الحالة الافتراضية أي False يقوم بإعادة الخرج الأخير من تسلسل الخرج. طبعاً لكي لاتقع في الأخطاء يجب أن نضع True إذا كانت الطبقة التالية هي طبقة تكرارية و False إذا كانت طبقة Dense فالطبقات التكرارية دخلها يجب أن يكون 3D بينما طبقات Dense دخلها يكون 2D. والدخل لهذه الطبقة يكون: [batch, timesteps, feature] والخرج: يكون إما 2D أو 3D كما أشرنا. المثال التالي لاستخدام هذه الطبقة مع مجموعة بيانات imdb لتحليل المشاعر: from keras.datasets import imdb from keras.preprocessing import sequence max_features = 10000 maxlen = 20 # تحميل البيانات print('Loading data...') (input_train, y_train), (input_test, y_test) = imdb.load_data(num_words=max_features) print(len(input_train), 'train sequences') print(len(input_test), 'test sequences') print('Pad sequences (samples x time)') # معالجة البيانات input_train = sequence.pad_sequences(input_train, maxlen=maxlen) # حشو input_test = sequence.pad_sequences(input_test, maxlen=maxlen) # حشو print('input_train shape:', input_train.shape) print('input_test shape:', input_test.shape) # بناء النموذج from keras.layers import Dense,Embedding,LSTM import keras model = keras.Sequential() model.add(Embedding(max_features, 64)) model.add(LSTM(64)) model.add(Dense(1, activation='sigmoid')) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc']) history = model.fit(input_train, y_train, epochs=10, batch_size=64, validation_split=0.2) """ Loading data... 25000 train sequences 25000 test sequences Pad sequences (samples x time) input_train shape: (25000, 20) input_test shape: (25000, 20) Epoch 1/10 313/313 [==============================] - 17s 36ms/step - loss: 0.6070 - acc: 0.6435 - val_loss: 0.4929 - val_acc: 0.7478 Epoch 2/10 313/313 [==============================] - 9s 30ms/step - loss: 0.3900 - acc: 0.8248 - val_loss: 0.5014 - val_acc: 0.7502 """ للإطلاع على SimpleRNN رغم أنني أجبتك عليها سابقاً:
    1 نقطة
  48. منذ أكثر من مئة عام عندما وضعت جامعة هارفارد أول منهج أكاديمي يدرس إدارة الأعمال وحتى اليوم كانت العلوم الإدارية كلها تركّز على إدارة المشاريع القائمة وتطويرها و حلِّ مشاكلها، وبهذا وجدنا مثلًا الإدارة المالية تبحث في سبل تأمين الموارد المالية اللازمة لتكبير المشروع، وإدارة الموارد البشرية تبحث في طرق تعيين الموظفين الأكثر كفاءة، وحتى الإدارة الاستراتيجية كانت تبحث في مستقبل المشروع الحالي. اليوم مع تطور شكل منظمات الأعمال والمشاريع بدأت تظهر هناك ما تعرف بالشركات الناشئة Startups والتي تشترك في أنها تقدّم منتجات أو خدمات أو تدخل في أسواق جديدة كليًا. بالتالي ظهرت فجوة كبيرة وهي أنَّ علم إدارة الأعمال لم يكن جاهزًا لتقديم أدوات تساعد على تأسيس هذه الشركات على الرّغم من أنّه يملك خبرة تزيد عن القرن في تطوير وإنماء الشركات القائمة بحد ذاتها. ومن هذا المنطلق كانت أداة مخطط نموذج العمل التجاري Business Model Canvas واحدة من الأدوات الثوريّة التي لبّت حاجة رواد الأعمال في التخطيط لمشاريعهم وشركاتهم الناشئة على الورق قبل إطلاقها. لماذا نحتاج مخطط نموذج العمل التجاري؟يعود الفضل لابتكار مخطط نموذج العمل التجاري إلى المؤلفين أليكس اوسترفالدر Alexander Osterwalder وإيف بينورYves Pigneur اللذين قدّماه في كتابهما Business Model generation والذي أطلق عام 2010. وتمت ترجمته للعربية العام الماضي (ابتكار نموذج العمل التجاري). وباختصار شديد يمكن أن نعرّف هذا المخطط على أنّه طريقة بصرية تخطيطية يمكن استخدامها أثناء مرحلة التخطيط للمشروع من أجل تدارُك الوقوع بالأخطاء قدر الإمكان. وهنا يبرز الفارق ما بين التخطيط للمشاريع التقليدية ولنقل محل لبيع العصائر والكوكتيل وبين المشاريع الناشئة الابتكارية مثل تطبيقات الهواتف الذكية. حيث أنّ المشاريع التقليدية لا تحتاج لبذل الكثير من الجهد في التخطيط فكل ما تحتاجه هو دراسة سريعة للجدوى الاقتصادية، بينما المشاريع الابتكارية فهي تحتاج لمزيد من التخطيط قبل الوصول لمرحلة دراسة الجدوى. سابقًا عندما كنت تود إطلاق مشروع ما تقوم بإعداد دراسة الجدوى، ومن ثم كتابة خطة العمل لتقديمها للمستثمرين (بنك أو رجل أعمال) من أجل الحصول على التمويل اللازم. أما اليوم مع الشركات الناشئة والمشاريع الابتكارية فإنك بحاجة لإعداد مخطط نموذج العمل التجاري قبل كتابة خطة العمل ودراسة الجدوى. لأنّ دراسة الجدوى تجيبك عن سؤال هام وهو: لو نفّذنا المشروع بهذه المعطيات، هل سيربح أم يخسر؟ بينما خطة العمل تجيبك عن سؤال هام هو: كيف سننفّذ العمل ونديره؟ لكن مخطط نموذج العمل يبدأ من مرحلة أبكر وهي الإجابة عن سؤال: ما الذي يجب أن نقدّمه؟ ولمن؟. فبدون مخطط نموذج العمل التجاري الصحيح لن نتمكن من الوصول إلى خطة عمل صحيحة وبالتالي فإنّ دراسة الجدوى الاقتصادية لن تكون صحيحة أيضًا. الدور الهام الذي يلعبه مخطط نموذج العمل التجاري هو أنّ الشركات الناشئة ليست مجرد نسخة بدائية من الشركات القائمة، بل هناك اختلاف جوهريّ في وظيفة كلٍّ منهما، حيث أنّ الشركة الناشئة دورها البحث عن نموذج عمل ناجح، بينما المشروع القائم دوره تنفيذ نموذج العمل أو النموذج الربحي Business Model. وهنا يأتي دور مخطط نموذج العمل حيث يسهّل على الشركات الناشئة عملية البحث عن النموذج الربحي المناسب لهم. الصورة مأخوذة من الترجمة العربية من الكتاب الذي يُمكن الحصول عليه من هنا ينقسم مخطط نموذج العمل التجاري إلى تسعة مكونات رئيسة وهي: 1- القيمة المقترحة أو العرض المقدّم Value Proposition 2- شرائح العملاء أو الزبائن Customer Segments 3- قنوات التوزيع Channels 4- العلاقة مع العملاء Customer Relationship 5- مصادر الإيرادات Revenue Stream 6- الموارد الأساسية Key Resources 7- الأنشطة الأساسية Key Activities 8- هيكل التكاليف structure Costs 9- الشركاء الأساسيون Key Partners 1- القيمة المقترحة أو العرض المقدّم Value Propositionقبل أن نشرّع في الحديث عن القيمة المقترحة، لنعرّف أولًا ما هي القيمة؟ وبم تختلف عن السعر و الثمن؟ ببساطة شديدة القيمة هي ما تحصل عليه من المنتج أو الخدمة، والسعر هو المبلغ المالي المطلوب دفعه لقاء الحصول على المنتج أو الخدمة، أما الثمن فهو يشمل إضافة للسعر الوقت والجهد المبذولان في المفاضلة ما بين المنتجات أو الخدمات المشابهة والبحث عنها واتخاذ القرار النهائي في شراء منتج أو خدمة معينة. إذًا السعر هو ما تدفعه والقيمة هي ما تحصل عليه. يقسّم خبراء التسويق عادة أي منتج إلى ثلاث طبقات، الخارجية وهي كافة العناصر المعنوية الإضافية التي تحصل عليها من المنتج كالشعور بالفخامة مع علامة تجارية معينة أو الثقة من شراء علامة تجارية أخرى أو حتى الصيانة المجانية أو التركيب المجاني. والطبقة الثانية الوسطى وهي التي عادة ما تعرف بها المنتجات وهي كافة العناصر الملموسة التي تشكّل كيان المنتج، أي الشكل واللون والوزن والرائحة والمواد الداخلة بصنعه .. إلخ. والطبقة الجوهرية الثالثة هي في الحقيقة أهم شيء في المنتج، هي السبب الذي يدفع الزبون لشراء المنتج وهي القيمة الحقيقية التي يقدّمها هذا المنتج. ليكن لدينا هاتف الآيفون كمثال، فالطبقة الخارجية هي إحساس التميّز من شراء أحد منتجات شركة آبل والطبقة الوسطى هي الخصائص الفنية للمنتج بحدّ ذاته كالتصميم والشاشة والكاميرا والطبقة الجوهرية هي خدمة الاتصال المحمول وتصفح الإنترنت واستخدام التطبيقات. لاحظ أن الزبون لا يشتري الآيفون لمجرد التميّز وإحساس الفخامة ولا من أجل شراء شاشة وكاميرا ودارات إلكترونية، إنّما من أجل الاتصال وهذه هي القيمة الجوهرية التي يقدّمها الآيفون ويتم تدعيمها بكافة الطبقات والخصائص الأخرى لتميّزه عن غيره حيث أن هناك طيفًا واسعًا من المنتجات التي تقدّم الخدمة الجوهرية نفسها. هناك عدة مداخل يمكن استخدامها في العرض المقدّم أو القيمة التي تودّ الشركة توصيلها لزبائنها: 1- القيمة المبتكرة أو الجديدة وهي المنتجات التي تكون جديدة كليًا على السوق مثل الآيباد حيث لم يكن هناك من قبله تعرف الحواسيب اللوحية على الرغم من أنه كانت هناك حاجة لها لكنها لم تكن واضحة تمامًا ولم يقم أحد بصنع منتج يلبيها. فالقيمة التي يدفع الناس مقابلها هي أنه منتج لا يوجد له بديل يمكن أن يحلّ محلّه. 2- القيمة بالأداء العاليوهنا عندما يكون منتجك مشابه لمنتجات كثيرة في السوق ويلبّي نفس القيمة التي يبحث عنها الزبون، يمكنك التميّز بتقديم قيمة أعلى من خلال الأداء الأعلى. ومن الأمثلة على هذا شركات صناعة الحواسب المحمولة فهي تواصل طرح المزيد من المنتجات التي تتميز عن بعضها فقط في أن أداءها أفضل وأعلى من السابق بالتالي يمكنها إنجاز الأعمال بسرعة وكفاءة أعلى. 3- القيمة بالتخصيص في العادة تقدم الشركات منتجاتها بشكل نمطي لكلّ الأسواق، وهنا يمكن التميّز وتقديم قيمة جديدة من خلال إتاحة تخصيص المنتج بحسب رغبات كل زبون بشكل منفصل. كما فعلت شركة موتورولا عندما أتاحت لكلّ زبون تصميم الهاتف الخاص به وحتى اختيار مواد صناعة الغطاء الخلفي لجهاز موتو إكس وهو ما لا توفّره باقي شركات الهواتف الذكية. 4- القيمة بالخدمة الشاملةبعض المنتجات المعقّدة والتي تحتاج لكثير من التخطيط قبل شرائها نظرًا للمخاطرة العالية فيها كالسعر المرتفع، يمكن تقديم قيمة أعلى من خلال الخدمة الشاملة. فمثلًا يمكن لشركة تصنع معدات طبية مثل أجهزة الليزر أن تقدّم خدمة النقل والتركيب والتدريب المجاني وحتى توفير الصيانة وقطع الغيار ما يخلق لها قيمة جديدة لا توفّرها الشركات المنافسة التي تكتفي ببيعك المنتج فقط. 5- القيمة بالتصميم في المنتجات المتشابهة التي تصنعها العديد من الشركات نجد أنّ بعضها يتميّز بتصميمه الجذّاب أو الذي يسهل استخدامه أو يمكن التعلّم على استعماله بسهولة حتى لكبار السنّ أو الأطفال وهنا مدخل جديد لوضع قيمة في المنتج هي بتحسين تصميمه، ومن أبرز الأمثلة على هذا المدخل بعض الهواتف الذكية التي تحمل مواصفات فنية متشابهة بالتالي تتميّز شركات عن غيرها بتصميم هواتفها. 6- القيمة بالسعر وهنا عندما يكون لديك منتج نمطي يشبه الكثير من المنافسين ولا تتمكن من تقديمه بتصميم جميل أو مفيد وسهل، يبقى أمامك المنافسة بالسعر بالتالي تتميّز عن باقي المنافسين. وهو ما فعلته العديد من شركات صناعة الهواتف الذكية الصينية حيث أنها تمكّنت من تقديم منتجاتها بأسعار رخيصة للغاية ما يجعلها تستهدف شريحة الزبائن التي تكون حساسة للسعر. 7- القيمة بالأمان وهي قيمة تعاكس السعر حيث يبحث هنا الزبون عن الأمان الأعلى ولو على حساب السعر، ونلاحظ هذه القيمة في المنتجات التي ترتبط بحياة الزبون كالسيارات مثلًا تميّزت فولفو السويدية بهذا المجال حيث أن سياراتها ليست الأفضل أداء ولا الأجمل تصميمًا ولا الأرخص سعرًا لكنها الأعلى أمانًا. 8- القيمة بسهولة الحصول على المنتج في المنتجات الاستهلاكية أو متكررة الشراء يكون معيار سهولة الحصول على المنتج حاسمًا بصنع القيمة بخاصة عندما يكون منتج نمطي كالمشروبات الغازية مثلًا عندما يتوفر منتجك في قنوات توزيع أكبر تغطي كلّ شارع في المدينة حيث سيجعل الزبون يفضّل هذا المنتج عن غيره الذي يحتاج لبحث عنه. إذًا القيمة المقترحة أو العرض المقدّم في منتجك هو كلّ العناصر التي تميّز شركة عن منافسيها ويدفع الزبون من أجلها ماله. وهذه كانت بعض الأمثلة عن طرق صنع القيمة في المنتج ويمكن الاعتماد على أكثر من مدخل معًا ما يجعل تقليد المنتج أصعب. 2- شرائح العملاء Customers Segmentsوهي الأفراد أو الشركات أو الجهات التي تسعى الشركة لخدمتهم من خلال العرض المقدّم. ويمكن أن يقسّم العملاء لعدّة شرائح أو مجموعات تشترك فيما بينها بصفات أو معايير معيّنة ويكون لكلّ شريحة قيمة أو عرض مقدّم مختلف عن الشريحة الأخرى. يمكن الاعتماد على عدّة معايير لتقسيم الشرائح، مثلًا بحسب احتياجاتهم فكلّ نوعية من الزبائن لديها احتياجات مختلفة تبحث عنها في منتجات الشركة لتلبيتها ويمكن الأخذ بالمعايير الديموغرافية هنا كالعمر والجنس ومعدل الدخل وغيرها، أو طرق الوصول للزبائن وذلك بتقسيم الأسواق إلى محلية وإقليمية وعالمية وغيرها. هناك أربعة أنواع لقطاعات شرائح العملاء تعدّ الأشهر ويمكن التعرّف على خصائصها: 1- كامل السوق وهنا توجّه أنشطة الشركة بكاملها إلى السوق باعتباره كتلة واحدة من الزبائن المتشابهين، كما في صناعة السيارات عندما يكون الزبائن المحتملون كافتهم يرغبون بالحصول على السيارات من أجل قيمة واحدة وهي النقل السريع المريح. 2- السوق المخصّصيتم تقسيم السوق إلى شريحة دقيقة لديها احتياجات خاصة من العرض المقدّم ويتم تحويل الأنشطة كافتها لتلبيتها. وبمثل صناعة السيارات هناك شركات تصنع سيارات فاخرة للغاية وأخرى تصنع سيارات رياضية فهذه الشركات تتجاهل معظم حجم السوق الذي يرغب بقيمة النقل السريع المريح وتقوم بتلبية الشريحة التي تبحث عن الفخامة أو السيارات السريعة. 3- التجزئة تقوم الشركة بتقسيم إضافي لشريحة زبائن بناءً على معايير جديدة. فيمكن لشركة أدوات صناعية أن تقسّم زبائنها من الشركات الصناعية بحسب مجالات صناعاتها. 4- التنويع وهنا تقوم الشركة بتلبية عدّة شرائح مختلفة من العملاء لها احتياجات أو قيم مختلفة, مثلًا فيس بوك يلبي احتياجات المستخدمين العاديين الباحثين عن التواصل الاجتماعي، بينما المعلنين يبحثون عن الوصول لزبائن أكثر، في حين أن المطوّرين يرغبون بمستخدمين أكثر لتطبيقاتهم. لاحظ كيف أن فيس بوك يلبي هذه الشرائح الثلاثة بالوقت نفسه. 3-قنوات التوزيع Channelsهي كافة الطرق والآليات التي تعتمد عليها الشركة في توصيل كلّ شريحة من شرائح العملاء المذكورة أعلاه مع القيمة التي يبحثون عنها. أي هي صلة الوصل ما بين المنتج أو الخدمة من جهة و شرائح العملاء من جهة أخرى. وكلّ قناة توزيع ناجحة يجب أن تؤدي خمس وظائف: 1- زيادة الوعيبخاصة عندما تكون الشركة أو المنتج جديدًا على السوق فيجب أن تعمل قناة التوزيع المستخدمة على زيادة وعي شرائح العملاء بالشركة أو المنتج وتعريفهم بتواجدها. 2- التقييم بعد أن أصبحت شريحة العملاء على وعي بوجود الشركة ومنتجاتها، يجب أن تساعد قناة التوزيع العملاء على تقييم ما تمت توعيتهم به، والتقييم هنا يصبّ على إيصال العرض المقدّم الحقيقي لشريحة العملاء المطلوبة. 3- الشراءبعد أن تعرّف العملاء على المنتج وقاموا بتقييم المنفعة المتحصّلة من ورائه، يجب أن تساعدهم قناة التوزيع على شراء المنتج بحيث تقوم بتذليل كافة مصاعب الشراء الممكنة. 4- التوصيل بعد الشراء يفترض بالقناة أن تساعد المستخدم على توصيل المنتج أو الخدمة واستهلاكها بالمكان الذي يريده وذلك بفعالية عالية فتكون سريعة وغير مكلفة. 5- خدمة ما بعد البيع بعد الانتهاء من توصيل واستهلاك المنتج أو الخدمة تأتي خدمات ما بعد البيع وذلك بعدة أشكال من أبسطها الدعم الفني وحلّ المشاكل أو الصيانة أو المساعدة بالتخلّص من المنتج حتى. هناك اليوم عدد كبير من قنوات التوزيع التي يمكن اعتمادها، ففي السابق كانت هناك القنوات الفيزيائية الحقيقية فقط من أجل الحصول على المنتج عليك التوجّه إلى مكان صنعه أو بيعه ويمكن للشركات فتح منافذ بيع خاصة بها أو توكيلها لشركاء تجزئة. أما اليوم فهناك منتجات وخدمات إلكترونية تعتمد على قنوات إلكترونية لتقديمها كالتطبيقات والمواقع. سنواصل شرح باقي المُكوّنات في المقال القادم
    1 نقطة
  49. مبدأ فصل الواجهات Interface Segregation Principle أو اختصارًا ISP هو أحد المبادئ الشهيرة من مبادئ SOLID في التصميم الكائنيّ. أوّل من قدّم هذا المبدأ روبرت مارتن في سلسلة مقالات في عام 1996، ويهدف هذا المبدأ إلى تجنُّب إنشاء واجهات "سمينة". الواجهة interface هي عبارة عن تجريد abstraction لناحية وظيفيّة (أو أكثر) ترث منها أنواع (أصناف) لدعم هذه الناحيّة الوظيفيّة، ونقول في هذه الحالة أنّ الصنف الابن يُحقّق الواجهة. فمثلًا تُعرّف الواجهة IComparer في لغة C# إمكانيّة المقارنة بين كائنين يحقّق صنفهما الواجهة IComparer. في لغات برمجة أخرى، قد لا يوجد تمثيل منفصل للواجهة، وإنّما يتم إنشاء أصناف ذات طبيعة مجرّدة لهذا الغرض، نسميها أصناف واجهة، وهي التي سنتحدّث عنها في هذا المقال. تظهر الواجهات السمينة (أو الملوّثة) بسبب توسعة صنف واجهة حالي ببعض النواحي الوظيفيّة الجديدة المفيدة لمجموعة جزئيّة فقط من التوابع methods. تؤدّي هذه الظاهرة في نهاية الأمر إلى إنشاء توابع ليس لها أيّ فائدة سوى تحقيق الواجهة للتمكّن من استخدامها. وهذا أمر سيّء بالطبع. تُعتبر تلك التوابع خطرة وهي تخرق على أيّة حال مبدأ LSP أيضًا. ينص مبدأ ISP كما كتبه المؤلّف: ينبغي أن يكون لكلّ واجهة هدف معرّف بوضوح ويُعبّر عن ناحية وظيفيّة مُحدّدة للمسألة المطروحة. الحل الأمثل (برأيي) لتحقيق هذا المبدأ هو استخدام الوراثة المتعدّدة عند تحقيق الواجهات. سيعمل هذا الأسلوب على فصل النواحي الوظيفيّة التي لا ترتبط منطقيًّا مع بعضها ويلغي الاعتماديّات dependencies الخاطئة. لنستعرض مثالًا يخرق مبدأ ISP. يتناول هذا المثال واجهة خاصّة بالنواحي الوظيفيّة الّتي من الممكن أن تمتلكها أي سيّارة: /* Bad example */ class CarOperation { public: virtual void steer(int degrees) = 0; virtual void pullHandbrake() = 0; virtual void accelerate() = 0; virtual void shift(int gear) = 0; virtual void toggleAirConditioning() = 0; }; هناك العديد من المزايا المألوفة التي توفّرها السيّارات، فكل سيّارة لها عجلة قيادة ومدوسة وقود بالإضافة إلى ناقل حركة يدوي وفرامل اليد. ولكن ماذا عن السيّارات التي لها ناقل حركة أوتوماتيكي؟ ففي مثل هذه السيّارات لا يوجد ناقل حركة يدوي، فالصنف الواجهة الوارد في الشيفرة السابقة سيجبر أي صنف ابن يرث منه على استخدام الطريقة shift التي تُعبّر عن ناقل حركة اليدوي حتى ولو كان هذا الصنف الابن يمثّل سيّارة ذات ناقل أوتوماتيكي. وينطبق نفس الكلام على الطريقة toggleAirConditioning التي تعبّر عن تشغيل جهاز التكييف في السيّارة رغم أنّ بعض السيّارات لا تملك جهاز تكييف. الأفضل في هذه الحالة أن نجزّئ الصنف الواجهة CarOperation إلى عدد من أصناف الواجهات الأصغر بحيث تُعبّر كلّ منها عن مجموعة محدّدة مترابطة منطقيًّا من المزايا: class BasicCarOperation { public: virtual void steer(int degrees) = 0; virtual void pullHandbrake() = 0; virtual void accelerate() = 0; }; class GearboxCarOperation { public: virtual void shift(int gear) = 0; }; class AirConditioningCarOperation { public: virtual void toggleAirConditioning() = 0; }; class AlfaRomeo166 : public BasicCarOperation, GearboxCarOperation, AirConditioningCarOperation { /* Implementation of all the interfaces. */ }; class SkodaFavorit136L : public BasicCarOperation, GearboxCarOperation { /* No air conditioning for old cars. */ }; سيلجأ الصنفان الابنان AlfaRomeo166 وSkodaFavorit136L إلى الوراثة المتعدّدة من الأصناف الواجهات. فإذا أردنا تشغيل جهاز التكييف في سيّارة ما عن طريق الدالّة beCool فسيكون ذلك كالتالي: void beCool(AirConditioningCarOperation* vehicle) { vehicle->toggleAirConditioning(); } نلاحظ أنّنا الدالّة beCool تقبل وسيطًا واحدًا وهو مؤشّر إلى كائن من النوع AirConditioningCarOperation، وهكذا فإنّ أي صنف ابن يرث من الصنف الواجهة AirConditioningCarOperation يمكن أن يُمرَّر إلى هذه الدالة بصرف النظر عن أيّ أصناف واجهات أخرى يرث منها هذا الصنف الابن. وهنا يكمن جمال مبدأ فصل الواجهات. سنحصل تمامًا على ما نريد، ليس أكثر وليس أقل، مما يجعل من الشيفرة البرمجيّة أسهل للصيانة ولإعادة الاستخدام وللفهم، ويساعد ذلك على تجنّب كم كبير من الأخطاء عندما نريد تعديل الشيفرة في المستقبل. المصادر: http://www.oodesign.com/interface-segregation-principle.html http://en.wikipedia.org/wiki/Interface_segregation_principle http://www.objectmentor.com/resources/articles/isp.pdf ترجمة -وبتصرّف- للمقال Interface Segregation Principle لصاحبه Radek Pazdera.
    1 نقطة
  50. مبدأ عكس التابعيّة Dependency Inversion Principle أو اختصارًا DIP، هو آخر مبادئ التصميم الكائنيّ SOLID ويتمتّع بمزايا كبيرة عند تطبيقه بالشكل السليم. أوّل من قدّم هذا المبدأ هو روبرت مارتن في مقالته التي نشرها عام 1996. أشار روبرت إلى أنّ الأسلوب الشائع في تصميم التابعيّة dependency ضمن المشاريع البرمجيّة في جعل الوحدات البرمجيّة عالية المستوى تعتمد على الوحدات البرمجيّة منخفضة المستوى بشكل مباشر هو أسلوب غير عمليّ ويؤدّي إلى مشاكل كبيرة عند إعادة استخدام الوحدات البرمجيّة عالية المستوى، تتمثّل هذه المشاكل في إجراء تعديلات برمجيّة عديدة عليها كي تتلاءم مع الاستخدام الجديد لها، وهذا بالطبع أمر غير جيّد. تُعتبر الوحدات البرمجيّة عالية المستوى بمثابة قلب التطبيق البرمجيّ. وقد نرغب في كثير من الأحيان أن نُعيد استخدامها في تطبيقات برمجيّة أخرى ولكن بدون إجراء تعديلات كبيرة عليها. يقترح روبرت مبدأ عكس التابعيّة والذي ينص على ما يلي: أ – لا ينبغي أن تعتمد الوحدات البرمجيّة عالية المستوى على الوحدات البرمجيّة منخفضة المستوى. يجب على كلّ منهما الاعتماد على واجهات (أصناف مجرّدة). ب – لا ينبغي أن تعتمد الواجهات/الأصناف المُجردّة على التفاصيل، فالتفاصيل هي من يجب أن تعتمد على الأصناف الواجهات. قد يكون من الصعب قليلًا فهم هذا المبدأ مباشرةً، لذلك اسمح لي بتوضيحه بشكل أفضل. يُقرّ هذا المبدأ أنّه ينبغي أن تكون هناك طبقة تجريديّة إضافيّة بين الوحدات البرمجيّة عالية ومنخفضة المستوى، تتألّف الطبقة التجريديّة من واجهات. فإذا كان لدينا وحدتان برمجيّتان أردنا أن تعتمد إحداهما على الأخر، فإنّ هذه الاعتماديّة ينبغي أن تتمّ عن طريق صنف واجهة معرّف خصيصًا لهذا الغرض. بهذا الأسلوب، فإنّ الوحدات البرمجيّة عالية المستوى لا تتعامل مباشرةً مع الوحدات البرمجيّة منخفضة المستوى. ستعمل الوحدات البرمجيّة منخفضة المستوى على تحقيق الواجهات (نستطيع القول أنّها سترث منها)، ففي حال أردنا استخدام أي وحدة برمجيّة في مشروع برمجيّ آخر فلن نحتاج إلى تعديل أيّ شيء ضمن الشيفرة البرمجيّة لها. فكل ما نحتاجه ببساطة هو تحقيق الواجهات التي ستعتمد عليها الوحدة البرمجيّة المراد إعادة استخدامها. بالنسبة للقسم الثاني من المبدأ (الفقرة ب) فهو ينبّه بأنّ الواجهات ينبغي ألّا تصمّم وفقًا للوحدات البرمجيّة منخفضة المستوى (التفاصيل). حيث ينبغي أن تُحقّق الأصناف الوجهات على نفس مستوى التجريد الذي تتمتّع به الوحدات البرمجيّة عالية المستوى. مثال عن عكس التابعيّة لنستعرض الآن مثالًا حول كيفية تطبيق هذا المبدأ. يدور هذا المثال حول التعامل مع الواجهات الرسوميّة للمستخدم، ليكن لدينا صنف يمثّل نافذة Window تحوي زرّين Button: class Button { public: void makeVisible(); }; class Window { Button* okButton; Button* cancelButton; Window() { okButton = new Button; okButton->makeVisible(); cancelButton = new Button; cancelButton->makeVisible(); } }; تكمن المشكلة هنا أنّه إذا تغيّر الصنف Button، سنضطّر إلى تغيير بانية الصنف Window أيضًا، وهذا بالطبع أمر غير مرغوب به، لأنّ الصنف Window سيكون عُرضةً للكثير من الاختبارات أثناء بناء البرنامج، وهذا سيؤدّي إلى الكثير من الأخطاء في كلّ مرّة نُعدّل فيها الصنف Button. يؤدّي استخدام صنف واجهة إلى تحسين التصميم إلى حدّ كبير: class IButton { public: static virtual IButton* getInstance() = 0; // factory method virtual void show() = 0; }; class Window { IButton* okButton; IButton* cancelButton; public: Window() { okButton = IButton::getInstance(); okButton->show(); cancelButton = IButton::getInstance(); cancelButton->show(); } }; class Button : public IButton { public: void show(); }; كما نرى الآن، يوجد صنف واجهة اسمه IButton وكل من الصنفين Button وWindow يعتمدان عليه. وهذا أمر جيّد للغاية، ففي حال أردنا استخدام الصنف Window في تطبيق برمجيّ جديد، فكل ما علينا هو استخدام أزرار Button تُحقّق الواجهة IButton فحسب. نلاحظ أيضًا التّابع الساكن getInstance الذي نستخدمه للحصول على الكائن الملائم من صنف الزر الذي يُحقّق صنف الواجهة IButton. المصادر http://www.objectmentor.com/publications/dip.pdf http://www.oodesign.com/dependency-inversion-principle.html http://en.wikipedia.org/wiki/Dependency_inversion_principle ترجمة -وبتصرّف- للمقال Dependency Inversion Principle لصاحبه Radek Pazdera.
    1 نقطة
×
×
  • أضف...