درک clean code در اندروید


قبل از شروع کدنویسی بهتر است بدانید چطور کد خود را مدیریت کنید و چطور کد خود را مقیاس پذیر کنید

همون طور که عمو باب توی کتاب میگه(نویسنده کتاب مشهور clean code معروف به عمو باب ):

شما این مقاله رو به دو دلیل میخوانید:اول اینکه شما برنامه نویس هستید و دوم اینکه میخواهید برنامه نویس بهتری بشید.(Robert C. Martin )

همونطور که ایشون میگه تصور کنید توی کتابخانه ای هستید و دارید به چند تا کتاب نگاه میکنید. اگر کتابخانه کتاب هاش رو مدیریت و دسته بندی کرده باشه شما سریعتر کتاب مورد نظرتون رو پیدا میکنید. به علاوه طراحی داخلی خوب باعث میشه وقتی دنبال کتاب میگردید احساس راحتی کنید.

مثل نوشتن کتاب, اگر میخواهید چیز فوق العاده ای بسازید باید بدونید چطور بنویسید و چطور کدتون رو تر و تمیز سازماندهی کنید. اگه تیم دارید یا کسی غیر از شما کدتون رو میبینه کافیه به اسم متغیر ها و کلاس ها و پکیج ها نگاه کنه تا برنامه رو درک کنه.

کد تمیز چیست؟

اینکه کارتون رو سریعتر تموم کنید ولی کسی نتونه کد شما رو بخونه اصلا خوب نیست چون خودش یه بدهی فنی محسوب میشه.

کد شما تمیز محسوب میشه اگه هرکسی در تیم شما بتونه راحت درکش کنه. کد تمیز میتونه توسط بقیه توسعه دهنده ها خوانده و توسعه داده بشه. با قابل فهم بودن, خوانایی, تغییرپذیری, توسعه پذیری و قابلیت نگهداری هم میاد.

-- باید بهش اهمیت بدم؟

دلیل اینکه باید بهش اهمیت بدید اینه که کد شما , خط فکری شما رو به دیگران توضیح میده.این دلیلیه که به خاطرش باید به افزایش خوانایی, زیبایی و سادگی کدتون فکر کنید.

مشخصات کد تمیز:

اگر کد شما مشخصات زیر را داشت بدانید و اگاه باشید که تمیز است.

  • کد شما زیبا است: کد شما باید مثل گوش دادن به اهنگ های محسن چاوشی یا یه ماشین خوش ساخت شما رو وادار به لبخند زدن کنه.
  • کد شما مورد مراقبت قرار گرفته باشد:وقت صرف کنید که کدتون رو ساده و متظم نگه دارید. به جزییات اهمیت دهید و از ان نگهداری کنید.
  • کد شما متمرکز و هدفمند است:هر تابع، هر کلاس و هر ماژول باید از یک خط فکری مشخص پیروی کند که با جزییات پیرامون ان , غیر قابل فهم و کثیف نشده باشد.
  • از تکرار کد پرهیز کرده باشد.
  • همه تست ها را پاس کند.
  • تعداد تابع ها و کلاس ها در آن به حداقل رسیده باشد.

یک فرق برنامه نویس باهوش و برنامه نویس حرفه این است که, حرفه ای میداند تمیزی و نظم حرف اول را میزند.حرفه ای ها از قدرتشان خوب استفاده میکنند و کدی مینویسند که دیگران هم آنرا بفهمند.

از اسم های با معنا استفاده کنید:

انتخاب اسم خوب زمان میبرد ولی بیشتر از چیزی که میگیرد , برمیگرداند. اسم متغیر ها و تابع ها و کلاس ها باید به همه سوالات بزرگ جواب دهد.باید بگوید چرا وجود دارد, چه کاری انجام میدهد و چطور استفاده میشود.اگر اسمی نیاز به کامنت و توضیح داشت نیت خود را به خوبی مشخص نمیکند.

بیایید چند مثال ببینیم.

--اسم کلاس ها

کلاس ها و اشیا (objects) باید اسم یا اسم-عباراتی(اسمی که از چند کلمه تشکیل شده) مثل Customer, WikiPage, Account, و AddressParser داشته باشند. از کلماتی مثل Manager, Processor, Data, یا Info در اسم کلاس استفاده نکنید. اسم کلاس نباید فعل باشد.

--اسم تابع ها

اسم تابع ها باید فعل باشد مثل:postPayment, deletePage, یا save. و Accessors, mutators, و predicates(مثل getter ها و setter ها) باید بر اساس مقدارشون نامگذاری شوند و پیشوند های get و set و هرچیزی مطابق استاندارد javabean داشته باشند.

— Use Problem Domain Names

When there is no “programmer-eese” for what you’re doing, use the name from the problem domain. At least the programmer who maintains your code can ask a domain expert what it means.(اینو خودم نفهمیدم ولی گذاشتم که بهم توضیح بدید)

کدتون رو بر اساس اصول S.O.L.I.D بنویسید.

این اصل توسط خود Robert C. Martin (عمو باب) ساخته شده. SOLIC مجموعه اصولی است که کد خوب رو توصیف میکنه.

اصل Single Responsibility --اصل تک وظیفگی (SRP) :

یعنی هر کلاس باید فقط یک مسعولیت داشته باشه. هرگز یک کلاس نباید بیش از یک دلیل برای به وجود اومدن داشته باشه.فقط چون میتونی هر چی دلت خواست به کلاس اضافه کنی به این معنی نیست که باید اینکارو انجام بدی. کلاس های بزرگ رو به کلاس های کوچک تر تقسیم کن و از GOD کلاس ها دوری کن.

به عنوان مثال:

فرض کنید یک RecyclerView.Adapter داریم که بخشی از منطق برنامه(حالا هر چیزی به غیر از Bind کردن اطلاعات) رو توی onBindViewHolder مشخص شده.

این باعث میشه که RecyclerView.Adapter بیشتر از یک مسعولیت داشته باشه. این تابع فقط مسعول اینه که اطلاعات جدید رو بده به view و اونا رو bind کنه.

اصل Open-Closed -- اصل باز و بسته بودن (OCP) :

اجزا نرم افزار(کلاس,متد) باید برای گسترش ازاد و برای تغییر محدود باشه. یعنی مثلا اگر کلاسی به اسم A داشته باشیم و هم تیمی شما بخواد توی یکی از تابع های توی A تغییری ایجاد کنه میتونه با extend کردن Aاینکارو انجام بده به جای اینکه تو کلاس اصلی تغییر ایجاد کنه.

یک مثال ساده همین کلاس RecyclerView.Adapter است. خیلی راحت میتونید با ارث بری کردن(extend) , آداپتر مخصوص خودتون با رفتار دلخواه بسازید بدون اینکه نیاز به تغییر RecyclerView.Adapter داشته باشید.

اصل Liskov Substitutions -- اصل جانشینی لیسکف (LSP):

کلاس فرزند(child classes) هیچوقت نباید از تعریف کلاس پدر(parent class) سرپیچی کند.(یا یه همچین چیزی)

یعنی زیرکلاس باید متد هایی از کلاس پدر رو override کنه که از توانایی های کلاس پدر فراتر نره. برای مثال, یک interface داریم که متد () داره. بعد از توی MyActivity استفاده میکنیم به طوری که یک toast نمایش میدهد.


interface ClickListener {
    fun ()
}
class MyActivity: AppCompatActivity(), ClickListener {

    //........
    override fun () {
        // Do the magic here
        toast(&quotOK button clicked&quot)
    }
}

***میدونم یکم پیچیده شد. یکم تو اینترنت براش وقت بگذارید.

اصل Interface Segregation:

این اصل بیان میکند که امکانات و متد هایی که به مشتری(client) مربوط نیست و از انها استفاده نمیکند , نباید به مشتری تحمیل کرد.

یعنی اگر بخواهید کلاس A را بسازید و اون رو توی یه کلاس دیگه implement کنید( کلاس B), نباید همه متد های A رو توی کلاس override , B بشه. برای اینکه اونو تر و تمیز در بیاریم.

مثال: توی اکتیویتون نیاز به implement کردن SearchView.OnQueryTextListener() دارید و فقط به متد onQuerySubmit نیاز دارید.


فقط لازمه یه callback بسازید و کلاسی که از SearchView.OnQueryTextListener() ارث بری میکند.

اصل Dependency Inversion :

به انتزاعات بستگی داره. به ارتباطات بستگی نداره

عمو باب میگه این اصل از دو بخش تشکیل شده:

  • متد های High-level نباید به متد های low-level بستگی داشته باشد. هر دو باید به انتزاعات وابسته باشند.
  • انتزاعات نباید به جزییات وابسته باشند. جزییات باید به انتزاعات بستگی داشته باشد.

متد های high-level که منطق پیچیده ای را به دوش میکشند باید قابلیت باز استفاده داشته باشند و از متد های low-level تاثیر نپذیرند. برای انجام اون باید ابتدا انتزاعی ایجاد کنید که متد های high-level و low-level رو از هم جدا کنه.

منبع: Medium