كمقدمة ، أود أن أذكر اقتباس
العم بوبأنت تقرأ هذا المقال لسببين. الأول - أنت مبرمج ، والثاني - تريد أن تكون أفضل مبرمج.
تخيل أنك في مكتبة وتبحث عن بعض الكتب. إذا تم تصنيف المكتبة ، وتضم فئات من الكتب ، فستجد بسرعة ما تحتاجه. بالإضافة إلى ذلك ، فإن التصميم الداخلي والهندسة المعمارية اللطيفين سيجعل إقامتك في هذه المكتبة مريحة للغاية بالنسبة لك.
كما هو الحال مع كتابة الكتب ، إذا كنت ترغب في إنشاء شيء رائع ، فأنت بحاجة إلى معرفة كيفية الكتابة وكيفية تنظيم التعليمات البرمجية الخاصة بك. إذا كان لديك أعضاء في الفريق أو أي شخص آخر لديه كود (قديم) ، فسوف يحتاجون فقط لرؤية الأسماء أو الحزم أو الفئات المتغيرة ، وسوف يفهمون على الفور. لا يحتاجون إلى قول "E ** l" أنا هذا الرمز وبدء تشغيله مرة أخرى من نقطة الصفر.
ما هو الكود النظيف؟

ترجمةعزيزي مبرمج:
عندما كتبت هذا الكود ، عرفنا الله فقط وكيف يعمل!
الآن فقط الله يعلم هذا!
قبل أن تحاول تحسين هذا الروتين ولن يؤدي إلى النجاح (على الأرجح) ، يرجى زيادة عداد الوقت لتحذير المطور التالي
مجموع الساعات التي قضاها: 567
كما ترون ، لا يكفي إنهاء التطوير بشكل أسرع. إذا لم يتمكنوا في المستقبل من معرفة هذا الرمز ، فسيصبح أيضًا دينًا تقنيًا.
رمزك في حالة "نقية" إذا كان بإمكان كل عضو في فريقك فهمه. يمكن قراءة التعليمات البرمجية النظيفة وتحسينها بواسطة أي مطور بخلاف المؤلف الأصلي. مع الفهم يأتي قابلية القراءة ، قابلية التغيير ، القابلية للتوسعة وقابلية الصيانة.
يجب أن أعتني بهذا؟
السبب الذي يجعلك تهتم بنظافة الكود هو أنك تصف أفكارك للمطورين الآخرين. هذا هو السبب في أنك يجب أن تهتم بأن رمزك أكثر أناقة وبساطة وقراءة.
علامات كود النظيفة
- يجب أن يكون رمزك أنيقًا: يجب أن تجعلك الشفرة تبتسم مثل صندوق الموسيقى جيد التصميم أو السيارة المصممة جيدًا
- يجب أن تركز التعليمات البرمجية الخاصة بك: كل وظيفة ، كل فئة ، كل وحدة تنفذ مهمة واحدة ، والتي لا تزال غير مشتتة تماما وغير ملوثة بالتفاصيل المحيطة.
- لا يحتوي الكود على التكرارات
- اجتياز جميع الاختبارات بنجاح
- تقليل عدد الكيانات والأساليب والفئات وما إلى ذلك
الفرق بين مبرمج جيد ومحترف هو أن المبرمج المحترف يفهم أن فهم الكود أمر بالغ الأهمية. يستخدم المحترف هذه القوة لكتابة التعليمات البرمجية التي يفهمها الجميع - Robert C. Martin
اكتب الأسماء الواعية
قد يستغرق اختيار اسم جيد الكثير من الوقت ، ولكنه سيوفر في وقت لاحق المزيد. يجب أن يجيب اسم المتغير ، الوظيفة ، الفصل على جميع الأسئلة المهمة. يجب أن تخبرك عن سبب وجودها ، والسبب في ذلك وكيفية استخدامها. إذا كان الاسم يتطلب تعليقًا ، فلن يكشف الاسم عن غرضه
مثال بسيط
أسماء الصف
يجب أن تكون الفئات والكائنات أسماء ، مثل Custom و WikiPage و Account و AddressParser. تجنب كلمات مثل Manager أو Processor أو Data أو Info. تذكر أيضًا أن اسم الفصل يجب ألا يكون فعلًا.
أسماء الطرق
يجب أن تكون أسماء الطرق عبارة عن أفعال ، على سبيل المثال postPayment أو deletePage أو save. يجب أن يتم تحديد معدّلات الوصول ، وفقًا لقيمها ، مع تعيين البادئة وتعيينها وفقًا لمعيار JavaBean.
قبل المتابعة ، خذ استراحة قصيرة ، واحفظ القهوة والكعك.

حسنًا ، دعنا الآن ننتقل إلى مبادئ SOLID.
كتابة التعليمات البرمجية التمسك بمبادئ الصلبة
تم تطوير هذه المبادئ من قبل العم بوب ، سوليد هو اختصار يصف مجموعة من المبادئ المصممة لكتابة كود جيد.
مبدأ المسئولية الفردية
هذا يعني أن كل فصل يجب أن يتحمل مسؤولية واحدة فقط. يجب ألا يكون هناك أكثر من سبب لتغيير الفصل. لا حاجة لإضافة كل شيء إلى فصلك ، ببساطة لأنه يمكنك القيام بذلك. تقسيم الطبقات الكبيرة إلى الأصغر وتجنب فئات الله.
مثال:
لدينا RecyclerView.Adapter مع منطق العمل داخل onBindViewHolder
class MyAdapter(val friendList: List<FriendListData.Friend>) : RecyclerView.Adapter<CountryAdapter.MyViewHolder>() { inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) { var name: TextView = view.findViewById(R.id.text1) var popText: TextView = view.findViewById(R.id.text2) } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { val friend = friendList[position] val status = if(friend.maritalStatus == "Married") { "Sold out" } else { "Available" } holder.name.text = friend.name holder.popText.text = friend.email holder.status.text = status } override fun getItemCount(): Int { return friendList.size } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_friendlist, parent, false) return MyViewHolder(view) } }
هذا يجعل RecyclerView.Adapter غير مسؤول فقط لأنه يحتوي على منطق العمل داخل onBindViewHolder. هذه الطريقة مسؤولة فقط عن إدراج البيانات في العرض.
مبدأ الانفتاح / الإغلاق (O)
يجب أن تكون كيانات البرامج مفتوحة للتوسع ، ولكن يجب إغلاقها للتعديل. هذا يعني أنه إذا كنت تقوم بتطوير الفئة A وسيريد زملاؤك تغيير الوظيفة داخل هذه الفئة. يمكنهم القيام بذلك بسهولة عن طريق توسيع هذه الفئة دون تغيير الفصل نفسه.
مثال بسيط هو الفئة RecyclerView.Adapter. يمكنك بسهولة توسيعه وإنشاء المحول الخاص بك مع سلوك غير قياسي دون تعديل RecyclerView.Adapter نفسه.
class FriendListAdapter(val friendList: List<FriendListData.Friend>) : RecyclerView.Adapter<CountryAdapter.MyViewHolder>() { inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) { var name: TextView = view.findViewById(R.id.text1) var popText: TextView = view.findViewById(R.id.text2) } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { val friend = friendList[position] holder.name.text = friend.name holder.popText.text = friend.email } override fun getItemCount(): Int { return friendList.size } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_friendlist, parent, false) return MyViewHolder(view) } }
مبدأ استبدال Barbara Lisk (L)
يجب أن يكمل الفصل الفرعي الوالد ، وليس تغييره. هذا يعني أن الفئة الفرعية يجب أن تتجاوز الأساليب الأصل التي لا تنتهك وظائف هذه الفئة الأصل. على سبيل المثال ، نقوم بإنشاء واجهة فئة تحتوي على مستمع onClick () ثم تقوم بتطبيق المستمع في MyActivity ومنحها إجراء Toast عند استدعاء onClick ().
interface ClickListener { fun onClick() } class MyActivity: AppCompatActivity(), ClickListener {
مبدأ فصل الواجهة
ينص هذا المبدأ على أن العميل يجب ألا يعتمد على الأساليب التي لا يستخدمها.
هذا يعني أنك إذا أردت كتابة الفئة "أ" وإضافة وظيفة الفئة "ب" إليها ، فلا داعي لإعادة تعريف جميع الفئات "أ" داخل الفصل "ب".
مثال: في نشاطنا ، نحتاج إلى تطبيق SearchView.OnQueryTextListener () ، لكننا نحتاج فقط إلى طريقة onQuerySubmit ().
mSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener{ override fun onQueryTextSubmit(query: String?): Boolean {
كيف نفعل هذا؟ سهل فقط قم بإنشاء رد اتصال وفصل يمتد SearchView.OnQueryTextListener ()
interface SearchViewQueryTextCallback { fun onQueryTextSubmit(query: String?) } class SearchViewQueryTextListener(val callback: SearchViewQueryTextCallback): SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { callback.onQueryTextSubmit(query) return true } override fun onQueryTextChange(query: String?): Boolean { return false } }
وهكذا نضيفها إلى وجهة نظرنا
val listener = SearchViewQueryTextListener( object : SearchViewQueryTextCallback { override fun onQueryTextSubmit(query: String?) {
أو هكذا باستخدام وظيفة التمديد في Kotlin
interface SearchViewQueryTextCallback { fun onQueryTextSubmit(query: String?) } fun SearchView.setupQueryTextSubmit (callback: SearchViewQueryTextCallback) { setOnQueryTextListener(object : SearchView.OnQueryTextListener{ override fun onQueryTextSubmit(query: String?): Boolean { callback.onQueryTextSubmit(query) return true } override fun onQueryTextChange(query: String?): Boolean { return false } }) }
val listener = object : SearchViewQueryTextCallback { override fun onQueryTextSubmit(query: String?) {
مبدأ انعكاس التبعية
الاعتماد على التجريد ، دون الاعتماد على شيء محدد.
يتكون تعريف انعكاس التبعية على العم بوب من مفهومين.
يجب ألا تعتمد وحدات المستوى العلوي على وحدات المستوى الأدنى. يجب أن يكون كلاهما مرتبطًا بالتجارب. يجب ألا تعتمد التجريدات على التفاصيل. يجب أن تعتمد التفاصيل على التجريد. يجب أن يعاد استخدامها بسهولة الوحدات النمطية عالية المستوى التي تنفذ المنطق المعقدة دون تغييرات على وحدات المستوى الأدنى. للقيام بذلك ، تحتاج إلى إدخال تجريد يفصل بين وحدات المستويات العليا والسفلى عن بعضها البعض.
مثال بسيط على هذا النمط MVP. لديك كائن واجهة يساعدك على التواصل مع فئات محددة. ما المقصود - فصول واجهة المستخدم (النشاط / الشظية) لا تحتاج إلى معرفة التنفيذ الفعلي لأساليب مقدم العرض. وبالتالي ، إذا قمت بإجراء تغييرات داخل مقدم العرض ، فليس من الضروري أن تقلق فئات واجهة المستخدم بشأن هذه التغييرات.
دعنا نلقي نظرة على مثال
interface UserActionListener { fun getUserData() } class UserPresenter : UserActionListener() {
والآن على النشاط
class UserActivity : AppCompatActivity() {
بهذه الطريقة ، نقوم بإنشاء واجهة تلخص تنفيذ مقدم العرض ، وتحتفظ فئة العرض الخاصة بنا بمرجع إلى PresenterInterface.