{"id":16962631,"url":"https://github.com/jrvansuita/solidkotlin","last_synced_at":"2025-06-16T11:37:58.105Z","repository":{"id":49821900,"uuid":"516191309","full_name":"jrvansuita/SolidKotlin","owner":"jrvansuita","description":"SOLID study using Kotlin 👨‍🏫","archived":false,"fork":false,"pushed_at":"2022-07-27T01:00:37.000Z","size":89,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-21T16:24:30.196Z","etag":null,"topics":["codelab","kotlin","solid","study"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jrvansuita.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-21T01:59:39.000Z","updated_at":"2022-10-05T17:19:36.000Z","dependencies_parsed_at":"2022-09-17T05:41:30.750Z","dependency_job_id":null,"html_url":"https://github.com/jrvansuita/SolidKotlin","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jrvansuita/SolidKotlin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrvansuita%2FSolidKotlin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrvansuita%2FSolidKotlin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrvansuita%2FSolidKotlin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrvansuita%2FSolidKotlin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jrvansuita","download_url":"https://codeload.github.com/jrvansuita/SolidKotlin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrvansuita%2FSolidKotlin/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260151342,"owners_count":22966498,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codelab","kotlin","solid","study"],"created_at":"2024-10-13T23:07:23.254Z","updated_at":"2025-06-16T11:37:58.083Z","avatar_url":"https://github.com/jrvansuita.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [Solid](https://simple.wikipedia.org/wiki/SOLID_(object-oriented_design)) Principles using Kotlin\n\nS.O.L.I.D. an acronym of a group of five good principles in object-oriented programming.\nHere are some classes I've implemented to study every SOLID principle using Kotlin. \n\n- **S** ingle Responsibility Principle (known as SRP)\n- **O** pen/Closed Principle\n- **L** iskov’s Substitution Principle\n- **I** nterface Segregation Principle\n- **D** ependency Inversion Principle\n\n\n\u003e *This is my pont-of-view, my understanding about the principles. It's my personal study shared on github.*\n\n-------\n\n### Study\n\n- [**S**ingle Responsibility ](/src/main/kotlin/SingleResponsibility.kt)\n```kotlin\n//A class should have only one reason to exists and responsible for one thing.\nclass SingleResponsibility {\n\n    /* ❌ Violation Example  */\n    //This class handles way too much\n\n    class SessionHandler {\n        fun startSession(user: User) = println(\"Starting ${user.name} session with ${user.id} id.\")\n        \n        fun activateUserAccount(user: User) = println(\"Activating ${user.name}.\")\n        \n        fun checkAccessRights(user: User) = println(\"Checking ${user.name} access.\")\n    }\n    \n    /* ✅ Correct Example */\n    //Now we can clearly see that each class is responsible for exactly one thing\n\n    class Session {\n        fun start(user: User) = println(\"Starting ${user.name} session with ${user.id} id.\")\n    }\n\n    class UserAccount {\n        fun activate(user: User)  = println(\"Activating ${user.name}.\")\n    }\n\n    class AccessRights {\n        fun check(user: User) = println(\"Checking ${user.name} access.\")\n    }\n}\n```\n- [**O**pen–Closed ](/src/main/kotlin/OpenClose.kt)\n```kotlin\n//Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.\nclass OpenClose {\n\n    /* ❌ Violation Example  */\n    // Will to work only with MySqlConnection\n\n    class DataBase {\n        private val connection = MySqlConnection(\"any\")\n        \n        fun connect() = println(\"Connect to Database using ${connection.uri}\")\n    }\n    \n    /* ✅ Correct Example */\n    //Extending and provide any implementation of Connection. It can be MySql, Firebird, Oracle, Sql Server, etc...\n\n    open class DataBase(private val connection: Connection) {\n        fun connect()  = println(\"Connect to Database using ${connection.uri}\")\n    }\n}\n```\n- [**L**iskov Substitution ](/src/main/kotlin/LiskovSubstitution.kt)\n```kotlin\n// All classes deriving from the base class should behave in the same manner as the superclass.\n// If we decide to replace the base class with the derived one, it should not break the existing functionality.\n class LiskovSubstitution {\n\n    interface Animal {\n        fun walk()\n        fun fly()\n    }\n\n    /* ❌ Violation Example  */\n    //Dog and Goose are animals, but Dog can't fly! Will break fly implementation.\n\n    class Dog : Animal {\n        override fun walk() = println(\"The dog is walking\")\n        override fun fly() = throw RuntimeException(\"The dog is not able to fly!\")\n    }\n\n    class Goose : Animal {\n        override fun walk() = println(\"The goose is walking\")\n        override fun fly() = println(\"The goose is flying\")\n    }\n\n    /* ✅ Correct Example */\n    //Cat is not a fowl, so it doesn't fly. Won't break fly implementation.\n\n    interface Animals {\n        fun walk()\n    }\n\n    interface Fowls : Animals {\n        fun fly()\n    }\n\n    class Cat : Animals {\n        override fun walk() = println(\"The cat is walking\")\n    }\n\n    class Duck : Fowls {\n        override fun walk() = println(\"The duck is walking\")\n        override fun fly() = println(\"The duck is flying\")\n    }\n}\n ```\n - [**I**nterface Segregation ](/src/main/kotlin/InterfaceSegregation.kt)\n ```kotlin\n //Many client-specific interfaces are better than one general-purpose interface\n \n class InterfaceSegregation {\n\n    /* ❌ Violation Example  */\n    // An interface that handles a lot of responsibility is a violation of this principle\n\n    interface Database {\n        fun insert()\n        fun update()\n        fun updateById()\n        fun delete()\n        fun select()\n        fun selectAll()\n        fun selectById()\n    }\n\n    /* ✅ Correct Example */\n    // Break this interface as much as need to distinct all the purposes\n\n    interface ReadDatabase {\n        fun select()\n        fun selectAll()\n        fun selectById()\n    }\n\n    interface WriteDatabase {\n        fun insert()\n        fun update()\n        fun updateById()\n        fun delete()\n    }\n}\n ```\n  - [**D**ependency Inversion  ](/src/main/kotlin/DependencyInversion.kt)\n```kotlin\n//Depend upon abstractions, not your own implementation.\nclass DependencyInversion {\n\n    /* ❌ Violation Example  */\n    // The message is being formatted inside send method\n\n    class EmailService {\n        fun send(message: String) {\n            val formattedMessage = \"Email: ${message.uppercase()}\"\n            println(\"Sending formatted message: $formattedMessage\")\n        }\n    }\n\n    /* ✅ Correct Example */\n    // The message is being formatted outside send method. You just inverted the formatting dependency.\n\n    class EmailService {\n        fun send(message: String, formatter: (String) -\u003e String) {\n            val formattedMessage = formatter.invoke(message)\n            println(\"Sending formatted message: $formattedMessage\")\n        }\n    }\n}\n```\n\n\n### References\n- Raj Suvariya [@medium.com](https://medium.com/mindorks/solid-principles-explained-with-examples-79d1ce114ace)\n- Vijay Mishra [@medium.com](https://medium.com/the-android-caf%C3%A9/solid-principles-the-kotlin-way-ff717c0d60da)\n- Samuel Oloruntoba [@digitalocean.com/community](https://www.digitalocean.com/community/conceptual_articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design)\n\n\n  \n  \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrvansuita%2Fsolidkotlin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjrvansuita%2Fsolidkotlin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrvansuita%2Fsolidkotlin/lists"}