SOLID: mga prinsipyo, 5 panuntunan ng OOP at aplikasyon sa development

May-akda: IT Sectr Nai-publish: 2026-05-11 Oras ng pagbabasa: 10 min

SOLID — limang prinsipyo ng object-oriented programming na binuo ni Robert C. Martin (Uncle Bob) noong unang bahagi ng 2000s. Ayon sa DigitalOcean, 2024, ang SOLID ay kumakatawan sa Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation at Dependency Inversion. Ang mga prinsipyong ito ay bumubuo ng pundasyon ng Clean Architecture at ginagamit sa Android development (MVP, MVVM, Clean Architecture) at iOS (VIPER, TCA).

Mga Pangunahing Punto

  • SOLID — akronim ng limang prinsipyo ng OOP: SRP, OCP, LSP, ISP, DIP, na binuo ni Robert C. Martin para sa paglikha ng flexible at maintainable na code.
  • SRP (Single Responsibility) — bawat klase ay may isang dahilan para magbago, isang responsibilidad bawat modyul.
  • OCP (Open-Closed) — ang mga klase ay bukas para sa extension ngunit sarado para sa pagbabago, na ipinatutupad sa pamamagitan ng inheritance at polymorphism.
  • LSP (Liskov Substitution) — ang mga object ng subclass ay dapat mapalitan ang mga object ng base class nang hindi binabago ang kawastuhan ng programa.
  • ISP (Interface Segregation) — ang mga kliyente ay hindi dapat umasa sa mga interface na hindi nila ginagamit, ang mga interface ay dapat makitid at espesipiko.
  • DIP (Dependency Inversion) — ang mga module ng mataas na antas ay hindi umaasa sa mga module ng mababang antas, parehong umaasa sa abstractions.

Ano ang SOLID? Pangkalahatang-ideya ng limang prinsipyo

SOLID — isang mnemonic acronym na tumutukoy sa limang prinsipyo ng object-oriented na disenyo. Ang termino ay ipinakilala ni Robert C. Martin sa artikulong “Design Principles and Design Patterns” (2000) at kalaunan ay pinasikat sa aklat na “Agile Software Development: Principles, Patterns, and Practices” (2002). Ang SOLID ay hindi framework o library — ito ay isang koleksyon ng mga praktika na ginagawang mas menos naka-couple, mas madaling i-test at mas madaling baguhin ang code.

Ayon sa Clean Coder Blog, 2014, bawat prinsipyo ng SOLID ay lumulutas ng isang partikular na problema sa disenyo: SRP lumalaban sa mga God-class, OCP — sa mga cascading na pagbabago, LSP — sa maling inheritance, ISP — sa matatabang interface, DIP — sa mahigpit na coupling. Sama-sama sila ay bumubuo ng pundasyon ng Clean Architecture na ginagamit sa mga proyektong Android na may MVP, MVVM at MVI.

SRP: Single Responsibility Principle

Single Responsibility Principle (SRP) — prinsipyo ng iisang responsibilidad. Pormulasyon: “Ang isang klase ay dapat magkaroon lamang ng isang dahilan para magbago.” Ito ay nangangahulugan na bawat modyul o klase ay responsable para sa eksaktong isang functionality o isang domain entity. Kung ang isang klase ay namamahala sa parehong mga user at pagpapadala ng email — mayroon itong dalawang dahilan para magbago, na lumalabag sa SRP.

Ayon sa Robert C. Martin, 2002, ang SRP ay ang pinakamahalaga at kasabay na pinakamadalas na labagin na prinsipyo. Sa mobile development, ang SRP ay madalas na nilalabag sa Activity/Fragment, pinagsasama ang UI logic, navigation, network work at business logic. Solusyon — paghiwalayin ang bawat layer sa isang hiwalay na klase: ViewModel para sa UI logic, Repository para sa data, NavController para sa navigation.

Halimbawa SRP: paghahati ng UserManager

Isaalang-alang ang klase na UserManager, na naglo-load ng profile, nagse-save ng mga setting at nagpapadala ng mga email. Ito ay tatlong magkakaibang responsibilidad, bawat isa ay dapat paghiwalayin sa hiwalay na klase: UserProfileRepository (pag-load), UserSettingsStorage (pag-save) at EmailService (pagpapadala). Ang code ng kliyente (ViewModel) ay gumagamit ng lahat ng tatlo sa pamamagitan ng Dependency Injection, at bawat klase ay madaling i-test nang isolado at binago nang hindi naaapektuhan ang iba.

kotlin
// ❌ Paglabag sa SRP: Alam ng Activity ang network, DB at UI
class ProfileActivity : AppCompatActivity() {
    fun loadProfile() {
        api.getUser() // Tawag sa network
        db.saveUser()    // Pagtatrabaho sa DB
        updateUI()         // Update ng UI
    }
}

// ✅ Sinusunod ang SRP: magkahiwalay na layers
class ProfileViewModel : ViewModel() {
    private val repo = UserRepository()
    fun loadProfile() { repo.getUser() }
}

Mga tanda ng paglabag sa SRP: ang klase ay naglalaman ng higit sa 200 linya, may mga pamamaraan mula sa iba't ibang mga domain, madalas magbago para sa iba't ibang mga dahilan. Para sa Android development ang patakaran ay simple: Activity ay responsable lamang para sa lifecycle ng screen, ViewModel — para sa UI state, Repository — para sa mga data source.

SRP at microservice architecture

Ang prinsipyong SRP ay naaangkop hindi lamang sa mga klase, kundi pati na rin sa arkitektura sa antas ng serbisyo. Bawat microservice ay responsable para sa isang domain entity: UserService — mga user lamang, PaymentService — mga pagbabayad lamang, NotificationService — mga notification lamang. Ito ay nagpapahintulot sa pag-scale, pag-deploy at pag-test ng mga serbisyo nang independyente. Sa isang mobile app, ang SRP sa antas ng microservice ay nagpapakita sa paghahati ng mga API client ayon sa domain.

OCP: Open-Closed Principle

Open-Closed Principle (OCP) — prinsipyo ng bukas/sarado. Ang mga klase ay dapat bukas para sa extension (maaaring magdagdag ng bagong behavior) at sarado para sa pagbabago (ang umiiral na code ay hindi nagbabago). Nakakamit ito sa pamamagitan ng polymorphism, abstract classes at interfaces. Sa halip na magdagdag ng if-else sa isang umiiral na pamamaraan, isang bagong implementasyon ng interface ang nilikha.

Ayon sa Clean Coder Blog, 2014, ang OCP ay pinaka-epektibo sa kombinasyon sa Strategy pattern. Halimbawa, kung ang app ay sumusuporta sa iba't ibang paraan ng pagbabayad (Google Pay, Apple Pay, PayPal), hindi na kailangang magdagdag ng switch-case sa payment processor. Bawat paraan ng pagbabayad ay nag-implementa ng karaniwang interface ng PaymentGateway, at isang bagong sistema ng pagbabayad ay idinadagdag bilang isang bagong klase nang hindi binabago ang umiiral na code.

kotlin
// ✅ OCP: bukas para sa extension, sarado para sa pagbabago
interface PaymentGateway {
    fun processPayment(amount: Double): Boolean
}

class GooglePayGateway : PaymentGateway {
    override fun processPayment(amount: Double) = true
}

// Bagong sistema ng pagbabayad — nang hindi binabago ang umiiral na code
class ApplePayGateway : PaymentGateway {
    override fun processPayment(amount: Double) = true
}

LSP: Liskov Substitution Principle

Liskov Substitution Principle (LSP) — prinsipyo ng substitution ni Barbara Liskov. Kung ang S ay subtype ng T, ang mga object ng T ay maaaring palitan ng mga object ng S nang hindi binabago ang mga katangian ng programa. Pormal: ang isang function na gumagamit ng base class ay dapat gumana nang tama sa anumang subclass nito. Kung ang subclass ay nag-throw ng exception kung saan ang base class ay hindi — ang LSP ay nilabag.

Ayon sa Robert C. Martin, 2002, ang LSP ay ang pinakamahirap na prinsipyo ng SOLID na maunawaan. Klasikong halimbawa ng paglabag — ang klase na Square (parisukat) na nagmamana mula sa Rectangle (parihaba). Kung ang setWidth para sa Square ay nagtatakda ng parehong lapad at taas, ang client code na umaasang behavior ng Rectangle ay makakakuha ng hindi inaasahang resulta. Sa mobile development, ang LSP ay madalas na nilalabag sa pagmamana ng ViewModel, kapag ang child ViewModel ay nagdagdag ng mga mandatoryong dependensya.

kotlin
// ❌ Paglabag sa LSP: Sinira ng Square ang behavior ng Rectangle
open class Rectangle(open var width: Int, open var height: Int)

class Square(side: Int) : Rectangle(side, side) {
    override var width
        get() = super.width
        set(value) { super.setBoth(value, value) }
}

ISP: Interface Segregation Principle

Interface Segregation Principle (ISP) — prinsipyo ng paghihiwalay ng interface. Ang mga kliyente ay hindi dapat umasa sa mga interface na hindi nila ginagamit. Sa halip ng isang “matabang” interface, gumawa ng ilang makitid at specialized na interface. Kung ang isang klase ay nag-implementa ng isang interface ngunit ang bahagi ng mga pamamaraan ay nag-throw ng UnsupportedOperationException o nananatiling walang laman — ito ay malinaw na tanda ng paglabag sa ISP.

Ayon sa DigitalOcean, 2024, ang ISP ay lalong nauugnay sa mobile development sa pagdidisenyo ng ViewModel at Repository. Sa halip ng isang UserRepository interface na may lahat ng CRUD method, mas mainam na gumawa ng QueryUserRepository (basahin lamang) at CommandUserRepository (sumulat). Kung gayon ang bumabasang client (UI element) ay umaasa lamang sa Query interface at hindi alam ang tungkol sa mga pamamaraan ng pagsulat.

kotlin
// ❌ Matabang interface — napipilitan ang client na mag-implementa ng hindi kailangang pamamaraan
interface UserOperations {
    fun getUser(id: String): User
    fun saveUser(user: User)
    fun deleteUser(id: String)
    fun exportUsers(): File
}

// ✅ ISP: magkahiwalay na interfaces
interface UserReader { fun getUser(id: String): User }
interface UserWriter { fun saveUser(user: User) }
interface UserDeleter { fun deleteUser(id: String) }

DIP: Dependency Inversion Principle

Dependency Inversion Principle (DIP) — prinsipyo ng pagbabaligtad ng dependensya. Ang mga module ng mataas na antas ay hindi dapat umasa sa mga module ng mababang antas. Parehong antas ay dapat umasa sa abstractions (interfaces). Ang mga abstraction ay hindi dapat umasa sa mga detalye — ang mga detalye ay umaasa sa abstractions. Ito ay hindi pareho sa “Dependency Injection” (DI), bagaman ang DI ay isang karaniwang paraan upang maipatupad ang DIP.

Ayon sa Robert C. Martin, 2019, ang DIP ay batayan ng Clean Architecture. Ang ViewModel (mataas na antas) ay hindi dapat direktang gumawa ng instance ng RetrofitApi (detalye). Sa halip, ang ViewModel ay umaasa sa UserRepository interface, at ang konkretong implementasyon na UserRepositoryImpl na may Retrofit ay ipinapasa sa pamamagitan ng constructor. Sa Android, ang DIP ay ipinatutupad sa pamamagitan ng Hilt/Dagger o Koin: lahat ng dependensya ay ibinibigay sa pamamagitan ng DI container.

kotlin
// ✅ DIP: Module ay umaasa sa abstraction, hindi sa detalye
class UserRepositoryImpl(
    private val api: UserApi,   // Umaasa sa interface
    private val db: UserDao     // Umaasa sa interface
) : UserRepository {

    override suspend fun getUser(id: String): User {
        return api.fetchUser(id)
    }
}

// Hilt DI: ang mga detalye ay konektado sa pamamagitan ng DI module
@Module
object NetworkModule {
    @Provides
    fun provideUserApi(retrofit: Retrofit): UserApi =
        retrofit.create(UserApi::class.java)
}

Paglalapat ng SOLID sa mobile development

SOLID sa mobile development ay inilalapat sa lahat ng antas: mula sa arkitektura ng app hanggang sa indibidwal na mga klase. Sa mga proyekto ng Android, hinahati ng Clean Architecture ang code sa tatlong layer: domain (business logic — independyente sa frameworks), data (repositories, API, DB) at presentation (UI, ViewModel). Ang domain layer ay gumagamit ng mga prinsipyo ng SOLID: use case (SRP), repository interfaces (DIP), entity classes (OCP + LSP).

Ayon sa Android Developers Guide, 2025, ang SRP sa Android ay nagpapakita sa paghahati ng ViewModel, Repository at Mapper. OCP — sa pagdaragdag ng mga bagong data source sa pamamagitan ng DataSource interface. LSP — sa pare-parehong pagproseso ng Result mula sa iba't ibang repositories. ISP — sa CQRS approach (paghihiwalay ng Read/Write repositories). DIP — sa pamamagitan ng Hilt/Koin para sa dependency injection.

PrinsipyoProblema kung wala itoSolusyon sa mobile project
SRPActivity na 1000+ linyaViewModel + UseCase + Repository
OCPswitch-case ayon sa uri ng pagbabayadStrategy: PaymentGateway interface
LSPBug sa pagpapalit ng BaseViewModelPagsusuri ng kontrata ng mga subclass
ISPUnsupportedOperationExceptionPaghihiwalay ng Reader / Writer
DIPViewModel manually gumagawa ng RetrofitHilt / Koin DI container

Mga karaniwang pagkakamali sa paglalapat ng SOLID

Mga pagkakamali sa SOLID ay kadalasang nauugnay sa labis na pagiging komplikado ng code. Una — literal na pagsunod sa mga prinsipyo nang hindi isinasaalang-alang ang konteksto. Ang paghahati ng isang UserService klase sa 10 interfaces at 15 klase para sa “malinis” na ISP ay overengineering. Ang SOLID ay isang kasangkapan, hindi layunin. Pangalawang pagkakamali — pagkalito sa pagitan ng SRP at “isang pamamaraan = isang responsibilidad”. Ang isang klase ay maaaring magkaroon ng maraming pamamaraan kung lahat sila ay kabilang sa isang lugar ng responsibilidad.

Ayon sa Simple Thread, 2024, pangatlong pagkakamali — pagbalewala sa LSP sa pagmamana ng ViewModel sa Android. Kung ang base ViewModel ay umaasa ng LiveData at ang anak ay gumagamit ng StateFlow — ang client code na naka-subscribe sa LiveData ay hindi makakatanggap ng mga update. Pang-apat — paglabag sa DIP para sa pag-test: RepositoryImpl ay direktang gumagawa ng instance ng OkHttpClient, na ginagawang imposible ang unit testing.

Gintong panuntunan: ilapat ang SOLID kapag lumulutas ito ng tunay na problema (madalas na pagbabago, kahirapan sa pag-test, pagdoble). Para sa simpleng CRUD screens, ang mahigpit na pagsunod sa lahat ng limang prinsipyo ay labis. Para sa business logic, financial calculations at API interactions, ang SOLID ay sapilitan.

Koneksyon ng SOLID at Clean Architecture

Clean Architecture (Robert C. Martin, 2012) — direktang paglalapat ng SOLID sa antas ng mga layer ng app. Ang SRP ay tumutukoy sa mga hangganan ng use case (bawat use case — isang klase). Ang OCP ay ipinatutupad sa pamamagitan ng repository interfaces (ang Data layer ay maaaring magbago nang hindi binabago ang Domain). Ang ISP ay nagbibigay ng paghahati ng Use Case sa input/output boundary. Ang DIP — direksyon ng mga dependensya papasok ng Domain layer. Ang LSP ay ginagarantiyahan na bawat implementasyon ng repository ay mapapalitan nang hindi sinisira ang use case.

Mga Madalas Itanong

Ano ang SOLID sa simpleng salita?

SOLID — limang panuntunan ng pagsulat ng code upang madaling baguhin, i-test at maunawaan. Bawat letra ay isang prinsipyo: huwag sumulat ng malalaking klase (SRP), huwag baguhin ang umiiral na code — magdagdag ng bago (OCP), huwag sirain ang behavior ng mga tagapagmana (LSP) at iba pa.

Aling prinsipyo ng SOLID ang pinakamahalaga?

SRP (Single Responsibility) ay itinuturing na pinakamahalaga dahil ang paglabag nito ay humahantong sa God-class — malalaking klase na mahirap i-test at baguhin. Gayunpaman, nang walang DIP (Dependency Inversion) ang code ay nananatiling mahigpit na naka-couple, na kritisyal din.

Ang SOLID ba ay sapilitan para sa mobile development?

Hindi sapilitan, ngunit lubos na inirerekomenda para sa komersyal na mga proyekto na may mahabang lifecycle. Para sa simpleng mga app (isang screen, walang business logic) ang SOLID ay maaaring labis. Para sa mga proyekto na may 50+ screen at 3+ developer, ang SOLID ay kinakailangang minimum.

Ano ang mangyayari kung hindi susundin ang SOLID?

Mga resulta: ang mga klase ay nagiging “mataba” (1000+ linya), ang pagbabago sa isang lugar ay sumisira sa tatlong iba pa, imposibleng sumulat ng mga unit test, ang pagdaragdag ng bagong feature ay tumatagal ng mga linggo. Sa paglipas ng panahon, ang code ay nagiging “Big Ball of Mud” — gusot at marupok.

Paano suriin kung ang SOLID ay sinusunod sa proyekto?

Mga tanda ng pagsunod: bawat klase ay mas mababa sa 200 linya, ang pagbabago ng feature ay hindi nakakaapekto sa 5+ file, ang mga test ay isinusulat nang hindi nagmo-mock ng 10 dependensya, ang bagong developer ay nauunawaan ang istraktura sa isang araw. Ang mga tool tulad ng SonarQube at detekt ay tumutulong na matukoy ang mga paglabag sa SRP at DIP.

Buod

  • SOLID — limang prinsipyo ng OOP (SRP, OCP, LSP, ISP, DIP) para sa flexible at maintainable na code
  • SRP — bawat entity ay responsable para sa isang gawain, nilulutas ang problema ng God-class
  • OCP — extension sa pamamagitan ng polymorphism, hindi pagbabago ng umiiral na code
  • LSP — ang mga tagapagmana ay hindi dapat sirain ang behavior ng base class
  • ISP — makitid na interface sa halip ng universal “Swiss knife”
  • DIP — pag-asa sa abstractions, injection sa pamamagitan ng Hilt/Koin sa Android
  • SOLID ay sapilitan para sa Clean Architecture at komersyal na mobile projects

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din