Our SuccessKnowledges
NEXTZY Logo
Crews
Chat
Talk with Team
NEXTZY Logo
NEXTZY
Chat
Home>Knowledges

ขึ้น Project Structure เพื่อใช้งานในโปรเจคขนาดใหญ่

Share:

ขึ้น Project Structure เพื่อใช้งานในโปรเจคขนาดใหญ่

Table of contents

  • การขึ้นโปรเจคแบบเก่า
  • การขึ้นโปรเจคแบบใหม่
  • 1. สร้างโปรเจคใหม่
  • 2. เขียนโค้ดเพิ่มใน setting.gradle
  • 3. ย้าย Library / Module ไปไว้ใน folder ที่ต้องการ
  • 4. เพิ่ม Gradle Script
  • 5. build.gradle ของ Application
  • เพิ่มเติม
  • สรุป
Nonthawit

Nonthawit

CEO | Engineer | Designer

VIEW

10.4k

CATEGORY

Technical

LAST UPDATED

April 20, 2018

Nonthawit

Nonthawit

CEO | Engineer | Designer

VIEW

10.4k

CATEGORY

Technical

LAST UPDATED

April 20, 2018

การขึ้นโปรเจคแบบเก่า

1. สร้างโปรเจคใหม่

2. นำ library ต่างๆที่เราต้องการมาใส่ใน project

ในตัวอย่างเรามีอยู่ 5 module ด้วยกันคือ

  1. app : เป็นส่วนของ application ของเรา
  2. common : ไว้เป็นที่รวมของ base class ทั้งหลาย ไม่ควรเอา business logic มาใส่ไว้ในนี้เพราะ module นี้ project อื่นๆสามารถนำไป reuse ใช้ต่อได้ เช่น BaseActivity/BaseFragment เป็นต้น
  3. commonapplication : ไว้เป็นที่รวมของ class ระดับ application ของเราเอง ซึ่ง Business logic เราจะใส่ไว้ในนี้แทน (เดี๋ยวอธิบายเพิ่มเติมให้ตอนหลังเนาะ)
  4. library1
  5. library2

แค่นี้ก็เป็นอันเสร็จ สามารถเขียนโค้ดได้แล้ว 😇

แต่เดี๋ยววว….. ทำไมเราต้องมาจัด project structure กันใหม่หละ?

คำถามต่างๆก็แล่นเข้ามาในหัว

  • ถ้าเป็น project ขนาดใหญ่หละ?
  • ถ้ามีคนดูแล project นี้หลายคนหละ?
  • ถ้า class มันเป็นร้อยๆ พันๆหละ?
  • ถ้าเรามีซัก 10 module 10 library หละ? 😱

มันจะจัดการและดูยากมากคับ การทำงานกับ project structure แบบด้านบนเริ่มไม่ตอบโจทย์ซักเท่าไหร่

เป็นที่มาของบล็อกในวันนี้ เราจะมาทำให้ clean และรองรับการ scale ในอนาคต

งั้นเรามาดูการขึ้นโปรเจคแบบใหม่กันดีกว่า

การขึ้นโปรเจคแบบใหม่

1. สร้างโปรเจคใหม่

ขั้นแรกทำเหมือนเก่าทุกอย่าง

2. เขียนโค้ดเพิ่มใน setting.gradle

include ":app", ":Common", ":CommonApplication", ... (แบบเก่า)

จะเห็นว่าจะต่างจาก setting.gradle อันเก่าอย่างสิ้นเชิง แล้วดีกว่าแบบเก่ายังไง

  • includeFlat : ทำให้เราสามารถนำ library / module มาไว้ใน folder ที่ต้องต้องการได้ในที่นี้คือชื่อ “TabCommon”

  • เราสามารถตั้งชื่อให้โปรเจคเราได้ด้วย ถ้า build apk มันก็เปลี่ยนให้ด้วยนะ จะได้ไม่สับสนกับแอปอื่นเวลา build ออกมา ในที่นี้เปลี่ยนชื่อจาก app เป็น “AppProjectStructure”

  • เรากำหนด path ของ libray / module ได้ตามใจเลยว่าอยากวางไว้ที่ไหน เพื่อให้สะดวกต่อการเข้าถึง

3. ย้าย Library / Module ไปไว้ใน folder ที่ต้องการ

ย้าย librayry / module จากแบบเดิมให้มาเป็นแบบนี้แล้วลองกด build gradle ดูใหม่ได้เลย

แค่นี้ก็เริ่มดูง่าย เป็นระเบียบชัดเจนกว่าแบบเดิมแล้ว 😇

4. เพิ่ม Gradle Script

เขียน gradle script เพิ่มดังนี้

  • applyCommon.gradle

เป็น script ที่เราจะเอาไปใส่ทุก build.gradle ในแต่ละ library / module เราจะได้ไม่ต้องเขียนโค้ดซ้ำๆกันให้เสียเวลา เวลาจะแก้ไขก็แก้ไขที่เดียวได้เลย

EXTRA: script ด้านบนจะเปลี่ยน java folder เป็น kotlin folder ด้วยนะ เพื่อความเท่ของโปรเจค

  • config.gradle

NOTE: def config = ext.config ต้องใส่บรรทัดนี้ด้วยนะ ไม่งั้นเราจะเรียกใช้ไม่ได้

config.gradle เป็นตัวจัดการเกี่ยวกับ version ของ library ต่างๆ ที่ library / module อื่นใช้เหมือนกัน

เราสามารถเรียกใช้แบบนี้ได้เลยในทุก libray / module คราวนี้พวก version ต่างๆก็สามารถแก้ที่เดียวได้เลย สะดวกมาก

  • improveSpeed.gradle

เป็น script ที่ใช้เพื่อลดเวลา build gradle ลงวิธี setup ตามนี้

Preferences ==> Compiler ==> Command-line Option -PdevBuild

เพราะเวลาเราอยู่ใน Build Variant ที่เป็น debug เราไม่จำเป็นต้อง enable ของพวกนี้

splits.abi.enable = false
splits.density.enable = false
aaptOptions.cruncherEnabled = false

และเรายังสามารถกำหนด spec การ build gradle ของแต่ละเครื่องได้ด้วยโดยใช้ productFlavors ตัวอย่างในที่นี้

ทำไว้ให้เครื่องที่ API 21 ขึ้นไปจะได้ไม่ต้องเสียเวลา build multidex เข้าไปด้วย

flavors ชื่อ: "minApi21" (ชื่ออะไรก็ได้แล้วแต่จะตั้ง)
minApi21 {            
dimension "minApi"
minSdkVersion 21
versionNameSuffix "-minApi21"
applicationIdSuffix ".min21"
}

ผลคือถ้าไป build gradle กับเรื่องที่ API 21 ขึ้นจะเร็วกว่าปกติครับ เพราะไม่ติดเรื่อง multidex ของ API version เก่าให้เสียเวลา

EXTRA: Speeding Up Your Android Gradle Builds (Google I/O ‘17)

5. build.gradle ของ Application

เนื่องจากเราแยก buildType ไว้ 2 แบบ คือ debug และ release เราจึงแยกไฟล์ proguard ไว้ด้วย

rules-proguard.pro
rules-proguard-debug.pro

release : ตรงไปตรงมา

minifyEnabled true            
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), "$project.rootDir/tools/rules-proguard.pro"

debug: ใส่ suffix ไว้เพื่อให้ build debug กับ release เป็นคนละแอปกัน

versionNameSuffix “ Debug” 
applicationIdSuffix “.debug”
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), “$project.rootDir/tools/rules-proguard-debug.pro”

signingConfigs สำหรับของ release

ให้ใส่ใน gradle.properties ตัวกลางที่อยู่ใน root directory ของ user นั้นๆในเครื่องเรา

MAC: Users/<YOUR_USER>/.gradle/gradle.properties
KEYSTORE_PASSWORD=<YOUR_PASSWORD>
KEYSTORE_FILE=<YOUR_KEY_PATH>
KEYSTORE_ALIAS=<YOUR_ALIAS>

NOTE: ทุกโปรเจคสามารถใช้ KEYSTORE_PASSWORD, KEYSTORE_FILE และ KEYSTORE_ALIAS ได้ด้วยนะ ถ้าเราใส่ไว้ใน gradle.properties ตัวกลาง

NOTE 2: หรือจะไว้ใน gradle.properties ของแต่ละโปรเจคก็ได้ แต่อย่างลืมใส่ .gitignore หละ

แค่นี้ก็เป็นอันเสร็จแล้ว เยอะนิดหน่อยแต่สบายในภายภาคหน้าครับ 🤩

เพิ่มเติม

Debug vs Release

แยกไว้เพื่อต้องการแยกโค้ด debug และ release ออกจากกัน

วิธีบ้านๆเราจะชอบใช้แบบนี้กัน

if( BuildConfig.DEBUG == true ){
// do something
}

เราไม่แนะนำถ้าเป็นโค้ดชุดใหญ่ๆ และเรามีสิทธิ์ที่จะพลาดเผลอเอาโค้ดใน debug ไปรันใน release ได้ซึ่งมันก็คือ production นะ 😱

ข้อดีของการแยกแบบนี้

  • เราสามารถแยกโค้ด debug กับ release ออกจากกันได้อย่างชัดเจน
  • สามารถเปลี่ยนชื่อแอปตอน build debug และ release ให้ต่างกันได้ด้วย โดยการไปแก้ string.xml ของแต่ละ folder เช่น
debug: "Structure Debug"
release: "Structure"
  • เปลี่ยน launcher ก็ยังทำได้

Common Module vs CommonApplication Module

สองตัวนี้เราจะเลือกวางโค้ดไว้ที่ module ไหน?

สำหรับตัว Common Module จะไว้วางโค้ดที่โปรเจคอื่นสามารถ resuse เอาไปใช้ได้เลย นั่นหมายความต้องไม่มี business logic ใดๆทั้งสิ้นเป็นแค่ Base Class จริงๆ

ถ้าโค้ดชุดไหนที่เราต้องมี business logic ปนอยู่หรือคิดว่าโปรเจคอื่นไม่น่าจะใช้ได้ให้วางไว้ที่ CommonApplication Module แทนครับ แล้วโปรเจคเราจะเป็น layer ที่สวยงามจัดการง่ายทันที

โครงสร้างสมมุติจึงเป็นแบบนี้

สรุป

การวาง Project Structure แบบใหม่ก็เพื่อรองรับการ scale ของแอปเราในอนาคต ทั้งทีมเอย requirement ใหม่ๆเอย รู้ตัวอีกทีก็อาจจะเป็นดินพอกกันไปเรื่อยๆแล้วจะกลับมาแก้ก็ลำบากกกก เราจึงต้องวางแผนไว้ตั้งแต่ตอนเริ่มขึ้นโปรเจคใหม่ครับ

บล็อกนี้น่าจะช่วยเป็น guildeline สำหรับคนที่กำลังจะขึ้นโปรเจคใหม่ หรืออยากจะเปลี่ยน Project Structure ของตัวเองใหม่

ทั้งหมดที่เราพูด จึงได้ตัวอย่าง Project Structure แบบใหม่ออกมาสวยงามแบบนี้ 😎

วันนี้พอแค่นี้เจอกันบล็อกหน้าเนาะ 😎

เข้าไปติดตามกันได้ https://www.facebook.com/thekhaeng.io/

อย่าลืม share ให้มนุษย์ Android คนอื่นด้วยหละ 😎

Share:

KNOWLEDGE

Related Articles

เข้าใจการทำ Selector แบบ Ripple effect
Nonthawit

Nonthawit

CEO | Engineer | Designer

เข้าใจการทำ Selector แบบ Ripple effect

20 สิ่ง ที่ได้หลังจากเป็น Android developer ที่ Nextzy 3 เดือน
Nonthawit

Nonthawit

CEO | Engineer | Designer

20 สิ่ง ที่ได้หลังจากเป็น Android developer ที่ Nextzy 3 เดือน

บทความนี้แชร์ประสบการณ์ 3 เดือนแรกของการทำงานเป็น Android Developer ที่ Nextzy ครอบคลุมทั้งด้าน technical เช่น MVP architecture, Android Lifecycle, ProGuard, Git workflow และการเขียน Unit Test รวมถึงด้าน soft skill อย่างการสื่อสารกับทีม, การแชร์ความรู้, และการเขียนโค้ดให้ readable และยืดหยุ่น นอกจากนี้ยังสะท้อนวัฒนธรรมองค์กรที่เน้นทีมเวิร์ค การ review โค้ด และบรรยากาศการทำงานที่สนุกสนาน ซึ่งล้วนช่วยลด learning curve และพัฒนาทักษะได้เร็วกว่าการเรียนรู้คนเดียว

[Tip/Trick] วิธีติดต่อกับ WebView ผ่าน JavascriptInterface มันเท่มาก
Nonthawit

Nonthawit

CEO | Engineer | Designer

[Tip/Trick] วิธีติดต่อกับ WebView ผ่าน JavascriptInterface มันเท่มาก

NEXTZY Logo
NEXTZY
48/27 Ratchadaphisek Rd, Samsen Nok, Huai Khwang, Bangkok 10310

Base at Thailand

Thailand

Home

Crews

Success

Download press kits

Knowledges

Chat

Talk with team

SCHEDULE