Oct.25

Tips: Flutter – Stack

@ Push widget into stack.
Navigator.of(context).push(route);

@ Pop widget from stack.
Navigator.of(context).pop();

@ Clear stack and back to root widget.
Navigator.of(context).popUntil((route) => route.isFirst);

@ Clear stack and reload root widget.
Navigator.of(context).pushAndRemoveUntil(route, ModalRoute.withName(“/”));

@ Clear stack and replace root widget.
Navigator.of(context).pushAndRemoveUntil(route, ModalRoute.withName(“”));


Flutter

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.04

Knight on the horizon!

Knight on the horizon to bring peace in our kingdom of mobile application development. Knight is coming and coming strong.

Nowadays lots of companies are going for cross-platform development to reduce development time and cost. Question is … how safe is it for long-term investment? 🤔

I’m working on mobile application development for a while and I saw many cross-platform projects died prematurely. Many projects died because those were depending 100% on 3rd party technologies. When these 3rd party technologies slow down, our projects slow down and when those die, take our projects with those as well. 😥

😭 THEN WHAT ARE WE GOING TO DO? WHO IS GOING TO SAVE US?

Well, we need to evaluate our long-term objectives and find balances. We might have chosen those paths because we didn’t have any other option at that time. But it’s about to change. 😉

3rd party technologies should be our projects’ supports but not souls. Our objective should be using those for our benefits, but if necessary we should be able to cut those off without killing our projects.

Let’s check iOS and Android native technologies.

iOS: Swift + Objective-C + UI Components (Proprietary).
Android: Kotlin + Java + UI Components (Proprietary).

Now let’s check widely used cross-platform technologies nowadays.

React Native: JavaScript + UI Components (Proprietary).
Flutter: Dart + UI Components (Proprietary).

We write whole application in React Native or Flutter. Those compile whole application natively for platforms.

As we can see, there are no common grounds between iOS/Android and React Native/Flutter in terms of technologies until compilation. 🥺

We just can’t cut those off whenever we want because whole existences of our applications depend on their existences. React Native and Flutter don’t correspond to native iOS and Android technologies until compilation.

Behold! Knight aka Kotlin Multiplatform is here to save us. 🛡

Kotlin Multiplatform allow us to compile codes and create libraries in native languages and formats. This technology compile codes written in Kotlin and generate libraries for Android and frameworks for iOS.

Check out: 😃 Kotlin Multiplatform 😍

We should develop user interface natively for platforms to provide native experience, smooth performance and customization whenever necessary.

We can compile sharable codes e.g. business rules, etc written for Android projects with Kotlin Multiplatform and can use those for iOS projects.

Later, if we don’t want to continue cross-platform development or share codes among platforms, we can just write those codes e.g. business rules, etc for iOS projects natively. Android projects can keep using existing codes as those are written in Kotlin.

Even after separation, both iOS and Android projects are alive and developments can continue independently with native technologies. 😍

Don’t worry! Our knight aka Kotlin Multiplaform is coming. Everything will be alright soon. 😁

Kotlin,Multiplaform,Thought

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.26

Kotlin Multiplatform

Kotlin Multiplatform allows cross-platform development with native languages! 😃 😍

With this approach, we can use native Android and iOS user interface and share libraries e.g. business rules in native format. 😃

Kotlin Multiplatform makes it possible to reduce costs and make business rules between platforms more reliable. 😍

Presentation on demo (Android and iOS) based on Velib Stations and Google Maps. 😎

Come on … let’s discover Kotlin Multiplatform. 😃

GitHub: https://github.com/muhammedsafiulazam/velibstations


Kotlin_Multiplatform_Version_1.0_Web

Kotlin,Multiplaform

Nov.12

Interview: Android – Reference

Dagger: Dagger is a fully static, compile-time dependency injection framework. It supports Android and Java. It is created by Square.


Butter Knife: Butter Knife is a view binding tool that uses annotations to generate boilerplate code for developers. It is developed by Jake Wharton.


RxAndroid: RxJava bindings for Android which is a library for composing asynchronous and event-based programs by using observable sequences.


Retrofit: Retrofit is a REST Client for Java and Android which makes it relatively easy to retrieve and upload data via a REST based web service. Retrofit turns HTTP API into a Java interface.


OkHTTP: OkHTTP is an open source efficient HTTP client. It supports SPDY protocol which is basis for HTTP 2.0 and allows multiple HTTP requests to be multiplexed over one socket connection. It is created by Square.


AutoValue: AutoValue concept is very simple – we write an abstract class, and @AutoValue implements it. There is literally no configuration.


Gson and Moshi: Gson and Moshi are JSON serialization and deserialization libraries. Moshi is created by Square.


Picasso: Picasso is a powerful image downloading and caching library for Android. It is created by Square.


Glide: Glide is a fast and efficient open source media management and image loading framework for Android focused on smooth scrolling. It wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.


Realm: Realm is a lightweight database that can replace both SQLite and ORM libraries. It is faster in performance and has lots of modern features, like JSON support, a fluent API, data change notifications, and encryption support.


SQLBrite: SQLBrite is a lightweight wrapper around SQLiteOpenHelper which introduces reactive stream semantics to SQL operations. In other words, our database can be observable. It is developed by Square.


Timber: Timber is a small and extensible utility library built on top of Android’s normal Log class. It is created by Jake Wharton.

Android,Reference,Interview

Nov.08

Interview: Android – Storage

Question: What is Persistent Storage?

Persistent Storage is any data storage device that retains data after turning-off power. It is also sometimes refers to non-volatile storage.


Question: What is SharedPreferences?

SharedPreferences is a library from Android which allows to save and retrieve data in the form of key-value pair in a application. It stores data persistently.


Question: What is SQLite?

SQLite is a opensource SQL database that provides a relational database management system. It stores data in a text file on a device. Android comes in with built-in SQLite database.


Question: What is Room?

Room provides an abstraction layer over SQLite to allow for more robust database access while harnessing the full power of SQLite. It is an ORM (Object Relational Mapper) for SQLite database in Android.

Android,Storage,Interview

Nov.08

Interview: Android – Network

Question: What are HTTP Client and REST Client?

HTTP Client is a client which is able to send requests and get responses from server in HTTP format.

REST Client is a client which is designed to use services from servers. These services are RESTFUL and use HTTP protocols.


Question: What is Parsing JSON?

Parsing = Interpreting.
JSon = Format specification.

Parsing JSON means interpreting data with a programming language.


Question: What is JSON Serialization/Deserialization?

JSON is a format that encode objects in a string.

Serialization means converting an object into a string and deserialization means converting a string into an object.


Question: What are Push Notifications?

Notification is a message that pops up on the user’s device. Notifications can be triggered locally by an open application, or they can be “pushed” from the server to the user even when the app is not running.

Push Notifications are assembled using two APIs: Notifications API and Push API. Notifications API lets the app display system notifications to the user. Push API allows a service worker to handle Push Messages from a server, even while the app is not active.

Android,Network,Interview

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