Dec.10

Clean Architecture

Clean architecture divide software in different layers like onion and defines definition of dependency rule among those layers e.g. source code dependencies can only point inwards.

Clean architecture in general have four layers, but we can have less or more layers if necessary as long as we follow dependency rule strictly. 😃

Dependency Rule: Outer layers are mechanism and inner layers are policies. Inner layers can not know anything about outer layers e.g. anything declared in outer layers can not be mentioned in inner layers including variables, functions, classes or other entities. This rule is simple and says that source code dependencies can only point inwards.

Checkout: 😃 Photo Album 😍 (SOLID, MVVM, CLEAN)

Photo Album show usages of dependency rule. We may need more layers based on complexities and sizes of projects, but as long as we follow dependency rule, projects fall under clean architecture.

EntitiesCore Libraries: Entities encapsulate most general and high-level rules. Entities represent classes, functions, etc which are used by other outer layers. Operational or changes in outer layers should not effect entities. Examples: ServiceManager.

Use CasesModels: Use cases contain application specific business rules and orchestrate flow of data to and from entities, and direct those entities to use their rules to achieve goals of those use cases. Examples: AlbumListModel.

GatewaysViewModels: Gateways convert data from format most convenient for the use cases and entities, to format most convenient for some external agency such user interfaces. Examples: AlbumListActivityModel.

UIViews: UI mainly contain views, frameworks and tools. Generally we don’t write much code in this layer other than glue code that communicates to the next circle inwards. Examples: AlbumListActivity.

Remember: We can have as much layers as necessary but we have to follow dependency rule. Clean architecture is nothing but following dependency rule strictly. 🙂

Architecture,Principle

Dec.06

SOLID in OOP

SOLID is an acronym for 5 design principles in OOP (Object-Oriented Programming).

These principles are a subset of many principles introduced by Robert C. Martin aka Uncle Bob in Design Principles and Design Patterns. SOLID acronym was later introduced by Michael Feathers. 🙂

Objective of these principles is to make software design and development more understandable, maintainable and extendable.

Codes or examples are written in Kotlin language. So let’s start. 😃

S: Single Responsibility Principle
Every entities (classes, modules, functions, etc.) should only have a single responsibility.

Wrong

class Zoo(val database: Database) {
   fun addAnimal(animal: Animal) {
      try {
         database.addAnimal(animal)
      } catch (exception: Exception) {
         Log.e("Error", exception.message)
      }
   }
}

Right

class Zoo(val database: Database) {
   val logger: Logger = Logger()
   fun addAnimal(animal: Animal) {
      try {
         database.addAnimal(animal)
      } catch (exception: Exception) {
         logger.log(exception)
      }
   }
}

Explanation: Zoo should not handle exceptions. So we are passing Exception to Logger for handling and allowing those to have single responsibility.

O: Open-Closed Principle
Every entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

Wrong

class Zoo(val database: Database) {
   val logger: Logger = Logger()
   fun addAnimal(animal: Animal) {
      try {
         if (animal.type = "Giraffe") {
            database.addGiraffe(animal)
         } else {
            database.addAnimal(animal)
         }
      } catch (exception: Exception) {
         logger.log(exception)
      }
   }
}

Right

open class Zoo(open val database: Database) {
   val logger: Logger = Logger()
   fun addAnimal(animal: Animal) {
      try {
         database.addAnimal(animal)
      } catch (exception: Exception) {
         logger.log(exception)
      }
   }
}

class GiraffeZoo(override val database: Database) : Zoo(database) {
   val logger: Logger = Logger()
   override fun addAnimal(animal: Animal) {
      try {
         database.addGiraffe(animal)
      } catch (exception: Exception) {
         logger.log(exception)
      }
   }
}

Explanation: By using inheritance e.g. override, we are adding extended behavior to Zoo without modifying existing method. Code is now clean and readable.

L: Liskov Substitution Principle
Entities should be replaceable with instances of their subtypes without altering correctness. Subtype should represents usage of base type.

Wrong

open class Zoo(open val database: Database) {
   val logger: Logger = Logger()
   fun addAnimal(animal: Animal) {
      try {
         database.addAnimal(animal)
      } catch (exception: Exception) {
         logger.log(exception)
      }
   }
}

class PandaZoo(override val database: Database, val notifier: Notifier) : Zoo(database) {
   override fun addAnimal(animal: Animal) {
      notifier.notify(animal)
   }
}

Right

class PandaZoo(override val database: Database, val notifier: Notifier) : Zoo(database) {
   override fun addAnimal(animal: Animal) {
      super.addAnimal(animal)
      notifier.notify(animal)
   }
}

Explanation: By not invoking super or adding to database, we are altering functionality which doesn’t align with base class. PandaZoo is a subtype of Zoo, so it should extend without costing existing behavior.

I: Interface Segregation Principle
Many entity specific interfaces are better than one general purpose interface. No entity should be forced to depend on methods it does not use.

Wrong

interface IAnimal {
   fun awake()
   fun sleep()
   fun run()
   fun fly()
}

Right

interface IAnimal {
   fun awake()
   fun sleep()
}

interface IGirrafe : IAnimal {
   fun run()
}

interface IEagle : IAnimal {
   fun fly()
}

Explanation: Giraffes don’t fly and Eagles don’t run. Now we have entity specific interfaces and entities are not forced to depend on useless methods.

D: Dependency Inversion Principle
Dependency inversion principle is a specific way of decoupling entities. Higher entities should not depend on lower entities. Both entities should depend on abstractions.

Wrong

class Zoo(val database: Database) {
   val logger: Logger = Logger()
   fun addAnimal(animal: Animal) {
      try {
         database.addAnimal(animal)
      } catch (exception: Exception) {
         logger.log(exception)
      }
   }
}

Right

class Zoo(val database: IDatabase, val logger: ILogger) {
   fun addAnimal(animal: Animal) {
      try {
         database.addAnimal(animal)
      } catch (exception: Exception) {
         logger.log(exception)
      }
   }
}

Explanation: Zoo should not create and depend on Logger directly. Plus we might want to use a subtype of Logger. So we are injecting dependencies (via interfaces) from outside instead of creating inside.

May be we are using SOLID in OOP all along more or less. 🤔 May be we didn’t know how to call it. But now we know! 😃

Architecture,Principle

Dec.03

How do we develop projects without messing up?

Through out my career, I got chances to work on different types of projects, architectures and with different types of teams.

NOBODY ever told me that they have messed up their project because they didn’t know better architecture or library.

From my experience and conversation with others, it seems like we usually mess up projects because of mismanagement or disorganization.

Every architecture and library have pros and cons. When we write dirty codes, we write dirty codes. We don’t write dirty codes because of any architecture or library.

Little by little our dirty codes grow and one day we realize that our project is out of control. We can’t point out a specific thing as it’s everywhere, so we blame our architecture.

Many companies or teams concentrate only on architectures and libraries during recruitments. We are developers and we always develop skills or learn new libraries quickly. Personality, experience and management or organizational skills come with time and these are things mainly responsible for messing up projects.

We are always learning new technologies as developers, but we should be open to learn and improve on those other non technical things as well.

Usually when we talk about what went wrong, we usually end up talking about technical things which we already know or safe to talk. We never talk about minor things which lead to those mistakes. So here I’m going to concentrate on those minor but important things.

How do we mess up projects?

1. Lack of guidelines – No coding convention and resource naming guideline.
2. Not following architecture – Mixing up entities (views and business rules) and not following directory structure.
3. Lack of tests – No actual plan on what to test or which corner cases to cover.
4. No code review – No code review or giving feedback negligibly. Also taking feedback personally.
5. Unclear responsibilities – Not knowing who is responsible for what. This brings lack of coordination as well.
6. Eyes not on target – Falling in love with project and forgetting about target e.g. consumers.
7. Lack of recognition – Lack of recognition brings lack of motivation. Employees usually don’t leave because of salaries.
8. Ego – Bringing ego in professional life which makes work environment toxic. Slowly everyone tries to avoid people with ego which is not good for project as well as for team.

How do we develop projects without messing up?
1. Guidelines – We can’t read minds. So make sure there are coding convention and resource naming guideline.
2. Following architecture – No matter which architecture we choose, we need to follow strictly. No exception is acceptable.
3. Tests – We should have plan for tests, otherwise we will end up with no tests or basic tests which may not cover corner cases.
4. Code review – Code review should be a habit. We should do code review with feedback. We should not take feedback personally.
5. Clear responsibilities – Everyone should be clear about their responsibilities and this is crucial for team building and coordination.
6. Eyes on target – Don’t fall in love with project and develop project only for oneself. We have target e.g. consumers.
7. Recognition – We need to recognize good works or someone else is going to recognize their works.
8. Politeness – Be polite and professional which make work environment great. Remember, everyone is working on same goal.

Now we know those little things we did unknowingly which indirectly affected our projects. We need to try to avoid those things. We can always try to become a better developer, a better colleague and a better human being.

Architecture,Thought,Management

Nov.07

Interview: Android – Architecture

Question: What is MVC?

MVC (Model–View–Controller) is a software design pattern commonly used for developing user interfaces which divides the related program logic into three interconnected elements.

Model represents dynamic data structure, logic and rules, independent of the user interface.

View is any representation of information such as a chart, diagram or table.

Controller accepts input and converts it to commands for the model or view.


Question: What is MVP?

MVP (Model–View–Presenter) is a derivation of the MVC (Model–View–Controller) architectural pattern, and is used mostly for building user interfaces.

Model is an interface defining the data to be displayed or otherwise acted upon in the user interface.

View is a passive interface that displays data (the model) and routes user commands (events) to the presenter to act upon that data.

Presenter acts upon the model and the view. It retrieves data from repositories (the model), and formats it for display in the view.


Question: What is MVVM?

MVVM (Model-View-ViewModel) is a software design pattern which facilitates a separation of development of the graphical user interface from development of the business logic or back-end logic (the data model). The viewmodel is a value converter, meaning the viewmodel is responsible for exposing (converting) the data objects from the model in such a way that objects are easily manageable or presentable.

Model refers either to a domain model, which represents real state content (object-oriented approach), or to the data access layer, which represents content (data-centric approach).

View is a passive interface that displays data (the model) and routes user commands (events) to the viewmodel to act upon that data.

ViewModel converts model information into values that can be displayed on a view. MVVM uses binder, which automates communication and synchronization between the view and its bound properties in the viewmodel.


Question: What is MVI (Unidirectional Data Flow)?

MVI (Model-View-Intent) is a software design pattern which follow Unidirectional and Circular Data Flow. Any user interaction is processed by business logic which brings change in the state. Then this new state is rendered on view and presented to the user.

Model represents dynamic data structure, logic and rules, independent of the user interface. Model also holds state.

View is any representation of information such as a chart, diagram or table. Views can contain one or more intents.

Intent represents an intention or command to perform an action by the user. It does not represent “android.content.Intent”.

Android,Architecture,Interview