[{"content":"I am working in a engineering team to develop open source UI libraries for Azure Communication Services. The public preview packages for UI libraries was released in November, 2021. Currently, we are preparing towards general availability with additional features.\nOur team goal is to receive feedback about API\u0026rsquo;s while we are in public preview, as the interface can be changed. As a UBC alumni and nwHack participant, I was aware that many organizations present API\u0026rsquo;s so that students can build projects using presented API\u0026rsquo;s.\nLooking at nwHack details, the event website indicated that nwHack event will be in person event. This was a perfect timing for our team to preset web and mobile UI libraries. The nwHack was planned on January 15th, 2022 and I was little worried to plan about sponsorship, event preparation as most of team members were on vacation in December, 2021.\nOnce I received a green signal from engineering managers to sponsor event, I quickly followed up with nwHack team to get the sponsorship package. At same time, me, Anjul and Jim formed a team to prepare for event.\nPlanning Our three members team (me, Anjul and Jim) scheduled quick discussion between us to plan all the nwHack events. Initially, our team ACS (Azure Communication Services) opted for gold sponsorship. We were required to planning for only workshop and boothing. In last week of December, because of British Columbia Covid restrictions nwHack changed events to virtual and converted our gold package to platinum in same budget. The platinum sponsorship added additional events like, quiz, sponsored Q\u0026amp;A and mini games to our event preparation list.\nGoal We planned Hackathon for following activities.\nEngage with students to share opportunities at Microsoft Create awareness of Azure Communication UI Libraries Receive feedback on Azure Communication Services to improve API\u0026rsquo;s Budget, Prizes As this was our first time conducting Hackathon at Microsoft, we were not aware of the process to get budget. Our group engineering manager helped us to get budget by communicating with Microsoft university contact team.\nBecause of chip shortage, we were not able to arrange devices for winner students. Luckily, we were able to get budget from cash prizes.\nTeam Formation Me, Jim and Anjul communicated with our teams to participate in nwHack. It was nice to see that many team members volunteered to participate as mentors. Once we reached to count of ten, we shared team list with nwHack team. We diversified mentors team by including engineers from Web, Android, iOS and backend.\nEvents The nwHack team shared the list of below events for platinum sponsors. It is great to see the events planned by nwHack team. All the events were good enough for students to get required knowledge as well as for organizations to create impact.\nSponsored Prize The sponsored prize is specific to organization goal. As our goal was to conduct feedback on Azure Communication Services, our winning criteria was to use at least one ACS UI library. We were able to get the budget for sponsored prize.\nKeynote and Pitch During keynote, we planned a 5 minute live presentation to introduce Azure Communication Services. With introduction, we also shared use cases so that students can come up with few ideas of developing communication product. Pitch was an quick 30 second live video to talk about sponsored prize.\nWorkshop During workshop, we demoed how to integrate UI libraries into existing application. We also talked about how to leverage ACS backend to develop Teams like application. We presented Android, iOS and React UI libraries with setup and setting up resource connection string tutorial. The students participation in workshop was amazing. As per participation, we hoped many students will develop projects using ACS UI libraries.\nGame We hosted trivia for 30 minutes. We included questions from history, technology, analytics. The event helped students to relax a bit :) (no coding)\nBoothing Microsoft recruitment team participated in an hour meeting scheduled by nwHack to answer co-op as well as full time hiring questions. In addition to hiring questions, students also asked questions about culture. This was an excellent event for student to understand the culture as well as hiring process.\nSponsored Q\u0026amp;A It was a most fun part of nwHack for me. As a mentor, I joined nwHack Sponsored Q\u0026amp;A. I was thinking here students will ask questions about technical projects or nwHack projects. However, in this session questions was about hobbies, difference between small and big organizations. I was not prepared and never answered this type of questions. I answered all questions on the spot, with information that I have :)\nResults Finally, we received 5 projects leveraging ACS UI library. From these projects, we selected a winner and a honorable project. It was awesome to see how quickly students adapted UI libraries.\nLearnings There are many learnings from nwHack 2022. In this post, I will talk about two.\nBuilding a team It is always great to indicate the responsibilities when you are building a team and hire candidates for specific responsibility.\nWe shared, below text to receive interest of team members to participate as mentor in nwHack.\n\u0026ldquo;We are conducting nwHack 2022 in January. The following events will be conducted at nwHack. Please let us know if you want to participate.\u0026rdquo; We received response of many team members. After building team, we realized that all members are only interested to conduct workshop, not other events.\nI think we should have posted below:\n\u0026ldquo;We are conducting nwHack 2022 in January. The following events will be conducted at nwHack. Please let us know if you want to participate and share the event name that you will like to organize.\u0026rdquo; Conducting a workshop During workshop, we started with introduction of ACS and demoed about leveraging ACS UI libraries into application. During nwHack mentorship sessions, many students asked basic questions about UI libraries.\nI think, we should have prepared an use case (may be small example). Then we should have developed that project in workshop by considering backend and frontend. This format should have helped to answer many questions of students.\nFinally, It was great experience to interact with students at nwHack. The feedback received from students will help us to shape our product and I learned how to organize Hackathon.\n","permalink":"https://inderpalaulakh.com/posts/nwhack2022/","summary":"Azure Communication Services (ACS) sponsored nwHack 2022 at The University of British Columbia. It was great to see the engagement from students to leverage open source API\u0026rsquo;s to solve daily problems. \u0026hellip;","title":"NwHack 2022"},{"content":"At the beginning of year 2021, my professional goal was to write blogs as well as to work on designing a software system.\nLuckily, at work, I got an opportunity to design a library using a programming language, design that I never used before, and I am happy about that. In addition, I joined a new team of nine members in early 2021 and at end of year 2021 the team is grown to fifteen members. It was an enjoyable year where I interacted with new hires every month and learned something new from every team member.\nThe book How to Win Friends and Influence People Paperback – Dale Carnegie helped me a lot to build a great relationship with team members. After reading book, I learned a way to respect the quality and positives in an individual by not comparing to someone else.\nThis year, while reading book The Design of Everyday Things - Don Norman I realized that if I am not able to operate or confused to achieve desired result using any device instead of blaming my capabilities, I can say it is bad design and it is true.\nThe most important realization that I have this year is to not use my existing skills to achieve something and learning new skills without even knowing where I am going to leverage them.\nIn upcoming years, I would like to have a roadmap to leverage my existing skills to build something and then expand my skillset as required. In addition, I want to be mindful while speaking to make sure to let only appropriate words as in remote meeting every word changes the conversation to different direction.\nHopefully, next year, I will be able to visit my parent and hometown (Punjab, India). The book list that I would like to complete next year includes The Pragmatic Programmer - Andrew, David, Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems - Martin, and The Art of Communication – Teri.\n","permalink":"https://inderpalaulakh.com/posts/year-2021/","summary":"At the beginning of year 2021, my professional goal was to write bogs as well as to work on designing a software system. \u0026hellip;","title":"Past (2021 (365 - 8)) - Present (Today 😊) - Future (*) "},{"content":"I do not know how the perfect software architectures are build. It is possible that perfect software designs are myth. The Myth of a Perfect Design\nAll successful products have working architectures that meets the engineering, operational costs as well as satisfy customer requirements. A thoughtful software design opens door for an organization to expand software design by adding new services to it\u0026rsquo;s umbrella easily.\nThis post may be helpful to a one man army with goal to learn and build a working software system. The post is limited to my knowledge and is open for feedback and suggestions. I will talk about following topics.\nConsiderations Security Auditing Diagnostics Localization Analytics Hosting Scalability Components Authentication and Authorization Database API\u0026rsquo;s Applications Considerations I am considering security, auditing, diagnostics, hosting, scalability as mandatory requirements that software design needs to fulfill before release. Localization and analytics are to improve revenue and customer satisfaction.\nSecurity User Data: All countries have specific requirements for user data handling like PIPEDA, GDPR. These policies needs to be respected and are very valuable to protect customer data. For healthcare application, additional requirements HIPAA more must be considered. Passwords in memory(Android, Windows, Browser process) needs to be encrypted. Otherwise, anyone can generate memory dump to read credentials. Diagnostics logs should not contain any sensitive information. In general, taking legal advice from a domain expert about data handling is very helpful in initial phase of system design. I indicated only few laws that I am aware of, I am sure there are many more.\nAuditing The purpose of auditing is to identify who performed what action on data. For example, a bank employee can search his friend profile in bank information management system and can check his account balance. This action is not appropriate until the owner of account request any information. The bank employee can use his friend information to make some deals. If bank information management system is not saving every action of employee\u0026rsquo;s like who visited user profiles then in case of legal lawsuit bank can never identify who visited a customer profile to breach data.\nIt is important for an system design to track all the activity on data (who read, who write, who delete, when read/write..).\nDiagnostics Every components needs to have logs when an error/exception occurs. Without logs it will be very hard to understand the cause of issues. It will be great to have a log analysis system to look at critical events to notify the owner of component to make system more reliable.\nResilient system - when a service goes down, other instance of service will be immediately available to not impact customers. A good error handling, diagnostics helps to make system more reliable.\nHosting Hosting is an important topic that determines the cost of running a product. We can host components on Azure/AWS/Google cloud. It will be great to design system that can be hosted on any cloud provider.\nUnderstanding the fundamentals of cloud security is must to deploy systems. All the cloud providers have certification courses to understand the basic concepts.\nScalability Scalability helps to handle unpredicted load on system. It is easy to scale a product if the system design is divided into small independent components. A few concepts that can help:\nContainerized services to access database A caching system like Redis to handle frequent used data Load balancers to manage service containers Database sharding Appropriate database choice SQL/NoSQL Event based system to manage transactions (async queries) Localization Localization is to support multiple languages. Most of website provides option to choose language. Building system considering localization takes very less effort to launch product in other corner of world.\nAnalytics Analytics helps to understand the product usage (example: the features mostly used by user. etc..). Most analytics frameworks provide extensions to build reports by easily integrating to database. If the data is scattered on multiple platforms, it may be more time consuming to analyze it. Frameworks\nComponents Now, I will talk about the high level components of system design. Every component has many sub components that will be covered in individual blog posts.\nAuthentication and Authorization OAuth is widely used authentication protocol. SAMP and OpenID Connect are used for authorization. It is very important to use central user login system to manage web, mobile user as a single source. The authentication and authorization component also serve the requests from backend to confirm authorization. Azure Active Directory B2C, Auth0 and AWS Cognito are few authentication and authorization platforms I am aware of.\nDatabase We need to understand SQl, NoSQL database to appropriately choose best database for a product. Addition in memory database like Redis or Memcached can be used for high availability.\nAPI\u0026rsquo;s API\u0026rsquo;s are used to access data from database or for delivering events to async queues. In my opinion, it is best to use containers for API\u0026rsquo;s or microservices. These containers can be managed by load balancers. Kubernetes helps for load balancing docker containers. We will look at Azure Kubernetes Service (AKS) in upcoming posts.\nApplications The product can delight customers only if user interface is designed considering customer requirements. We will talk about frameworks that can be used for to develop website. Mobile applications also plays a significant role in system design.\nIf application do not need to access OS specific concepts for Mobile, I think React Native and React can be best options to develop Android and iOS application and website.\nKMM(Kotlin Multi Module) can be used to share code between Android and iOS to reduce development effort.\n","permalink":"https://inderpalaulakh.com/posts/systemdesign1/","summary":"I do not know how the perfect software architectures are build. It is possible that perfect software designs are myth. \u0026hellip;","title":"Software System Design"},{"content":"Adding a chat to Android application is made easy by Azure Communication Services. Luckily, the requirement to build user interface can be fulfilled by ChatKit.\nAt end of this post, you will be familiar with:\nHow to build Android Sample Chat Application (GitHub)? How to create Azure Communication Services Chat resource? How to generate user token and user id from communication service resource connection string? Build Android Sample Chat Application Clone Android Sample Chat Application (GitHub) Open chatjoin and chatadmin in Android Studio Run applications on emulator or device Create Azure Communication Service Resource Open Azure Portal Create Communication Service resource Copy connection string More information at Create a Communication Services resource Generate Communication Service User Token Clone access-tokens-quickstart cd to access-tokens-quickstart Execute \u0026rsquo;npm install` Enter connection string copied previously to const connectionString Change scope to chat // This code demonstrates how to fetch your connection string // from an environment variable. const connectionString = \u0026#34;\u0026lt;ACS_CONNECTION_STRING_FROM_PORTAL\u0026gt;\u0026#34;; // Instantiate the identity client const identityClient = new CommunicationIdentityClient(connectionString); // This code demonstrates how to fetch your endpoint and access key // from an environment variable. /*const endpoint = process.env[\u0026#34;COMMUNICATION_SERVICES_ENDPOINT\u0026#34;]; const accessKey = process.env[\u0026#34;COMMUNICATION_SERVICES_ACCESSKEY\u0026#34;]; const tokenCredential = new AzureKeyCredential(accessKey); // Instantiate the identity client const identityClient = new CommunicationIdentityClient(endpoint, tokenCredential);*/ // Authenticate with managed identity // const endpoint = \u0026#34;\u0026lt;ACS_CONNECTION_STRING_FROM_PORTAL\u0026gt;\u0026#34;; // const tokenCredential = new DefaultAzureCredential(); // const identityClient = new CommunicationIdentityClient(endpoint, tokenCredential); // Create an identity let identityResponse = await identityClient.createUser(); console.log(`\\nCreated an identity with ID: ${identityResponse.communicationUserId}`); // Issue an access token with the \u0026#34;voip\u0026#34; scope for an identity let tokenResponse = await identityClient.getToken(identityResponse, [\u0026#34;chat\u0026#34;]); const { token, expiresOn } = tokenResponse; console.log(`\\nIssued an access token with \u0026#39;voip\u0026#39; scope that expires at ${expiresOn}:`); console.log(token); //Refresh access tokens // Value of identityResponse represents the Azure Communication Services identity stored during identity creation and then used to issue the tokens being refreshed // let refreshedTokenResponse = await identityClient.getToken(identityResponse, [\u0026#34;chat\u0026#34;]); // Revoke access tokens // await identityClient.revokeTokens(identityResponse); // console.log(`\\nSuccessfully revoked all access tokens for identity with ID: ${identityResponse.communicationUserId}`); // Delete an identity // await identityClient.deleteUser(identityResponse); // console.log(`\\nDeleted the identity with ID: ${identityResponse.communicationUserId}`); Do not forget to comment Revoke access tokens Delete an identity Execute node .\\issue-access-token.js More information at Azure Communication Services Chat to generate Azure Communication Service Token with scope as chat. access-tokens-quickstart Having an issue? Check if below video can help.\nStart Chat Enter required information obtained by executing node .\\issue-access-token.js On Start Chat button click, you will see a ThreadId generated in logs. ChatThreadID -: 19:Pk6_myvAX.....U1@thread.v2 Join Chat Enter required information, input threadId from Run AzureChatAdmin Click Join Chat ","permalink":"https://inderpalaulakh.com/posts/azurechat/","summary":"This post demonstrates the Android chat application leveraging Azure Communication Services and ChatKit.","title":"Android Sample Chat Application using Azure Communication Services and ChatKit"},{"content":"Last week, I read an article \u0026ldquo;Harnessing the Power of Less\u0026rdquo; published in Special Times Edition \u0026ldquo;Secrets of Success\u0026rdquo;.\nThe beautiful line \u0026ldquo;Stretching encourages adaptation and working with what you already have, rather than focusing on needing more\u0026rdquo; from the article daunted me to rewire my burned out brain.\nThe article has an exercise to ask self a question: What can I do with what I have? As usual, instead of working on this question, I modified question to: What task I want to do? What skills I already have to complete the task?\nWhat skills I do not have to complete the task?\nBy now, I know the questions that I need to answer to save my burned out brain.\nThank God, I know the task I want to do 😌. I will write a series of blog posts to answer the questions.\n","permalink":"https://inderpalaulakh.com/posts/thepowerofless/","summary":"Last week, I read an article \u0026ldquo;Harnessing the Power of Less\u0026rdquo; published in Special Times Edition \u0026ldquo;Secrets of Success\u0026rdquo;. The beautiful line \u0026ldquo;Stretching encourages adaptation and working with what you already have, rather than focusing on needing more\u0026rdquo; \u0026hellip;","title":"Harnessing the Power of Less"},{"content":"Kotlin supports Higher order functions. In this blog, I will create a higher order function that will use map \u0026amp; fold right for execution.\nBefore diving into higher order functions, let\u0026rsquo;s go through map \u0026amp; fold right.\nmap is collective transform operation.\nvar numbers = mutableListOf(1, 2, 3) numbers = numbers.map { it*2 }.toMutableList() // elements in numbers: 2,4,6 foldRight accept initial state, apply initial state to all elements and return final state.\nvar numbers = mutableListOf(1, 2, 3) var result = numbers.foldRight(100, {a,b -\u0026gt; test(a,b)}) private fun test(a: Int, b: Any): Int { return a + b as Int } /* First execution: initial 100 a = 3 b = 100 Second Execution a = 2 b = 103 Third Execution a = 1 b = 105 final: result = 106 */ Let\u0026rsquo;s create a higher order function Middleware that takes an instance StringApp, has inner function next: Type and return Type.\ntypealias Type = (value: String) -\u0026gt; Unit typealias Middleware = (stringApp: StringApp) -\u0026gt; (next: Type) -\u0026gt; Type Now, create three classes that implements Middleware.\nclass MiddlewareA : Middleware { override fun invoke(stringApp: StringApp) = { next: Type -\u0026gt; { value: String -\u0026gt; next(\u0026#34;$value MiddlewareA \u0026#34;) } } } class MiddlewareB : Middleware { override fun invoke(stringApp: StringApp) = { next: Type -\u0026gt; { value: String -\u0026gt; next(\u0026#34;$value MiddlewareB \u0026#34;) } } } class MiddlewareC : Middleware { override fun invoke(stringApp: StringApp) = { next: Type -\u0026gt; { value: String -\u0026gt; next(\u0026#34;$value MiddlewareC \u0026#34;) } } } StringApp class receives list of middlewares and call dispatch to execute higher order function.\nclass StringApp(private val middlewares: MutableList\u0026lt;Middleware\u0026gt;) { private fun reduce(value: String) { val result = value; // result = } fun dispatch(value: String) { var dispatch2 = middlewares[2](this)(::reduce) var dispatch1 = middlewares[1](this)(dispatch2) middlewares[0](this)(dispatch1)(value) } } The higher order function can be written as below:\nval app = StringApp(mutableListOf(MiddlewareA(), MiddlewareB(), MiddlewareC())) app.dispatch(\u0026#34;init\u0026#34;) { middlewareC -\u0026gt; set string value to \u0026#34;init middleware A middleware B middleware C\u0026#34; { middlewareB -\u0026gt; set string value to \u0026#34;init middleware A middleware B\u0026#34; { middlewareA -\u0026gt; set string value to \u0026#34;init middleware A\u0026#34; } } } Let\u0026rsquo;s use map \u0026amp; fold right to execute higher order function.\nclass StringApp(middlewares: MutableList\u0026lt;Middleware\u0026gt;) { // map inject store reference to all middleware functions private val middlewareMap: List\u0026lt;(Type) -\u0026gt; Type\u0026gt; = middlewares.map { m -\u0026gt; m.invoke(this) } /* // now below code execution required to achieve result var dispatch2 = middlewareMap[2](::reduce) var dispatch1 = middlewareMap[1](dispatch2) middlewareMap[0](dispatch1)(value) */ var middlewareDispatch = compose(middlewareMap)(::reduce) // traverse through middlewares // build middleware chain by injecting dispatch from previous middleware // inject ::reduce to last middleware private fun compose(functions: List\u0026lt;(Type) -\u0026gt; Type\u0026gt;): (Type) -\u0026gt; Type = { dispatch -\u0026gt; functions.foldRight( dispatch, { nextDispatch, composed -\u0026gt; nextDispatch(composed) }) } private fun reduce(value: String) { val result = value; } private fun dispatch(value: String) { middlewareDispatch(value) } } I learned map \u0026amp; fold while implementing redux middleware concepts from library kotlin-redux.\nUsing higher order functions for middleware helps to stop middleware chain execution. If a middleware subscribes to service, on async callback the middleware can finish the work without invoking next middleware.\n","permalink":"https://inderpalaulakh.com/posts/middlewarekotlin/","summary":"\u003cp\u003eKotlin supports \u003ca href=\"https://en.wikipedia.org/wiki/Higher-order_function\"\u003eHigher order functions\u003c/a\u003e. In this blog, I will create a higher order function that will use map \u0026amp; fold right for execution.\u003c/p\u003e\n\u003cp\u003eBefore diving into higher order functions, let\u0026rsquo;s go through map \u0026amp; fold right.\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003emap\u003c/code\u003e is collective transform operation.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e numbers = mutableListOf(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enumbers = numbers.map { \u003cspan style=\"color:#66d9ef\"\u003eit\u003c/span\u003e*\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e }.toMutableList()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// elements in numbers: 2,4,6\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ccode\u003efoldRight\u003c/code\u003e accept initial state, apply initial state to all elements and return final state.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e numbers = mutableListOf(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e result = numbers.foldRight(\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e, {a,b \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e test(a,b)})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efun\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etest\u003c/span\u003e(a: Int, b: Any): Int {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e a + b \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e Int\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e/*\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eFirst execution: \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003einitial 100\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003ea = 3\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eb = 100\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eSecond Execution\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003ea = 2\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eb = 103\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eThird Execution\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003ea = 1\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eb = 105\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003efinal: result = 106\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e*/\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eLet\u0026rsquo;s create a higher order function \u003ccode\u003eMiddleware\u003c/code\u003e that takes an instance \u003ccode\u003eStringApp\u003c/code\u003e, has inner function \u003ccode\u003enext:  Type\u003c/code\u003e and return \u003ccode\u003eType\u003c/code\u003e.\u003c/p\u003e","title":"Kotlin map, foldRight \u0026 nested functions to implement redux middleware"},{"content":"It is very connivent to use any DI framework when all the objects required are available in application. For example, I have two classes Logger, Service and class Middleware is dependent on these classes.\nclass Logger() class Service() //this class requires Logger \u0026amp; Service object class Middleware(private val logger:Logger. private val service:Service) // middleware object val middleware = Middleware(Logger(),Service()) Dagger can build objects of Logger and Service classes by indicating @Inject annotation to all three classes\ninternal class Logger @Inject constructor() internal class Service @Inject constructor() //this class requires Logger \u0026amp; Service object internal class Middleware @Inject constructor(private val logger:Logger. private val service:Service) @Component interface MiddlewareComponent { fun buildComponent():Middleware } // middleware object val middleware = DaggerMiddlewareComponent.builder().build().buildComponent() If the project requirements are modified to get Logger with custom implementation, we can write @Module to support dependency injection.\n// now, Logger is interface interface Logger class Service @Inject constructor() class Middleware @Inject constructor(val logger: Logger, val service: Service) @Module class LoggerModule constructor(val logger: Logger) { @Provides fun providesLogger(): Logger { return logger } } @Component(modules = [LoggerModule::class]) interface MiddlewareComponent { fun buildComponent(): Middleware } //custom implementation class NullLogger : Logger //injecting logger module with interface implementation val middleware = DaggerMiddlewareComponent.builder().loggerModule(LoggerModule(NullLogger())).build().buildComponent() ","permalink":"https://inderpalaulakh.com/posts/dicustom/","summary":"\u003cp\u003eIt is very connivent to use any DI framework when all the objects required are available in application. For example, I have two classes \u003ccode\u003eLogger\u003c/code\u003e, \u003ccode\u003eService\u003c/code\u003e and class \u003ccode\u003eMiddleware\u003c/code\u003e is dependent on these classes.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eLogger\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eService\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//this class requires Logger \u0026amp; Service object\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMiddleware\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e logger:\u003cspan style=\"color:#a6e22e\"\u003eLogger\u003c/span\u003e. \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e service:Service)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// middleware object\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e middleware = Middleware(Logger(),Service())\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ccode\u003eDagger\u003c/code\u003e can build objects of \u003ccode\u003eLogger\u003c/code\u003e and \u003ccode\u003eService\u003c/code\u003e classes by indicating \u003ccode\u003e@Inject\u003c/code\u003e annotation to all three classes\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einternal\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eLogger\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e@Inject\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econstructor\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einternal\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eService\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e@Inject\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econstructor\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//this class requires Logger \u0026amp; Service object\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einternal\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMiddleware\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e@Inject\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econstructor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e logger:\u003cspan style=\"color:#a6e22e\"\u003eLogger\u003c/span\u003e. \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e service:Service)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Component\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMiddlewareComponent\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efun\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebuildComponent\u003c/span\u003e():Middleware\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// middleware object\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e middleware = \u003cspan style=\"color:#a6e22e\"\u003eDaggerMiddlewareComponent\u003c/span\u003e.builder().build().buildComponent()\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIf the project requirements are modified to get \u003ccode\u003eLogger\u003c/code\u003e with custom implementation, we can write \u003ccode\u003e@Module\u003c/code\u003e to support dependency injection.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// now, Logger is interface\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eLogger\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eService\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e@Inject\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econstructor\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMiddleware\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e@Inject\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econstructor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e logger: Logger, \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e service: Service)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Module\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eLoggerModule\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econstructor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e logger: Logger) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Provides\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efun\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprovidesLogger\u003c/span\u003e(): Logger {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e logger\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Component\u003c/span\u003e(modules = [LoggerModule\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMiddlewareComponent\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efun\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebuildComponent\u003c/span\u003e(): Middleware\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//custom implementation\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eNullLogger\u003c/span\u003e : Logger\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//injecting logger module with interface implementation\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e middleware = \u003cspan style=\"color:#a6e22e\"\u003eDaggerMiddlewareComponent\u003c/span\u003e.builder().loggerModule(LoggerModule(NullLogger())).build().buildComponent()\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Dagger, Injecting custom objects (Interface implementation)"},{"content":"Below are widely used Dependency Injection frameworks mostly by android \u0026amp; Java application projects.\nFor Android application development, the suggested Framework by Google are Dagger and Hilt. These frameworks help to avoid writing boilerplate code.\nGuice Guice (pronounced \u0026lsquo;juice\u0026rsquo;) is a lightweight dependency injection framework for Java 6 and above, brought to you by Google. (github.com)\nWith 10K stars this framework is mostly used by Java developers where Java is used for backend \u0026amp; Application development.\nFor Android, this framework is not suggested as this framework use reflections to scan annotations from code. This requires significant CPU cycles and RAM thus slowdowns application launch.\nReflection on the desktop/server JVM is very efficient, and even very large Guice applications don\u0026rsquo;t have performance problems related to Guice.\nManage your app\u0026rsquo;s memory | Android Developers : Other dependency injection frameworks that use reflection tend to initialize processes by scanning your code for annotations. This process can require significantly more CPU cycles and RAM and can cause a noticeable lag when the app launches.\nDagger Dagger is an open source Guice alternative designed to run efficiently on Android.\nNo doubt, Dagger makes life easier, for Android Library development this seems to cause issue if Application include library that use different version of Dagger. (Note: Gradle use latest version of library if library has multiple versions in Application.)\nDagger is a fully static, compile-time dependency injection framework for Java, Kotlin, and Android. The dependency of Dagger is not included to .aar for Android Library.\nlisted issue: android - Dagger 2. Library and app has different version Compilation issues after moving to 2.34 from 2.33 - Hilt · Issue #2541 · google/dagger\nHilt (Beta) Hilt is built on top of the popular DI library Dagger to benefit from the compile-time correctness, runtime performance, scalability, and Android Studio support that Dagger provides.\nAndroid app requires you to write a substantial amount of boilerplate. Hilt reduces the boilerplate code that is involved in using Dagger in an Android application. Hilt automatically generates and provides the following:\nComponents for integrating Android framework classes with Dagger that you would otherwise need to create by hand. Scope annotations to use with the components that Hilt generates automatically. Predefined bindings to represent Android classes such as Application or Activity. Predefined qualifiers to represent @ApplicationContext and @ActivityContext. Dependency injection with Hilt | Android Developers\nTo compare Hilt \u0026amp; Dagger read Dependency injection on Android with Hilt.\nServiceLocator The service locator design pattern also improves decoupling of classes from concrete dependencies. You create a class known as the service locator that creates and stores dependencies and then provides those dependencies on demand.\nclass ServiceLocator { private static ServiceLocator instance = null; private ServiceLocator() {} public static ServiceLocator getInstance() { if (instance == null) { synchronized(ServiceLocator.class) { instance = new ServiceLocator(); } } return instance; } public Engine getEngine() { return new Engine(); } } class Car { private Engine engine = ServiceLocator.getInstance().getEngine(); public void start() { engine.start(); } } class MyApp { public static void main(String[] args) { Car car = new Car(); car.start(); } } Summary In my opinion, the DI library choice becomes easy once we decide the Android Library delivery method.\n.aar: if the project requirement is to share .aar with developers, Dagger is good choice as it is compile time and has capabilities to get custom objects from application. Source Code: if we are going to share code with developers and Android library is injected into application as source project then Service Locator pattern is good choice for Android Library development as we do not want to inject dependencies to library that can cause conflicts with application’s dependencies. Another drawback is maintaince required to test/update library when new version of Hilt or Dagger is released. ","permalink":"https://inderpalaulakh.com/posts/di/","summary":"\u003cp\u003eBelow are widely used Dependency Injection frameworks mostly by android \u0026amp; Java application projects.\u003c/p\u003e\n\u003cp\u003eFor Android application development, the suggested Framework by Google are Dagger and Hilt. These frameworks help to avoid writing boilerplate code.\u003c/p\u003e\n\u003ch1 id=\"guice\"\u003eGuice\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/google/guice\"\u003eGuice (pronounced \u0026lsquo;juice\u0026rsquo;) is a lightweight dependency injection framework for Java 6 and above, brought to you by Google. (github.com)\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eWith 10K stars this framework is mostly used by Java developers where Java is used for backend \u0026amp; Application development.\u003c/p\u003e\n\u003cp\u003eFor Android, this framework is not suggested as this framework use reflections to scan annotations from code. This requires significant CPU cycles and RAM thus slowdowns application launch.\u003c/p\u003e\n\u003cp\u003eReflection on the desktop/server JVM is very efficient, and even very large Guice applications don\u0026rsquo;t have performance problems related to Guice.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://developer.android.com/topic/performance/memory#DependencyInjection\"\u003eManage your app\u0026rsquo;s memory |  Android Developers\u003c/a\u003e : Other dependency injection frameworks that use reflection tend to initialize processes by scanning your code for annotations. This process can require significantly more CPU cycles and RAM and can cause a noticeable lag when the app launches.\u003c/p\u003e","title":"Android/Java Dependency Injection Frameworks (Android Library \u0026 App Development)"},{"content":"Redis is in-memory data structure store. Redis has a really good documentation to learn and implement framework capabilities. My mentor at Job guided me to learn Redis. My primary focus is to understand how Redis helps for Distributed Caching.\nDistributed Caching Distributed Caching is cache shared by multiple servers. The miclsroservices or services can keep it\u0026rsquo;s own cache for data but distributed cache has many advantages as we can scale and manage cache at one place.\nThe caches are used to save time to reduce cost to read database from database. The in memory(RAM cache) data is much more efficient to perform read operations as compared to SQL databases. Redis supports distributed caching by clusters. Twitter has redis instance for every user across data centers. When a tweet comes, the tweet is inserted into redis cache instance of every user who follows the tweet owner Real Time Delivery Twitter. Distributing caching helps twitter to deliver 300k tweets/sec.\n","permalink":"https://inderpalaulakh.com/posts/redis/","summary":"\u003cp\u003e\u003ca href=\"https://redis.io/\"\u003eRedis\u003c/a\u003e is in-memory data structure store. Redis has a really good documentation to learn and implement framework capabilities. \u003cbr/\u003e\u003c/p\u003e\n\u003cp\u003eMy mentor at Job guided me to learn Redis. My primary focus is to understand how Redis helps for \u003ccode\u003eDistributed Caching\u003c/code\u003e.\u003cbr/\u003e\u003c/p\u003e\n\u003ch2 id=\"distributed-caching\"\u003eDistributed Caching\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://en.wikipedia.org/wiki/Distributed_cache\"\u003eDistributed Caching\u003c/a\u003e is cache shared by multiple servers. The miclsroservices or services can keep it\u0026rsquo;s own cache for data but distributed cache has many advantages as we can scale and manage cache at one place.\u003cbr/\u003e\u003c/p\u003e\n\u003cp\u003eThe caches are used to save time to reduce cost to read database from database. The in memory(RAM cache) data is much more efficient to perform read operations as compared to SQL databases. \u003cbr/\u003e\u003c/p\u003e\n\u003cp\u003eRedis supports distributed caching by clusters. Twitter has redis instance for every user across data centers. When a tweet comes, the tweet is inserted into redis cache instance of every user who follows the tweet owner \u003ca href=\"https://www.infoq.com/presentations/Real-Time-Delivery-Twitter/\"\u003eReal Time Delivery Twitter\u003c/a\u003e. Distributing caching helps twitter to deliver 300k tweets/sec.\u003cbr/\u003e\u003c/p\u003e","title":"Distributed caching - Redis"},{"content":"Recently, I developed an Android application. The application was developed focusing on simplicity. The application was small thus skipped writing unit tests. I know skipping the unit tests is not a good practice.\nIn past, I was working on backend projects where tons of unit tests exists for API\u0026rsquo;s. I am new to application development and spent some time to learn about MVC and MVVM design patterns.\nFor next project, the preference is MVVM. At end of this post I will share the reason to choose MVVM.\nThe example code for this post is written for Android application.\nMVC (Model-View-Controller) Model: Model is data layer. Model call services or database to get data from external systems. View: View is user interface layer. Controller: Controller is triggered first. Controller has reference to Model as well as View. Controller get data from Model and send to View.\nI developed a sample application to demonstrate MVC. This application populates ListView on Button click.\nFolder Structure User.java\npublic class User { private String name; public User(String name) { this.name = name; } public String getName() { return name; } } UserModel.java\npublic class UserModel{ private final ArrayList\u0026lt;User\u0026gt; userList; public UserModel(){ userList = new ArrayList\u0026lt;User\u0026gt;(); // get users from database userList.add(new User(\u0026#34;Ram\u0026#34;)); userList.add(new User(\u0026#34;Devin\u0026#34;)); userList.add(new User(\u0026#34;Sham\u0026#34;)); userList.add(new User(\u0026#34;Inder\u0026#34;)); userList.add(new User(\u0026#34;David\u0026#34;)); userList.add(new User(\u0026#34;Kaur\u0026#34;)); } public ArrayList\u0026lt;User\u0026gt; getUsers() { return userList; } } UserController.java Controller has instances of both Model \u0026amp; View. Controller get data from Model \u0026amp; update view.\npublic class UserController { private final UserModel userModel; private final UserView userView; public UserController(UserView userView) { this.userModel = new UserModel(); this.userView = userView; } public void getUsers() { userView.displayUsers(userModel.getUsers()); } } UserView.java UserView create instance of Controller. This class handles button clicks from UI.\npublic class UserView { View userView; UserController userController; Button getUsersButton; ListView usersListView; public UserView(Context context, ViewGroup container) { userView = LayoutInflater.from(context).inflate(R.layout.activity_main, container, false); userController = new UserController(this); } public void initView() { getUsersButton = userView.findViewById(R.id.button); getUsersButton.setOnClickListener(l -\u0026gt; { userController.getUsers(); }); usersListView = userView.findViewById(R.id.user_list_view); } public void displayUsers(ArrayList\u0026lt;User\u0026gt; users) { UsersAdapter adapter = new UsersAdapter(userView.getContext(), users); usersListView.setAdapter(adapter); } public View getRootView() { return userView; } } class UsersAdapter extends ArrayAdapter\u0026lt;User\u0026gt; { public UsersAdapter(Context context, ArrayList\u0026lt;User\u0026gt; users) { super(context, 0, users); } @Override public View getView(int position, View convertView, ViewGroup parent) { User user = getItem(position); if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_view_item, parent, false); } TextView tvName = (TextView) convertView.findViewById(R.id.user_name); tvName.setText(user.getName()); return convertView; } } MainActivity.java MainActivity creates UserView instance.\npublic class MainActivity extends AppCompatActivity { UserView userView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); userView = new UserView(MainActivity.this, null); setContentView(userView.getRootView()); userView.initView(); } } activity_main.xml\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt; \u0026lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\u0026#34;http://schemas.android.com/apk/res/android\u0026#34; xmlns:app=\u0026#34;http://schemas.android.com/apk/res-auto\u0026#34; xmlns:tools=\u0026#34;http://schemas.android.com/tools\u0026#34; android:layout_width=\u0026#34;match_parent\u0026#34; android:layout_height=\u0026#34;match_parent\u0026#34; tools:context=\u0026#34;.MainActivity\u0026#34;\u0026gt; \u0026lt;ListView android:id=\u0026#34;@+id/user_list_view\u0026#34; android:layout_width=\u0026#34;match_parent\u0026#34; android:layout_height=\u0026#34;match_parent\u0026#34; android:layout_marginTop=\u0026#34;90dp\u0026#34; app:layout_constraintBottom_toBottomOf=\u0026#34;parent\u0026#34; app:layout_constraintEnd_toEndOf=\u0026#34;parent\u0026#34; app:layout_constraintStart_toStartOf=\u0026#34;parent\u0026#34; app:layout_constraintTop_toTopOf=\u0026#34;parent\u0026#34; \u0026gt; \u0026lt;/ListView\u0026gt; \u0026lt;Button android:id=\u0026#34;@+id/button\u0026#34; android:layout_width=\u0026#34;wrap_content\u0026#34; android:layout_height=\u0026#34;wrap_content\u0026#34; android:layout_marginStart=\u0026#34;151dp\u0026#34; android:layout_marginTop=\u0026#34;5dp\u0026#34; android:layout_marginEnd=\u0026#34;146dp\u0026#34; android:layout_marginBottom=\u0026#34;24dp\u0026#34; android:text=\u0026#34;Get Users\u0026#34; app:layout_constraintBottom_toTopOf=\u0026#34;@+id/user_list_view\u0026#34; app:layout_constraintEnd_toEndOf=\u0026#34;parent\u0026#34; app:layout_constraintStart_toStartOf=\u0026#34;parent\u0026#34; app:layout_constraintTop_toTopOf=\u0026#34;parent\u0026#34; /\u0026gt; \u0026lt;/androidx.constraintlayout.widget.ConstraintLayout\u0026gt; list_view_item.xml\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt; \u0026lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\u0026#34;http://schemas.android.com/apk/res/android\u0026#34; xmlns:app=\u0026#34;http://schemas.android.com/apk/res-auto\u0026#34; xmlns:tools=\u0026#34;http://schemas.android.com/tools\u0026#34; android:layout_width=\u0026#34;match_parent\u0026#34; android:layout_height=\u0026#34;match_parent\u0026#34; tools:context=\u0026#34;.MainActivity\u0026#34;\u0026gt; \u0026lt;TextView android:id=\u0026#34;@+id/user_name\u0026#34; android:layout_width=\u0026#34;wrap_content\u0026#34; android:layout_height=\u0026#34;wrap_content\u0026#34; android:text=\u0026#34;Name\u0026#34; /\u0026gt; \u0026lt;/androidx.constraintlayout.widget.ConstraintLayout\u0026gt; In above example, controller is not loosely coupled with view. It has both View \u0026amp; Model. View also has controller reference to send receive.\nMVVM (Model-View-ViewModel) Model: Model is data layer. Model call services or database to get data from external systems. View: View is user interface layer. View is triggered first to request controller to get data from Model. View Model: View Model has reference to Model only. ViewModel is loosely coupled with View through livedata or databinding.\nI developed a sample application to demonstrate MVVM. This application populates ListView on Button click. Folder Structure User.java\npublic class User { private String name; public User(String name) { this.name = name; } public String getName() { return name; } } UserModel.java\npublic class UserModel{ private final ArrayList\u0026lt;User\u0026gt; userList; public UserModel(){ userList = new ArrayList\u0026lt;User\u0026gt;(); // get users from database userList.add(new User(\u0026#34;Ram\u0026#34;)); userList.add(new User(\u0026#34;Devin\u0026#34;)); userList.add(new User(\u0026#34;Sham\u0026#34;)); userList.add(new User(\u0026#34;Inder\u0026#34;)); userList.add(new User(\u0026#34;David\u0026#34;)); userList.add(new User(\u0026#34;Kaur\u0026#34;)); } public ArrayList\u0026lt;User\u0026gt; getUsers() { return userList; } } UserViewModel.java UserViewModel has instances of Model. Controller get data from Model and notify live data subscribers.\npublic class UserViewModel extends ViewModel { private MutableLiveData\u0026lt;ArrayList\u0026lt;User\u0026gt;\u0026gt; userList; public UserViewModel() { userList = new MutableLiveData\u0026lt;\u0026gt;(); } public MutableLiveData\u0026lt;ArrayList\u0026lt;User\u0026gt;\u0026gt; getObserverUserList() { return userList; } public void getUsers() { // notify subscribers userList.postValue((new UserModel()).getUsers()); } } MainActivity.java MainActivity creates UserViewModel. UserViewModel triggers live data.\npublic class MainActivity extends AppCompatActivity { UserViewModel userViewModel; Button getUsersButton; ListView usersListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // get view model userViewModel = ViewModelProviders.of(this).get(UserViewModel.class); getUsersButton = findViewById(R.id.button); getUsersButton.setOnClickListener(l -\u0026gt; { userViewModel.getUsers(); }); usersListView = findViewById(R.id.user_list_view); // subscribe to view model userViewModel.getObserverUserList().observe(this, l -\u0026gt; { UsersAdapter adapter = new UsersAdapter(this, l); usersListView.setAdapter(adapter); }); } } class UsersAdapter extends ArrayAdapter\u0026lt;User\u0026gt; { public UsersAdapter(Context context, ArrayList\u0026lt;User\u0026gt; users) { super(context, 0, users); } @Override public View getView(int position, View convertView, ViewGroup parent) { User user = getItem(position); if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_view_item, parent, false); } TextView tvName = (TextView) convertView.findViewById(R.id.user_name); tvName.setText(user.getName()); return convertView; } } list_view_item.xml\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt; \u0026lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\u0026#34;http://schemas.android.com/apk/res/android\u0026#34; xmlns:app=\u0026#34;http://schemas.android.com/apk/res-auto\u0026#34; xmlns:tools=\u0026#34;http://schemas.android.com/tools\u0026#34; android:layout_width=\u0026#34;match_parent\u0026#34; android:layout_height=\u0026#34;match_parent\u0026#34; tools:context=\u0026#34;.MainActivity\u0026#34;\u0026gt; \u0026lt;TextView android:id=\u0026#34;@+id/user_name\u0026#34; android:layout_width=\u0026#34;wrap_content\u0026#34; android:layout_height=\u0026#34;wrap_content\u0026#34; android:text=\u0026#34;Name\u0026#34; /\u0026gt; \u0026lt;/androidx.constraintlayout.widget.ConstraintLayout\u0026gt; In above example, controller is loosely coupled with view. It has only Model. Controller has no information of view.\nNote: The data bindings can be used for loose coupling.\nFinally My purpose to use design patterns is to write unit testable and maintainable code. As MVVM ViewModel is loosely coupled with View. I can write unit tests for Model \u0026amp; ViewModel without referencing View. In future, many new modules will be integrated to project. Considering all these requirement, I will consider MVVM.\n","permalink":"https://inderpalaulakh.com/posts/mvcmvvm/","summary":"\u003cp\u003eRecently, I developed an Android application. The application was developed focusing on simplicity. The application was small thus skipped writing unit tests. I know skipping the unit tests is not a good practice.\u003c/p\u003e\n\u003cp\u003eIn past, I was working on backend projects where tons of unit tests exists for API\u0026rsquo;s. I am new to application development and spent some time to learn about \u003ccode\u003eMVC\u003c/code\u003e and \u003ccode\u003eMVVM\u003c/code\u003e design patterns.\u003c/p\u003e\n\u003cp\u003eFor next project, the preference is \u003ccode\u003eMVVM\u003c/code\u003e. At end of this post I will share the reason to choose \u003ccode\u003eMVVM\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eThe example code for this post is written for Android application.\u003c/p\u003e\n\u003ch2 id=\"mvc-model-view-controller\"\u003eMVC (Model-View-Controller)\u003c/h2\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"../images/mvc.jpg\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eModel\u003c/strong\u003e: Model is data layer. Model call services or database to get data from external systems.\u003cbr/\u003e\n\u003cstrong\u003eView\u003c/strong\u003e: View is user interface layer.\u003cbr/\u003e\n\u003cstrong\u003eController\u003c/strong\u003e: Controller is triggered first. Controller has reference to Model as well as View. Controller get data from Model and send to View.\u003cbr/\u003e\u003c/p\u003e","title":"MVC \u0026 MVVM Android Design Pattern (Android)"},{"content":"We can make our code snippets more interesting and readable by sharing code with color formatting.\nTo turn on colors, just add language short name 😉\nFor C# code, add cs after ```.\n```cs\nwrite your code here\n```\nExample:\nstatic void Main(string[] args) { Logging logger = new Logging(); logger.Log(\u0026#34;login success\u0026#34;); } ","permalink":"https://inderpalaulakh.com/posts/colorcode/","summary":"\u003cp\u003eWe can make our code snippets more interesting and readable by sharing code with color formatting.\u003c/p\u003e\n\u003cp\u003eTo turn on colors, just add language short name 😉\u003c/p\u003e\n\u003cp\u003eFor \u003ccode\u003eC#\u003c/code\u003e code, add \u003ccode\u003ecs\u003c/code\u003e after ```.\u003c/p\u003e\n\u003cp\u003e```cs\u003c/p\u003e\n\u003cp\u003ewrite your code here\u003c/p\u003e\n\u003cp\u003e```\u003c/p\u003e\n\u003cp\u003eExample:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-cs\" data-lang=\"cs\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e Main(\u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e[] args)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            Logging logger = \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Logging();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            logger.Log(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;login success\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Coding blog with colored code snippets(.md posts)"},{"content":"This design patterns guides to create a wrap around existing class to reuse existing class for a new requirement.\nAssume, I have two logging classes named WriteLogsToLocalFile and WriteLogsToServer.\nclass WriteLogsToLocalFile { public void Log(string fileName, string message) { //write logs to file } } class WriteLogsToServer { public void Log(string urL, string message, string token) { //call rest API with oAuth // Note: here token is used for oAuth } } static void Main(string[] args) { WriteLogsToLocalFile fileLogs = new WriteLogsToLocalFile(); fileLogs.Log(\u0026#34;hello.xml\u0026#34;, \u0026#34;login success\u0026#34;); WriteLogsToServer serverLogs = new WriteLogsToServer(); serverLogs.Log(\u0026#34;https://server.logs/upload\u0026#34;, \u0026#34;login success\u0026#34;, \u0026#34;oAuthToken\u0026#34;); } Here user is manually creating objects to write logs separately to local file and server.My requirement is to create a common class for logging, so that client can call common class. The common class should blindly recurse through list of loggers to log message.\nIn below code, a new interface ILog is not compatible with WriteLogsToLocalFile and WriteLogsToServer. We created WriteLogsToServerAdapter and WriteLogsToServerAdapter. Logging is helper class.\ninterface ILog { void Log(string message); } // this class can not implement interface thus created Adapter class WriteLogsToLocalFile { public void Log(string fileName, string message) { //write logs to file } } // this class can not implement interface thus created Adapter class WriteLogsToServer { public void Log(string urL, string message, string token) { //call rest API with oAuth // Note: here token is used for oAuth } } class WriteLogsToLocalFileAdapter : ILog { string location; WriteLogsToLocalFile fileLog = new WriteLogsToLocalFile(); public WriteLogsToLocalFileAdapter(string location) { this.location = location; } public void Log(string message) { fileLog.Log(this.location, message); } } class WriteLogsToServerAdapter: ILog { string oAuthToken; string location; WriteLogsToServer serverLogs = new WriteLogsToServer(); public WriteLogsToServerAdapter(string token, string location) { this.oAuthToken = token; this.location = location; } public void Log(string message) { serverLogs.Log(this.location, message, this.oAuthToken); } } class Logging { ILog fileLogs = new WriteLogsToLocalFileAdapter(\u0026#34;index.log\u0026#34;); ILog serverLogs = new WriteLogsToServerAdapter(\u0026#34;oAuthToken\u0026#34;, \u0026#34;apiPath\u0026#34;); public void Log(string message) { fileLogs.Log(message); serverLogs.Log(message); } } static void Main(string[] args) { Logging logger = new Logging(); logger.Log(\u0026#34;login success\u0026#34;); } ","permalink":"https://inderpalaulakh.com/posts/adapterdesignpattern/","summary":"\u003cp\u003eThis design patterns guides to create a wrap around existing class to reuse existing class for a new requirement.\u003c/p\u003e\n\u003cp\u003eAssume, I have two logging classes named \u003ccode\u003eWriteLogsToLocalFile\u003c/code\u003e and \u003ccode\u003eWriteLogsToServer\u003c/code\u003e.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eclass WriteLogsToLocalFile\n        {\n            public void Log(string fileName, string message)\n            {\n                //write logs to file \n            }\n        }\n\n        class WriteLogsToServer\n        {\n            public void Log(string urL, string message, string token)\n            {\n                //call rest API with oAuth \n                // Note: here token is used for oAuth\n            }\n        }\n\n        static void Main(string[] args)\n        {\n            WriteLogsToLocalFile fileLogs = new WriteLogsToLocalFile();\n            fileLogs.Log(\u0026#34;hello.xml\u0026#34;, \u0026#34;login success\u0026#34;);\n\n            WriteLogsToServer serverLogs = new WriteLogsToServer();\n            serverLogs.Log(\u0026#34;https://server.logs/upload\u0026#34;, \u0026#34;login success\u0026#34;, \u0026#34;oAuthToken\u0026#34;);\n        }\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eHere user is manually creating objects to write logs separately to local file and server.My requirement is to create a common class for logging, so that client can call common class. The common class should blindly recurse through list of loggers to log message.\u003c/p\u003e\n\u003cp\u003eIn below code, a new interface \u003ccode\u003eILog\u003c/code\u003e is not compatible with \u003ccode\u003eWriteLogsToLocalFile\u003c/code\u003e and \u003ccode\u003eWriteLogsToServer\u003c/code\u003e. We created \u003ccode\u003eWriteLogsToServerAdapter\u003c/code\u003e and \u003ccode\u003eWriteLogsToServerAdapter\u003c/code\u003e. \u003ccode\u003eLogging\u003c/code\u003e is helper class.\u003c/p\u003e","title":"Adapter Design Pattern"},{"content":"Code reviews plays an important role to keep code consistent and readable. Code reviews are conducted to maintain quality and simplicity. The bugs should be taken care by automated tests. Code reviews are the best way to learn coding skills from your team members.\nIn this post, I want to share my opinion on how to write code reviews comments. I read a document Google code review. This document is really helpful to write code reviews comments and how to fix, reply on code review comments.\nThe variable name, function name or class name style formatting This type of comments should be taken care by compile time code validation. For example, Android has checkstyle.\nRename class or variable names When we are suggesting someone to rename something in our code, maybe we can express or thoughts by: why to change name? what are the suggested names?\nCode Refactoring This is especially important part of code review. When you request someone to change approach, please always share the benefits of suggested approach. What is new approach? How new approach benefits over existing approach?\n","permalink":"https://inderpalaulakh.com/posts/codereview/","summary":"\u003cp\u003eCode reviews plays an important role to keep code consistent and readable. Code reviews are conducted to maintain quality and simplicity. The bugs should be taken care by automated tests. Code reviews are the best way to learn coding skills from your team members.\u003c/p\u003e\n\u003cp\u003eIn this post, I want to share my opinion on how to write code reviews comments. I read a document \u003ca href=\"https://google.github.io/eng-practices/review/reviewer/comments.html\"\u003eGoogle code review\u003c/a\u003e. This document is really helpful to write code reviews comments and how to fix, reply on code review comments.\u003c/p\u003e\n\u003ch2 id=\"the-variable-name-function-name-or-class-name-style-formatting\"\u003eThe variable name, function name or class name style formatting\u003c/h2\u003e\n\u003cp\u003eThis type of comments should be taken care by compile time code validation. For example, \u003ccode\u003eAndroid\u003c/code\u003e has \u003ccode\u003echeckstyle\u003c/code\u003e.\u003c/p\u003e\n\u003ch2 id=\"rename-class-or-variable-names\"\u003eRename class or variable names\u003c/h2\u003e\n\u003cp\u003eWhen we are suggesting someone to rename something in our code, maybe we can express or thoughts by:\nwhy to change name?\nwhat are the suggested names?\u003c/p\u003e","title":"Code Review"},{"content":"The Composite Design pattern is structural design pattern. This design pattern is used when we want to treat a group of objects in same way. The composite design pattern has following elements.\nComponent This is a class that contain all the members that needs to be implemented by all the objects.\nComposite This class is used to add, remove and traverse components.\nLeaf The leaf object in tree structure is defined as leaf element.\nCode Sample I want to print salaries of all employees in my organization with names and designation. The root of organization tree is CEO. The CEO has directors as child composite. The director has managers as child composite. Finally, engineers at level 1 as leaf because no one is reporting them.\n// ignore this, just to print static int i = 0; interface IComponent { void print(); } class Composite : IComponent { private string name; private string designation; private decimal salary; private List\u0026lt;IComponent\u0026gt; listComponent = new List\u0026lt;IComponent\u0026gt;(); public Composite(String name, String designation, decimal salary) { this.name = name; this.designation = designation; this.salary = salary; } public void addComponent(IComponent component) { listComponent.Add(component); } public void printDesignation() { Console.Write(designation); Console.Write(\u0026#34; \u0026#34;); } public void printName() { Console.Write(name); Console.Write(\u0026#34; \u0026#34;); } public void printSalary() { Console.Write(salary); Console.Write(\u0026#34; \u0026#34;); } public void print() { printName(); printDesignation(); printSalary(); Console.WriteLine(\u0026#34; \u0026#34;); i++; foreach (var component in listComponent) { for(int k =0;k \u0026lt;i; k++) { Console.Write(\u0026#34; - \u0026#34;); } component.print(); } } } class Leaf : IComponent { private string name; private string designation; private decimal salary; public Leaf(String name, String designation, decimal salary) { this.name = name; this.designation = designation; this.salary = salary; } public void print() { printName(); printDesignation(); printSalary(); Console.WriteLine(\u0026#34; \u0026#34;); } public void printDesignation() { Console.Write(designation); Console.Write(\u0026#34; \u0026#34;); } public void printName() { Console.Write(name); Console.Write(\u0026#34; \u0026#34;); } public void printSalary() { Console.Write(salary); Console.Write(\u0026#34; \u0026#34;); } } static void Main(string[] args) { Leaf ram = new Leaf(\u0026#34;Ram\u0026#34;, \u0026#34;SE1\u0026#34;, 1000000); Leaf sham = new Leaf(\u0026#34;Sham\u0026#34;, \u0026#34;SE1\u0026#34;, 1000000); Composite teamLead = new Composite(\u0026#34;Mohan\u0026#34;, \u0026#34;Team Lead\u0026#34;, 1000000); teamLead.addComponent(ram); teamLead.addComponent(sham); Composite manager = new Composite(\u0026#34;John\u0026#34;, \u0026#34;Manager\u0026#34;, 1000000); manager.addComponent(teamLead); Composite director = new Composite(\u0026#34;kuku\u0026#34;, \u0026#34;Director\u0026#34;, 1000000); director.addComponent(manager); //traverse through all director.print(); } } Output:\nkuku Director 1000000 - John Manager 1000000 - - Mohan Team Lead 1000000 - - - Ram SE1 1000000 - - - Sham SE1 1000000 ","permalink":"https://inderpalaulakh.com/posts/compositedesignpattern/","summary":"\u003cp\u003eThe Composite Design pattern is structural design pattern. This design pattern is used when we want to treat a group of objects in same way. The composite design pattern has following elements.\u003c/p\u003e\n\u003ch3 id=\"component\"\u003eComponent\u003c/h3\u003e\n\u003cp\u003eThis is a class that contain all the members that needs to be implemented by all the objects.\u003c/p\u003e\n\u003ch3 id=\"composite\"\u003eComposite\u003c/h3\u003e\n\u003cp\u003eThis class is used to add, remove and traverse components.\u003c/p\u003e\n\u003ch3 id=\"leaf\"\u003eLeaf\u003c/h3\u003e\n\u003cp\u003eThe leaf object in tree structure is defined as leaf element.\u003c/p\u003e\n\u003ch2 id=\"code-sample\"\u003eCode Sample\u003c/h2\u003e\n\u003cp\u003eI want to print salaries of all employees in my organization with names and designation. The root of organization tree is CEO. The CEO has directors as child composite. The director has managers as child composite. Finally, engineers at level 1 as leaf because no one is reporting them.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e        // ignore this, just to print \n        static int i = 0;\n\n        interface IComponent\n        {\n            void print();\n        }\n\n\n        class Composite : IComponent\n        {\n            private string name;\n            private string designation;\n            private decimal salary;\n            private List\u0026lt;IComponent\u0026gt; listComponent = new List\u0026lt;IComponent\u0026gt;();\n\n            public Composite(String name, String designation, decimal salary)\n            {\n                this.name = name;\n                this.designation = designation;\n                this.salary = salary;\n            }\n\n            public void addComponent(IComponent component)\n            {\n                listComponent.Add(component);\n            }\n\n            public void printDesignation()\n            {\n                Console.Write(designation);\n                Console.Write(\u0026#34; \u0026#34;);\n            }\n\n            public void printName()\n            {\n                Console.Write(name);\n                Console.Write(\u0026#34; \u0026#34;);\n\n            }\n\n            public void printSalary()\n            {\n                Console.Write(salary);\n                Console.Write(\u0026#34; \u0026#34;);\n\n            }\n\n            public void print()\n            {\n                printName();\n                printDesignation();\n                printSalary();\n                Console.WriteLine(\u0026#34; \u0026#34;);\n                i++;\n\n                foreach (var component in listComponent)\n                {\n                    for(int k =0;k \u0026lt;i; k++)\n                    {\n                        Console.Write(\u0026#34; - \u0026#34;);\n                    }\n                    component.print();\n\n                }\n            }\n        }\n\n        class Leaf : IComponent\n        {\n            private string name;\n            private string designation;\n            private decimal salary;\n\n            public Leaf(String name, String designation, decimal salary)\n            {\n                this.name = name;\n                this.designation = designation;\n                this.salary = salary;\n            }\n\n            public void print()\n            {\n                printName();\n                printDesignation();\n                printSalary();\n                Console.WriteLine(\u0026#34; \u0026#34;);\n            }\n\n            public void printDesignation()\n            {\n                Console.Write(designation);\n                Console.Write(\u0026#34; \u0026#34;);\n\n            }\n\n            public void printName()\n            {\n                Console.Write(name);\n                Console.Write(\u0026#34; \u0026#34;);\n\n            }\n\n            public void printSalary()\n            {\n                Console.Write(salary);\n                Console.Write(\u0026#34; \u0026#34;);\n\n            }\n        }\n\n\n\n\n        static void Main(string[] args)\n        {\n            Leaf ram = new Leaf(\u0026#34;Ram\u0026#34;, \u0026#34;SE1\u0026#34;, 1000000);\n            Leaf sham = new Leaf(\u0026#34;Sham\u0026#34;, \u0026#34;SE1\u0026#34;, 1000000);\n\n            Composite teamLead = new Composite(\u0026#34;Mohan\u0026#34;, \u0026#34;Team Lead\u0026#34;, 1000000);\n            teamLead.addComponent(ram);\n            teamLead.addComponent(sham);\n\n            Composite manager = new Composite(\u0026#34;John\u0026#34;, \u0026#34;Manager\u0026#34;, 1000000);\n            manager.addComponent(teamLead);\n\n            Composite director = new Composite(\u0026#34;kuku\u0026#34;, \u0026#34;Director\u0026#34;, 1000000);\n            director.addComponent(manager);\n\n            //traverse through all\n            director.print();\n        }\n    }\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eOutput:\u003c/p\u003e","title":"Composite Design Pattern"},{"content":"In this post, I am writing about how to setup Azure Active Directory Android application login to access Azure functions protected with Azure Active Directory authentication.\nCreate an Android Application Open Android Studio and create new Project with Empty Activity.\nConfigure project with below settings\nGet SHA1 \u0026amp; package name Open powershell and cd to C:\\Users\u0026lt;username\u0026gt;.android Execute below command, if prompted for password enter android or leave blank\nkeytool -list -v -keystore debug.keystore -alias androiddebugkey -storepass android -keypass android Copy SHA1 -\u0026gt; Navigate to https://base64.guru/converter/encode/hex and convert SHA1 to Base64\nCopy package name from AndroidManifest.xml\nNow you have packagename \u0026amp; Base64 SHA1 hash\nSetup Azure Active Directory I followed steps from Register your app under Azure Active Directory (using Android platform settings) to setup AAD.\nLogin to Azure\nOpen AAD\nClick App Registration -\u0026gt; New Registration\nSelect Authentication\nSelect Add a platform\nEnter SHA1 Hash \u0026amp; package name\nCopy Android Configuration Android App Login \u0026amp; Logout implementation I followed steps from Configure your App Service or Azure Functions app to use Azure AD login\nEdit build.gradle and add\nimplementation \u0026#39;com.microsoft.identity.client:msal:1.4.+\u0026#39; packagingOptions{ exclude(\u0026#34;META-INF/jersey-module-version\u0026#34;) } Edit build.gradle and add\n\u0026lt;activity android:name=\u0026#34;com.microsoft.identity.client.BrowserTabActivity\u0026#34;\u0026gt; \u0026lt;intent-filter\u0026gt; \u0026lt;action android:name=\u0026#34;android.intent.action.VIEW\u0026#34; /\u0026gt; \u0026lt;category android:name=\u0026#34;android.intent.category.DEFAULT\u0026#34; /\u0026gt; \u0026lt;category android:name=\u0026#34;android.intent.category.BROWSABLE\u0026#34; /\u0026gt; \u0026lt;data android:scheme=\u0026#34;msauth\u0026#34; android:host=\u0026#34;com.example.********\u0026#34; android:path=\u0026#34;/GH**********I=\u0026#34; /\u0026gt; \u0026lt;/intent-filter\u0026gt; \u0026lt;/activity\u0026gt; Configure auth_config_single_account.json as below Edit activity_main.xml and add\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt; \u0026lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\u0026#34;http://schemas.android.com/apk/res/android\u0026#34; xmlns:app=\u0026#34;http://schemas.android.com/apk/res-auto\u0026#34; xmlns:tools=\u0026#34;http://schemas.android.com/tools\u0026#34; android:layout_width=\u0026#34;match_parent\u0026#34; android:layout_height=\u0026#34;match_parent\u0026#34; tools:context=\u0026#34;.MainActivity\u0026#34;\u0026gt; \u0026lt;Button android:id=\u0026#34;@+id/loginButton\u0026#34; android:layout_width=\u0026#34;wrap_content\u0026#34; android:layout_height=\u0026#34;wrap_content\u0026#34; android:layout_marginStart=\u0026#34;157dp\u0026#34; android:layout_marginTop=\u0026#34;46dp\u0026#34; android:layout_marginEnd=\u0026#34;161dp\u0026#34; android:text=\u0026#34;Login\u0026#34; app:layout_constraintEnd_toEndOf=\u0026#34;parent\u0026#34; app:layout_constraintStart_toStartOf=\u0026#34;parent\u0026#34; app:layout_constraintTop_toTopOf=\u0026#34;parent\u0026#34; /\u0026gt; \u0026lt;Button android:id=\u0026#34;@+id/signoutButton\u0026#34; android:layout_width=\u0026#34;wrap_content\u0026#34; android:layout_height=\u0026#34;wrap_content\u0026#34; android:layout_marginStart=\u0026#34;153dp\u0026#34; android:layout_marginTop=\u0026#34;82dp\u0026#34; android:layout_marginEnd=\u0026#34;159dp\u0026#34; android:text=\u0026#34;Signout\u0026#34; app:layout_constraintEnd_toEndOf=\u0026#34;parent\u0026#34; app:layout_constraintStart_toStartOf=\u0026#34;parent\u0026#34; app:layout_constraintTop_toBottomOf=\u0026#34;@+id/loginButton\u0026#34; /\u0026gt; \u0026lt;/androidx.constraintlayout.widget.ConstraintLayout\u0026gt; Edit MainActivity.java and add\npackage com.example.logintestaad; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import com.microsoft.identity.client.AuthenticationCallback; import com.microsoft.identity.client.IAccount; import com.microsoft.identity.client.IAuthenticationResult; import com.microsoft.identity.client.IPublicClientApplication; import com.microsoft.identity.client.ISingleAccountPublicClientApplication; import com.microsoft.identity.client.PublicClientApplication; import com.microsoft.identity.client.exception.MsalException; public class MainActivity extends AppCompatActivity { Button signInButton; Button signOutButton; private final static String[] SCOPES = {\u0026#34;Files.Read\u0026#34;}; private ISingleAccountPublicClientApplication mSingleAccountApp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); signInButton = findViewById(R.id.loginButton); signOutButton = findViewById(R.id.signoutButton); signInButton.setVisibility(View.GONE); signOutButton.setVisibility(View.GONE); //Sign in user signInButton.setOnClickListener(new View.OnClickListener(){ public void onClick(View v) { if (mSingleAccountApp == null) { return; } mSingleAccountApp.signIn(MainActivity.this, null, SCOPES, getAuthInteractiveCallback()); } }); //Sign out user signOutButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mSingleAccountApp == null){ return; } mSingleAccountApp.signOut(new ISingleAccountPublicClientApplication.SignOutCallback() { @Override public void onSignOut() { signInButton.setVisibility(View.VISIBLE); signOutButton.setVisibility(View.GONE); } @Override public void onError(@NonNull MsalException exception){ } }); } }); PublicClientApplication.createSingleAccountPublicClientApplication(getApplicationContext(), R.raw.auth_config_single_account, new IPublicClientApplication.ISingleAccountApplicationCreatedListener() { @Override public void onCreated(ISingleAccountPublicClientApplication application) { mSingleAccountApp = application; loadAccount(); } @Override public void onError(MsalException exception) { // displayError(exception); } }); } private AuthenticationCallback getAuthInteractiveCallback() { return new AuthenticationCallback() { @Override public void onSuccess(IAuthenticationResult authenticationResult) { signInButton.setVisibility(View.GONE); signOutButton.setVisibility(View.VISIBLE); } @Override public void onError(MsalException exception) { /* Failed to acquireToken */ } @Override public void onCancel() { } }; } private void loadAccount() { if (mSingleAccountApp == null) { return; } mSingleAccountApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback() { @Override public void onAccountLoaded(@Nullable IAccount activeAccount) { // You can use the account data to update your UI or your app database. if(activeAccount == null) { signInButton.setVisibility(View.VISIBLE); signOutButton.setVisibility(View.GONE); } else { signOutButton.setVisibility(View.GONE); signInButton.setVisibility(View.VISIBLE); } } @Override public void onAccountChanged(@Nullable IAccount priorAccount, @Nullable IAccount currentAccount) { if (currentAccount == null) { // Perform a cleanup task as the signed-in account changed. } } @Override public void onError(@NonNull MsalException exception) { } }); } } Run application, you should be able to login \u0026amp; Logout\nCreating \u0026amp; Publishing Azure Function Follow below documents to setup Azure Function using Visual Studio or Visual Studio Code.\nDevelop Azure Functions by using Visual Studio Code Develop Azure Functions by using Visual Studio Code\nOnce Azure function is hosted, verify the URL response in browser.\nhttps://\u0026lt;yourfunctionanme\u0026gt;.azurewebsites.net/api/\u0026lt;functionparameter\u0026gt;\nProtect Azure Function with Azure Active Directory Authentication Follow document Configure your App Service or Azure Functions app to use Azure AD login\nOpen function in Azure and select Authentication\nEnable On\nSelect Log in with Azure Active Directory for Action to take when request is not authenticated\nClick Azure Active Directory as Authentication Provider\nClick Advanced\nEnter client id from andridLoginTest Azure Directory Application setup (Setup Azure Active Directory)\nEnter Issuer Url as https://sts.windows.net/\u0026lt;tokenid\u0026gt;\nClick Allowed Token Audience and add your function URL (do not add / or api/, just base URL)\nSetup Azure Active Directory (AAD) API Expose and Scopes Open Azure Active Directory\nSelect Branding and setup Home page URL to Azure Function\nClick Expose an API -\u0026gt; Add a scope -\u0026gt; set Application ID URI to Azure function URI(https://.azurewebsites.net) -\u0026gt; Save and Continue\nIn next window Add a scope -\u0026gt; set Scope name as apiaccess-\u0026gt; select Admins and users -\u0026gt; Enter anything in consent name and description\nClick API permissions -\u0026gt; Add a Permission -\u0026gt; My API's -\u0026gt; select Name of API (scope name -\u0026gt; apiaccess)-\u0026gt; Add Permission -\u0026gt; Grant admin consent for Default -\u0026gt; yes-\u0026gt;save-\u0026gt;grant admin consent-\u0026gt;yes\nAndroid App Calling function Edit build.gradle and add\nimplementation \u0026#39;com.android.volley:volley:1.1.1\u0026#39; Edit AndroidManifest.xml and add\n\u0026lt;uses-permission android:name=\u0026#34;android.permission.INTERNET\u0026#34; /\u0026gt; Replace MainActivity.java\npackage com.example.logintestaad; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import com.android.volley.AuthFailureError; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; import com.microsoft.identity.client.AuthenticationCallback; import com.microsoft.identity.client.IAccount; import com.microsoft.identity.client.IAuthenticationResult; import com.microsoft.identity.client.IPublicClientApplication; import com.microsoft.identity.client.ISingleAccountPublicClientApplication; import com.microsoft.identity.client.PublicClientApplication; import com.microsoft.identity.client.exception.MsalException; import com.android.volley.RequestQueue; import java.util.HashMap; import java.util.Map; public class MainActivity extends AppCompatActivity { private final static String[] SCOPES = {\u0026#34;https://androidaccessfunctiontest20210122095133.azurewebsites.net/apiaccess\u0026#34;}; Button signInButton; Button signOutButton; private ISingleAccountPublicClientApplication mSingleAccountApp; private RequestQueue queue; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); signInButton = findViewById(R.id.loginButton); signOutButton = findViewById(R.id.signoutButton); signInButton.setVisibility(View.GONE); signOutButton.setVisibility(View.GONE); //Sign in user signInButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (mSingleAccountApp == null) { return; } mSingleAccountApp.signIn(MainActivity.this, null, SCOPES, getAuthInteractiveCallback()); } }); //Sign out user signOutButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mSingleAccountApp == null) { return; } mSingleAccountApp.signOut(new ISingleAccountPublicClientApplication.SignOutCallback() { @Override public void onSignOut() { signInButton.setVisibility(View.VISIBLE); signOutButton.setVisibility(View.GONE); } @Override public void onError(@NonNull MsalException exception) { } }); } }); PublicClientApplication.createSingleAccountPublicClientApplication(getApplicationContext(), R.raw.auth_config_single_account, new IPublicClientApplication.ISingleAccountApplicationCreatedListener() { @Override public void onCreated(ISingleAccountPublicClientApplication application) { mSingleAccountApp = application; loadAccount(); } @Override public void onError(MsalException exception) { // displayError(exception); } }); } private AuthenticationCallback getAuthInteractiveCallback() { return new AuthenticationCallback() { @Override public void onSuccess(IAuthenticationResult authenticationResult) { signInButton.setVisibility(View.GONE); signOutButton.setVisibility(View.VISIBLE); String token = authenticationResult.getAccessToken(); String tokenGenerationAddress = \u0026#34;https://androidaccessfunctiontest20210122095133.azurewebsites.net/api/callme\u0026#34;; //cal azure function with access token queue = Volley.newRequestQueue(getApplicationContext()); StringRequest stringRequest = new StringRequest(Request.Method.GET, tokenGenerationAddress, new Response.Listener\u0026lt;String\u0026gt;() { @Override public void onResponse(String response) { String text = response; } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { //textView.setText(\u0026#34;That didn\u0026#39;t work!\u0026#34;); } }) { @Override public Map\u0026lt;String, String\u0026gt; getHeaders() throws AuthFailureError { HashMap\u0026lt;String, String\u0026gt; headers = new HashMap\u0026lt;String, String\u0026gt;(); headers.put(\u0026#34;Authorization\u0026#34;, \u0026#34;Bearer \u0026#34; + token); return headers; } }; queue.add(stringRequest); } @Override public void onError(MsalException exception) { } @Override public void onCancel() { } }; } private void loadAccount() { if (mSingleAccountApp == null) { return; } mSingleAccountApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback() { @Override public void onAccountLoaded(@Nullable IAccount activeAccount) { // You can use the account data to update your UI or your app database. if (activeAccount == null) { signInButton.setVisibility(View.VISIBLE); signOutButton.setVisibility(View.GONE); } else { signOutButton.setVisibility(View.VISIBLE); signInButton.setVisibility(View.GONE); } } @Override public void onAccountChanged(@Nullable IAccount priorAccount, @Nullable IAccount currentAccount) { if (currentAccount == null) { // Perform a cleanup task as the signed-in account changed. } } @Override public void onError(@NonNull MsalException exception) { } }); } } Finally, debug code, you should be able to see response from Azure function.\n","permalink":"https://inderpalaulakh.com/posts/azureaad/","summary":"\u003cp\u003eIn this post, I am writing about how to setup Azure Active Directory Android application login to access Azure functions protected with Azure Active Directory authentication.\u003c/p\u003e\n\u003ch2 id=\"create-an-android-application\"\u003eCreate an Android Application\u003c/h2\u003e\n\u003cp\u003eOpen Android Studio and create new Project with Empty Activity.\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"../images/androidappcreation.png\"\u003e\u003c/p\u003e\n\u003cp\u003eConfigure project with below settings\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"../images/configuringproject.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"get-sha1--package-name\"\u003eGet SHA1 \u0026amp; package name\u003c/h2\u003e\n\u003cp\u003eOpen powershell and cd to C:\\Users\u0026lt;username\u0026gt;.android\nExecute below command, if prompted for password enter \u003ccode\u003eandroid\u003c/code\u003e or leave blank\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ekeytool -list -v -keystore debug.keystore -alias androiddebugkey -storepass android -keypass android\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003cimg loading=\"lazy\" src=\"../images/gettingSHA.PNG\"\u003e\u003c/p\u003e\n\u003cp\u003eCopy SHA1 -\u0026gt; Navigate to \u003ca href=\"https://base64.guru/converter/encode/hex\"\u003ehttps://base64.guru/converter/encode/hex\u003c/a\u003e and convert SHA1 to Base64\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"../images/sha.PNG\"\u003e\u003c/p\u003e\n\u003cp\u003eCopy package name from \u003ccode\u003eAndroidManifest.xml\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eNow you have packagename \u0026amp; Base64 SHA1 hash\u003c/p\u003e\n\u003ch2 id=\"setup-azure-active-directory\"\u003eSetup Azure Active Directory\u003c/h2\u003e\n\u003cp\u003eI followed steps from \u003ca href=\"https://docs.microsoft.com/en-us/azure/active-directory/develop/tutorial-v2-android\"\u003eRegister your app under Azure Active Directory (using Android platform settings)\u003c/a\u003e to setup AAD.\u003c/p\u003e\n\u003cp\u003eLogin to Azure\u003cbr\u003e\nOpen \u003ccode\u003eAAD\u003c/code\u003e\u003cbr\u003e\nClick \u003ccode\u003eApp Registration\u003c/code\u003e -\u0026gt; \u003ccode\u003eNew Registration\u003c/code\u003e\u003cbr\u003e\n\u003cimg loading=\"lazy\" src=\"../images/newreg.PNG\"\u003e\u003cbr\u003e\nSelect \u003ccode\u003eAuthentication\u003c/code\u003e\u003cbr\u003e\nSelect \u003ccode\u003eAdd a platform\u003c/code\u003e\u003cbr\u003e\n\u003cimg loading=\"lazy\" src=\"../images/authsetup.PNG\"\u003e\u003cbr\u003e\nEnter \u003ccode\u003eSHA1 Hash\u003c/code\u003e \u0026amp; \u003ccode\u003epackage name\u003c/code\u003e\u003cbr\u003e\n\u003cimg loading=\"lazy\" src=\"../images/configure.PNG\"\u003e\u003cbr/\u003e\nCopy \u003ccode\u003eAndroid Configuration\u003c/code\u003e\u003cbr/\u003e\n\u003cimg loading=\"lazy\" src=\"../images/copyconfig.PNG\"\u003e\u003cbr\u003e\u003c/p\u003e","title":"Android Application implementing Azure Active Directory Authentication to call protected Azure Function "},{"content":"Checkstyle is a development tool to help programmers write Java code that adheres to a coding standard.\nSteps to enable checkstyle for Android Project Create checkstyle.xml Create folder checkstyle inside Android Project app folder. Create file checkstyle.xml Reference\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34;?\u0026gt; \u0026lt;!DOCTYPE module PUBLIC \u0026#34;-//Puppy Crawl//DTD Check Configuration 1.2//EN\u0026#34; \u0026#34;http://www.puppycrawl.com/dtds/configuration_1_2.dtd\u0026#34;\u0026gt; \u0026lt;!-- Checkstyle configuration that checks the sun coding conventions from: - the Java Language Specification at http://java.sun.com/docs/books/jls/second_edition/html/index.html - the Sun Code Conventions at http://java.sun.com/docs/codeconv/ - the Javadoc guidelines at http://java.sun.com/j2se/javadoc/writingdoccomments/index.html - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html - some best practices Checkstyle is very configurable. Be sure to read the documentation at http://checkstyle.sf.net (or in your downloaded distribution). Most Checks are configurable, be sure to consult the documentation. To completely disable a check, just comment it out or delete it from the file. Finally, it is worth reading the documentation. --\u0026gt; \u0026lt;module name=\u0026#34;Checker\u0026#34;\u0026gt; \u0026lt;!-- If you set the basedir property below, then all reported file names will be relative to the specified directory. See http://checkstyle.sourceforge.net/5.x/config.html#Checker \u0026lt;property name=\u0026#34;basedir\u0026#34; value=\u0026#34;${basedir}\u0026#34;/\u0026gt; --\u0026gt; \u0026lt;!-- Checks that a package-info.java file exists for each package. --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage --\u0026gt; \u0026lt;module name=\u0026#34;JavadocPackage\u0026#34;/\u0026gt; \u0026lt;!-- Checks whether files end with a new line. --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile --\u0026gt; \u0026lt;module name=\u0026#34;NewlineAtEndOfFile\u0026#34;/\u0026gt; \u0026lt;!-- Checks that property files contain the same keys. --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_misc.html#Translation --\u0026gt; \u0026lt;module name=\u0026#34;Translation\u0026#34;/\u0026gt; \u0026lt;!-- Checks for Size Violations. --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_sizes.html --\u0026gt; \u0026lt;module name=\u0026#34;FileLength\u0026#34;/\u0026gt; \u0026lt;!-- Checks for whitespace --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_whitespace.html --\u0026gt; \u0026lt;module name=\u0026#34;FileTabCharacter\u0026#34;/\u0026gt; \u0026lt;!-- Miscellaneous other checks. --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_misc.html --\u0026gt; \u0026lt;module name=\u0026#34;RegexpSingleline\u0026#34;\u0026gt; \u0026lt;property name=\u0026#34;format\u0026#34; value=\u0026#34;\\s+$\u0026#34;/\u0026gt; \u0026lt;property name=\u0026#34;minimum\u0026#34; value=\u0026#34;0\u0026#34;/\u0026gt; \u0026lt;property name=\u0026#34;maximum\u0026#34; value=\u0026#34;0\u0026#34;/\u0026gt; \u0026lt;property name=\u0026#34;message\u0026#34; value=\u0026#34;Line has trailing spaces.\u0026#34;/\u0026gt; \u0026lt;/module\u0026gt; \u0026lt;module name=\u0026#34;TreeWalker\u0026#34;\u0026gt; \u0026lt;!-- Checks for Javadoc comments. --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_javadoc.html --\u0026gt; \u0026lt;module name=\u0026#34;JavadocMethod\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;JavadocType\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;JavadocVariable\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;JavadocStyle\u0026#34;/\u0026gt; \u0026lt;!-- Checks for Naming Conventions. --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_naming.html --\u0026gt; \u0026lt;module name=\u0026#34;ConstantName\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;LocalFinalVariableName\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;LocalVariableName\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;MemberName\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;MethodName\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;PackageName\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;ParameterName\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;StaticVariableName\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;TypeName\u0026#34;/\u0026gt; \u0026lt;!-- Checks for Headers --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_header.html --\u0026gt; \u0026lt;!-- \u0026lt;module name=\u0026#34;Header\u0026#34;\u0026gt; --\u0026gt; \u0026lt;!-- The follow property value demonstrates the ability --\u0026gt; \u0026lt;!-- to have access to ANT properties. In this case it uses --\u0026gt; \u0026lt;!-- the ${basedir} property to allow Checkstyle to be run --\u0026gt; \u0026lt;!-- from any directory within a project. See property --\u0026gt; \u0026lt;!-- expansion, --\u0026gt; \u0026lt;!-- http://checkstyle.sf.net/config.html#properties --\u0026gt; \u0026lt;!-- \u0026lt;property --\u0026gt; \u0026lt;!-- name=\u0026#34;headerFile\u0026#34; --\u0026gt; \u0026lt;!-- value=\u0026#34;${basedir}/java.header\u0026#34;/\u0026gt; --\u0026gt; \u0026lt;!-- \u0026lt;/module\u0026gt; --\u0026gt; \u0026lt;!-- Following interprets the header file as regular expressions. --\u0026gt; \u0026lt;!-- \u0026lt;module name=\u0026#34;RegexpHeader\u0026#34;/\u0026gt; --\u0026gt; \u0026lt;!-- Checks for imports --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_import.html --\u0026gt; \u0026lt;module name=\u0026#34;AvoidStarImport\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;IllegalImport\u0026#34;/\u0026gt; \u0026lt;!-- defaults to sun.* packages --\u0026gt; \u0026lt;module name=\u0026#34;RedundantImport\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;UnusedImports\u0026#34;/\u0026gt; \u0026lt;!-- Checks for Size Violations. --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_sizes.html --\u0026gt; \u0026lt;module name=\u0026#34;LineLength\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;MethodLength\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;ParameterNumber\u0026#34;/\u0026gt; \u0026lt;!-- Checks for whitespace --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_whitespace.html --\u0026gt; \u0026lt;module name=\u0026#34;EmptyForIteratorPad\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;GenericWhitespace\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;MethodParamPad\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;NoWhitespaceAfter\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;NoWhitespaceBefore\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;OperatorWrap\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;ParenPad\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;TypecastParenPad\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;WhitespaceAfter\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;WhitespaceAround\u0026#34;/\u0026gt; \u0026lt;!-- Modifier Checks --\u0026gt; \u0026lt;!-- See http://checkstyle.sf.net/config_modifiers.html --\u0026gt; \u0026lt;module name=\u0026#34;ModifierOrder\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;RedundantModifier\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;AvoidNestedBlocks\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;EmptyBlock\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;LeftCurly\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;NeedBraces\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;RightCurly\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;AvoidInlineConditionals\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;DoubleCheckedLocking\u0026#34;/\u0026gt; \u0026lt;!-- MY FAVOURITE --\u0026gt; \u0026lt;module name=\u0026#34;EmptyStatement\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;EqualsHashCode\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;HiddenField\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;IllegalInstantiation\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;InnerAssignment\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;MagicNumber\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;MissingSwitchDefault\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;RedundantThrows\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;SimplifyBooleanExpression\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;SimplifyBooleanReturn\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;DesignForExtension\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;FinalClass\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;HideUtilityClassConstructor\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;InterfaceIsType\u0026#34;/\u0026gt; \u0026lt;module name=\u0026#34;VisibilityModifier\u0026#34;/\u0026gt; \u0026lt;/module\u0026gt; \u0026lt;/module\u0026gt; Create checkstyle.gradle Create checkstyle.gradle inside app folder (at same level where build.gradle exists)\napply plugin: \u0026#39;checkstyle\u0026#39; checkstyle { description: \u0026#39;code style check\u0026#39; group \u0026#39;verification\u0026#39; configFile file(\u0026#39;checkstyle/checkstyle.xml) } task checkstyle(type: Checkstyle, group: \u0026#39;verification\u0026#39;) { source \u0026#39;src\u0026#39; include \u0026#39;**/*.java\u0026#39; exclude \u0026#39;**/gen/**\u0026#39; exclude \u0026#39;**/R.java\u0026#39; classpath = files() } Enable checkstyle.gradle Edit build.gradle(Project:**) and add\nsubprojects { apply from:\u0026#34;checkstyle.gradle\u0026#34; afterEvaluate{ preBuild.dependsOn(\u0026#39;checkstyle\u0026#39;) check.dependsOn \u0026#39;checkstyle\u0026#39; } } Finally Run/Build application (preBuild.dependsOn('checkstyle') will force the build to fail if checkstyle finds any violation); or Open Terminal and execute gradle check --stacktrace\nYou can see HTML violations report at app/build/reports/checkstyle/checkstyle.html\n","permalink":"https://inderpalaulakh.com/posts/android-checkstyle/","summary":"\u003cp\u003e\u003ca href=\"https://github.com/checkstyle/checkstyle\"\u003eCheckstyle\u003c/a\u003e is a development tool to help programmers write Java code that adheres to a coding standard.\u003c/p\u003e\n\u003ch1 id=\"steps-to-enable-checkstyle-for-android-project\"\u003eSteps to enable checkstyle for Android Project\u003c/h1\u003e\n\u003ch2 id=\"create-checkstylexml\"\u003eCreate checkstyle.xml\u003c/h2\u003e\n\u003cp\u003eCreate folder \u003ccode\u003echeckstyle\u003c/code\u003e inside Android Project \u003ccode\u003eapp\u003c/code\u003e folder.\nCreate file checkstyle.xml \u003ca href=\"https://github.com/skeeto/sample-java-project/blob/master/checkstyle.xml\"\u003eReference\u003c/a\u003e\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e\u0026lt;?xml version=\u0026#34;1.0\u0026#34;?\u0026gt;\n\u0026lt;!DOCTYPE module PUBLIC\n    \u0026#34;-//Puppy Crawl//DTD Check Configuration 1.2//EN\u0026#34;\n    \u0026#34;http://www.puppycrawl.com/dtds/configuration_1_2.dtd\u0026#34;\u0026gt;\n\n\u0026lt;!--\n  Checkstyle configuration that checks the sun coding conventions from:\n    - the Java Language Specification at\n      http://java.sun.com/docs/books/jls/second_edition/html/index.html\n    - the Sun Code Conventions at http://java.sun.com/docs/codeconv/\n    - the Javadoc guidelines at\n      http://java.sun.com/j2se/javadoc/writingdoccomments/index.html\n    - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html\n    - some best practices\n  Checkstyle is very configurable. Be sure to read the documentation at\n  http://checkstyle.sf.net (or in your downloaded distribution).\n  Most Checks are configurable, be sure to consult the documentation.\n  To completely disable a check, just comment it out or delete it from the file.\n  Finally, it is worth reading the documentation.\n--\u0026gt;\n\n\u0026lt;module name=\u0026#34;Checker\u0026#34;\u0026gt;\n    \u0026lt;!--\n        If you set the basedir property below, then all reported file\n        names will be relative to the specified directory. See\n        http://checkstyle.sourceforge.net/5.x/config.html#Checker\n        \u0026lt;property name=\u0026#34;basedir\u0026#34; value=\u0026#34;${basedir}\u0026#34;/\u0026gt;\n    --\u0026gt;\n\n    \u0026lt;!-- Checks that a package-info.java file exists for each package.     --\u0026gt;\n    \u0026lt;!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage --\u0026gt;\n    \u0026lt;module name=\u0026#34;JavadocPackage\u0026#34;/\u0026gt;\n\n    \u0026lt;!-- Checks whether files end with a new line.                        --\u0026gt;\n    \u0026lt;!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile --\u0026gt;\n    \u0026lt;module name=\u0026#34;NewlineAtEndOfFile\u0026#34;/\u0026gt;\n\n    \u0026lt;!-- Checks that property files contain the same keys.         --\u0026gt;\n    \u0026lt;!-- See http://checkstyle.sf.net/config_misc.html#Translation --\u0026gt;\n    \u0026lt;module name=\u0026#34;Translation\u0026#34;/\u0026gt;\n\n    \u0026lt;!-- Checks for Size Violations.                    --\u0026gt;\n    \u0026lt;!-- See http://checkstyle.sf.net/config_sizes.html --\u0026gt;\n    \u0026lt;module name=\u0026#34;FileLength\u0026#34;/\u0026gt;\n\n    \u0026lt;!-- Checks for whitespace                               --\u0026gt;\n    \u0026lt;!-- See http://checkstyle.sf.net/config_whitespace.html --\u0026gt;\n    \u0026lt;module name=\u0026#34;FileTabCharacter\u0026#34;/\u0026gt;\n\n    \u0026lt;!-- Miscellaneous other checks.                   --\u0026gt;\n    \u0026lt;!-- See http://checkstyle.sf.net/config_misc.html --\u0026gt;\n    \u0026lt;module name=\u0026#34;RegexpSingleline\u0026#34;\u0026gt;\n       \u0026lt;property name=\u0026#34;format\u0026#34; value=\u0026#34;\\s+$\u0026#34;/\u0026gt;\n       \u0026lt;property name=\u0026#34;minimum\u0026#34; value=\u0026#34;0\u0026#34;/\u0026gt;\n       \u0026lt;property name=\u0026#34;maximum\u0026#34; value=\u0026#34;0\u0026#34;/\u0026gt;\n       \u0026lt;property name=\u0026#34;message\u0026#34; value=\u0026#34;Line has trailing spaces.\u0026#34;/\u0026gt;\n    \u0026lt;/module\u0026gt;\n\n    \u0026lt;module name=\u0026#34;TreeWalker\u0026#34;\u0026gt;\n\n        \u0026lt;!-- Checks for Javadoc comments.                     --\u0026gt;\n        \u0026lt;!-- See http://checkstyle.sf.net/config_javadoc.html --\u0026gt;\n        \u0026lt;module name=\u0026#34;JavadocMethod\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;JavadocType\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;JavadocVariable\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;JavadocStyle\u0026#34;/\u0026gt;\n\n\n        \u0026lt;!-- Checks for Naming Conventions.                  --\u0026gt;\n        \u0026lt;!-- See http://checkstyle.sf.net/config_naming.html --\u0026gt;\n        \u0026lt;module name=\u0026#34;ConstantName\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;LocalFinalVariableName\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;LocalVariableName\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;MemberName\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;MethodName\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;PackageName\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;ParameterName\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;StaticVariableName\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;TypeName\u0026#34;/\u0026gt;\n\n\n        \u0026lt;!-- Checks for Headers                                --\u0026gt;\n        \u0026lt;!-- See http://checkstyle.sf.net/config_header.html   --\u0026gt;\n        \u0026lt;!-- \u0026lt;module name=\u0026#34;Header\u0026#34;\u0026gt;                            --\u0026gt;\n            \u0026lt;!-- The follow property value demonstrates the ability     --\u0026gt;\n            \u0026lt;!-- to have access to ANT properties. In this case it uses --\u0026gt;\n            \u0026lt;!-- the ${basedir} property to allow Checkstyle to be run  --\u0026gt;\n            \u0026lt;!-- from any directory within a project. See property      --\u0026gt;\n            \u0026lt;!-- expansion,                                             --\u0026gt;\n            \u0026lt;!-- http://checkstyle.sf.net/config.html#properties        --\u0026gt;\n            \u0026lt;!-- \u0026lt;property                                              --\u0026gt;\n            \u0026lt;!--     name=\u0026#34;headerFile\u0026#34;                                  --\u0026gt;\n            \u0026lt;!--     value=\u0026#34;${basedir}/java.header\u0026#34;/\u0026gt;                   --\u0026gt;\n        \u0026lt;!-- \u0026lt;/module\u0026gt; --\u0026gt;\n\n        \u0026lt;!-- Following interprets the header file as regular expressions. --\u0026gt;\n        \u0026lt;!-- \u0026lt;module name=\u0026#34;RegexpHeader\u0026#34;/\u0026gt;                                --\u0026gt;\n\n\n        \u0026lt;!-- Checks for imports                              --\u0026gt;\n        \u0026lt;!-- See http://checkstyle.sf.net/config_import.html --\u0026gt;\n        \u0026lt;module name=\u0026#34;AvoidStarImport\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;IllegalImport\u0026#34;/\u0026gt; \u0026lt;!-- defaults to sun.* packages --\u0026gt;\n        \u0026lt;module name=\u0026#34;RedundantImport\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;UnusedImports\u0026#34;/\u0026gt;\n\n\n        \u0026lt;!-- Checks for Size Violations.                    --\u0026gt;\n        \u0026lt;!-- See http://checkstyle.sf.net/config_sizes.html --\u0026gt;\n        \u0026lt;module name=\u0026#34;LineLength\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;MethodLength\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;ParameterNumber\u0026#34;/\u0026gt;\n\n\n        \u0026lt;!-- Checks for whitespace                               --\u0026gt;\n        \u0026lt;!-- See http://checkstyle.sf.net/config_whitespace.html --\u0026gt;\n        \u0026lt;module name=\u0026#34;EmptyForIteratorPad\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;GenericWhitespace\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;MethodParamPad\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;NoWhitespaceAfter\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;NoWhitespaceBefore\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;OperatorWrap\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;ParenPad\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;TypecastParenPad\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;WhitespaceAfter\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;WhitespaceAround\u0026#34;/\u0026gt;\n\n\n        \u0026lt;!-- Modifier Checks                                    --\u0026gt;\n        \u0026lt;!-- See http://checkstyle.sf.net/config_modifiers.html --\u0026gt;\n        \u0026lt;module name=\u0026#34;ModifierOrder\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;RedundantModifier\u0026#34;/\u0026gt;\n\n        \u0026lt;module name=\u0026#34;AvoidNestedBlocks\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;EmptyBlock\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;LeftCurly\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;NeedBraces\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;RightCurly\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;AvoidInlineConditionals\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;DoubleCheckedLocking\u0026#34;/\u0026gt;    \u0026lt;!-- MY FAVOURITE --\u0026gt;\n        \u0026lt;module name=\u0026#34;EmptyStatement\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;EqualsHashCode\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;HiddenField\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;IllegalInstantiation\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;InnerAssignment\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;MagicNumber\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;MissingSwitchDefault\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;RedundantThrows\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;SimplifyBooleanExpression\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;SimplifyBooleanReturn\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;DesignForExtension\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;FinalClass\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;HideUtilityClassConstructor\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;InterfaceIsType\u0026#34;/\u0026gt;\n        \u0026lt;module name=\u0026#34;VisibilityModifier\u0026#34;/\u0026gt;\n\n    \u0026lt;/module\u0026gt;\n\n\u0026lt;/module\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"create-checkstylegradle\"\u003eCreate checkstyle.gradle\u003c/h2\u003e\n\u003cp\u003eCreate checkstyle.gradle inside app folder (at same level where build.gradle exists)\u003c/p\u003e","title":"Android Studio Enable Checkstyle (Gradle)"},{"content":"I use online tools to generate sequence diagrams. Recently, my colleague at work guided me about Mermaid to generate sequence diagrams. This is an awesome tool.\nMermaid\nMermaid has online editor Editor. However, I did not use online editor for confidentiality reasons.\nI created index.html and opened in browser.\n\u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;script src=\u0026#34;https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script\u0026gt; mermaid.initialize({ startOnLoad: true }); \u0026lt;/script\u0026gt; \u0026lt;div class=\u0026#34;mermaid\u0026#34;\u0026gt; sequenceDiagram participant A participant B A-\u0026gt;\u0026gt;B:How are you? B--\u0026gt;\u0026gt; A: I am good loop test loop A-\u0026gt;\u0026gt;B:How are you? B--\u0026gt;\u0026gt; A: I am good end \u0026lt;/div\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; ","permalink":"https://inderpalaulakh.com/posts/mermaid/","summary":"\u003cp\u003eI use online tools to generate sequence diagrams. Recently, my colleague at work guided me about Mermaid to generate sequence diagrams. This is an awesome tool.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://mermaid-js.github.io/mermaid/#/\"\u003eMermaid\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eMermaid has online editor \u003ca href=\"https://mermaid-js.github.io/mermaid-live-editor/#/edit/dW5kZWZpbmVk\"\u003eEditor\u003c/a\u003e. However, I did not use online editor for confidentiality reasons.\u003c/p\u003e\n\u003cp\u003eI created index.html and opened in browser.\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e\n\u0026lt;html\u0026gt;\n  \u0026lt;body\u0026gt;\n    \u0026lt;script src=\u0026#34;https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt;\n    \u0026lt;script\u0026gt;\n      mermaid.initialize({ startOnLoad: true });\n    \u0026lt;/script\u0026gt;\n    \u0026lt;div class=\u0026#34;mermaid\u0026#34;\u0026gt;\n\n      sequenceDiagram\n        participant A\n        participant B     \n        A-\u0026gt;\u0026gt;B:How are you?\n        B--\u0026gt;\u0026gt; A: I am good\n        loop test loop\n            A-\u0026gt;\u0026gt;B:How are you?\n            B--\u0026gt;\u0026gt; A: I am good\n        end\n    \u0026lt;/div\u0026gt;\n  \u0026lt;/body\u0026gt;\n\u0026lt;/html\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e","title":"Generation of Sequence Diagram using Mermaid"},{"content":"The year 2020 was a year of unpredicted event Covid-19. In January, my wife travelled to Toronto for her co-op and I planned to spend my evenings studying algorithms and software engineering concepts alongside full time job.\nI planned to complete most of the study-topics in March and completed as planned. In mid-March my office shared guidelines to work from home. My wife was also back from Toronto and started a co-op remotely.\nI saved two hours of commute time. My office had layoffs. Some of my teammates were laid off. It was a hard time to see teammates leaving, and I got worried about myself.\nI started to spend more time studying software engineering topics. Usually, I develop hobby projects using technologies I do not use as a part of my job. Because of Covid-19, I got much time to work on hobby projects to explore AWS and Azure infrastructures.\nMeanwhile, because of layoffs I started preparing for interviews and applied for jobs in June/July. My wife gifted me a LeetCode subscription for interview preparation.\nFinally, I received an offer from Microsoft in September and it was the happiest moment for me. I resigned from my job and joined Microsoft in October.\nI am interested to learn more about Software Architecture. Luckily, my mentor at my current job is guiding me to read books on topics to achieve my goal.\nThis year was a year of learning. Important learning for me from this year was to be ready for unplanned events like Covid-19. It taught me the value of time. Using commute time to study had fruitful results.\nEven though, 2020 will be remembered as a Covid-19 year, However, this is the year where technology contributed to achieve social communication, healthcare, personal and organizational goals.\nLearnings from 2020:-\nDo something useful in commute time (prodcast if driving :))\nBe in touch with the latest technologies\nBe healthy\nBlogging is good\nIn 2021, I will:-\nLeave fried food( Now I am 30 :) )\nContinue blogging to share my learning\nRead more books\nWill develop an app\n","permalink":"https://inderpalaulakh.com/posts/2020review/","summary":"\u003cp\u003eThe year 2020 was a year of unpredicted event Covid-19. In January, my wife travelled to Toronto for her co-op and I planned to spend my evenings studying algorithms and software engineering concepts alongside full time job.\u003c/p\u003e\n\u003cp\u003eI planned to complete most of the study-topics in March and completed as planned. In mid-March my office shared guidelines to work from home. My wife was also back from Toronto and started a co-op remotely.\u003c/p\u003e\n\u003cp\u003eI saved two hours of commute time. My office had layoffs. Some of my teammates were laid off.  It was a hard time to see teammates leaving, and I got worried about myself.\u003c/p\u003e\n\u003cp\u003eI started to spend more time studying software engineering topics. Usually, I develop hobby projects using technologies I do not use as a part of my job. Because of Covid-19, I got much time to work on hobby projects to explore AWS and Azure infrastructures.\u003c/p\u003e","title":"2020 Review"},{"content":"Recently, I struggled a bit to figure out a way to access Azure-Pipeline Variables in Node.js JavaScript/TypeScript project. However, it is easy.\n.yml Pipeline code - task: Npm@1 displayName: \u0026#34;Run project\u0026#34; env: MyVariableName: $(MYVARIABLENAME) // this is pipeline variable name, in Capital letters inputs: commands: \u0026#39;custom\u0026#39; CustomCommand: \u0026#39;run test\u0026#39; npm Package install package string-replace-loader\nTypeScript/JavaScript File Create a file with any name \u0026ldquo;test.ts\u0026rdquo;\ntest.ts const test = () =\u0026gt; { const myVariable = \u0026#34;My-Variable\u0026#34;; }; Setup webpack.config.js module: { rules: [ { test: /test\\.ts$/, loader: \u0026#39;string-replace-loader\u0026#39;, options: { search: \u0026#39;My-Variable\u0026#39;, replace: process.env[\u0026#39;MyVariableName\u0026#39;] // from .yml env } } ] } } Finally \u0026#34;scripts\u0026#34; :{ \u0026#34;test\u0026#34;: \u0026#34;webpack --config webpack.config.js\u0026#34; } ","permalink":"https://inderpalaulakh.com/posts/pipelinevar/","summary":"\u003cp\u003eRecently, I struggled a bit to figure out a way to access Azure-Pipeline Variables in Node.js JavaScript/TypeScript project. However, it is easy.\u003c/p\u003e\n\u003ch2 id=\"yml-pipeline-code\"\u003e.yml Pipeline code\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e- task: Npm@1\n  displayName: \u0026#34;Run project\u0026#34;\n  env:\n    MyVariableName: $(MYVARIABLENAME)  // this is pipeline variable name, in Capital letters\n  inputs:\n    commands: \u0026#39;custom\u0026#39;\n    CustomCommand: \u0026#39;run test\u0026#39;\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"npm-package\"\u003enpm Package\u003c/h2\u003e\n\u003cp\u003einstall package \u003ca href=\"https://www.npmjs.com/package/string-replace-loader\"\u003estring-replace-loader\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"typescriptjavascript-file\"\u003eTypeScript/JavaScript File\u003c/h2\u003e\n\u003cp\u003eCreate a file with any name \u0026ldquo;test.ts\u0026rdquo;\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003etest.ts\n\nconst test = () =\u0026gt; {\n    \n    const myVariable = \u0026#34;My-Variable\u0026#34;;\n\n};\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"setup-webpackconfigjs\"\u003eSetup webpack.config.js\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e module: {\n    rules: [\n      {\n        test: /test\\.ts$/,\n        loader: \u0026#39;string-replace-loader\u0026#39;,\n        options: {\n          search: \u0026#39;My-Variable\u0026#39;,\n          replace: process.env[\u0026#39;MyVariableName\u0026#39;]  // from .yml env\n        }\n      }\n    ]\n  }\n}\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"finally\"\u003eFinally\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e\n\u0026#34;scripts\u0026#34; :{\n    \u0026#34;test\u0026#34;: \u0026#34;webpack --config webpack.config.js\u0026#34;\n}\n\u003c/code\u003e\u003c/pre\u003e","title":"Accessing Azure Pipeline variables in Webpack Node.js"},{"content":"To understand Double Dispatch, understanding of Overloading and Overriding is must. I already talked about Overloading and Overriding in post Overloading \u0026amp; Overriding.\nOne level of virtual dispatching derived types override a base types: as shown below\nclass Farms { public virtual void Irrigation() { Console.WriteLine(\u0026#34;Farm Type\u0026#34;); } } class WheatFarm : Farms { public override void Irrigation() { Console.WriteLine(\u0026#34;WheatFarm\u0026#34;); } } class RicaFarm : WheatFarm { public override void Irrigation() { Console.WriteLine(\u0026#34;RicaFarm\u0026#34;); } } static void Main(string[] args) { var a = new Farms(); var b = new WheatFarm(); var c = new RicaFarm(); a.Irrigation(); b.Irrigation(); c.Irrigation(); } //output Farm Type WheatFarm RicaFarm Two level of virtual dispatching (Double Dispatch) This concept is used in Visitor Design Pattern.\nuse polymorphic static binding technique to ensure that proper overload is called\nclass Crop { public virtual void CropName(CropWatering obj) { obj.WaterSupply(this); } } class Wheat : Crop { public override void CropName(CropWatering obj) { obj.WaterSupply(this); } } /* An example of overloading (Method with same name but different parameter type) * */ class CropWatering { public virtual void WaterSupply(Crop crop) { Console.WriteLine(\u0026#34;CropWatering working on type Crop\u0026#34;); } public virtual void WaterSupply(Wheat wheat) { Console.WriteLine(\u0026#34;CropWatering working on type Wheat\u0026#34;); } } class CropWatringSpring : CropWatering { public override void WaterSupply(Crop crop) { Console.WriteLine(\u0026#34;CropWatringSpring working on type Crop\u0026#34;); } public override void WaterSupply(Wheat wheat) { Console.WriteLine(\u0026#34;CropWatringSpring working on type Wheat\u0026#34;); } } static void Main(string[] args) { Crop crop = new Crop(); Wheat wheat = new Wheat(); CropWatering cropWatering = new CropWatering(); crop.CropName(cropWatering); wheat.CropName(cropWatering); CropWatringSpring cropWatringSpring = new CropWatringSpring(); crop.CropName(cropWatringSpring); wheat.CropName(cropWatringSpring); } //output CropWatering working on type Crop CropWatering working on type Wheat CropWatringSpring working on type Crop CropWatringSpring working on type Wheat Reference\n","permalink":"https://inderpalaulakh.com/posts/doubledispatch/","summary":"\u003cp\u003eTo understand Double Dispatch, understanding of Overloading and Overriding is must. I already talked about Overloading and Overriding in post \u003ca href=\"https://inderpalaulakh.com/posts/dispatch/\"\u003eOverloading \u0026amp; Overriding\u003c/a\u003e.\u003c/p\u003e\n\u003ch2 id=\"one-level-of-virtual-dispatching\"\u003eOne level of virtual dispatching\u003c/h2\u003e\n\u003cp\u003ederived types override a base types: as shown below\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e        class Farms\n        {\n            public virtual void Irrigation()\n            {\n                Console.WriteLine(\u0026#34;Farm Type\u0026#34;);\n            }\n        }\n\n        class WheatFarm : Farms\n        {\n            public override void Irrigation()\n            {\n                Console.WriteLine(\u0026#34;WheatFarm\u0026#34;);\n            }\n        }\n\n        class RicaFarm : WheatFarm\n        {\n            public override void Irrigation()\n            {\n                Console.WriteLine(\u0026#34;RicaFarm\u0026#34;);\n            }\n        }\n\n\n        static void Main(string[] args)\n        {\n            var a = new Farms();\n            var b = new WheatFarm();\n            var c = new RicaFarm();\n            a.Irrigation();\n            b.Irrigation();\n            c.Irrigation();\n        }\n\n        //output\n        Farm Type\n        WheatFarm\n        RicaFarm\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"two-level-of-virtual-dispatching-double-dispatch\"\u003eTwo level of virtual dispatching (Double Dispatch)\u003c/h2\u003e\n\u003cp\u003eThis concept is used in Visitor Design Pattern.\u003c/p\u003e\n\u003cp\u003euse polymorphic static binding technique to ensure that proper overload is called\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e        class Crop\n        {\n            public virtual void CropName(CropWatering obj)\n            {\n                obj.WaterSupply(this);\n            }\n        }\n\n        class Wheat : Crop\n        {\n            public override void CropName(CropWatering obj)\n            {\n                obj.WaterSupply(this);\n            }\n        }\n\n        /* An example of overloading (Method with same name but different parameter type)\n         * */\n        class CropWatering\n        {\n            public  virtual void WaterSupply(Crop crop)\n            {\n                Console.WriteLine(\u0026#34;CropWatering working on type Crop\u0026#34;);\n            }\n\n            public  virtual void WaterSupply(Wheat wheat)\n            {\n                Console.WriteLine(\u0026#34;CropWatering working on type Wheat\u0026#34;);\n            }\n        }\n\n        class CropWatringSpring : CropWatering\n        {\n            public override void WaterSupply(Crop crop)\n            {\n                Console.WriteLine(\u0026#34;CropWatringSpring working on type Crop\u0026#34;);\n            }\n\n            public override void WaterSupply(Wheat wheat)\n            {\n                Console.WriteLine(\u0026#34;CropWatringSpring working on type Wheat\u0026#34;);\n            }\n        }\n\n\n        static void Main(string[] args)\n        {\n            Crop crop = new Crop();\n            Wheat wheat = new Wheat();\n            CropWatering cropWatering = new CropWatering();\n            crop.CropName(cropWatering);\n            wheat.CropName(cropWatering);\n\n            CropWatringSpring cropWatringSpring = new CropWatringSpring();\n            crop.CropName(cropWatringSpring);\n            wheat.CropName(cropWatringSpring);\n        }\n\n        //output\n        CropWatering working on type Crop\n        CropWatering working on type Wheat\n        CropWatringSpring working on type Crop\n        CropWatringSpring working on type Wheat\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003ca href=\"https://lostechies.com/derekgreer/2010/04/19/double-dispatch-is-a-code-smell/\"\u003eReference\u003c/a\u003e\u003c/p\u003e","title":"DoubleDispatch"},{"content":"To learn about Single \u0026amp; Double Dispatch, many design patterns, we need to understand Overloading and Overriding.\nOverloading Overloading is compile-time polymorphism. The methods/functions with same name but different number/type parameters are example of Overloading.\nAs Overloading is compile-time, means during run-time the base type is considered. Example:\nclass Crop { public virtual void CropName() { Console.WriteLine(\u0026#34;Hey, My type is Crop\u0026#34;); } } class Wheat : Crop { public override void CropName() { Console.WriteLine(\u0026#34;Hey, My type is Wheat\u0026#34;); } } /* An example of overloading (Method with same name but different parameter type) * */ class CropWatering { public void WaterSupply(Crop crop) { Console.WriteLine(\u0026#34;I am working on type Crop\u0026#34;); } public void WaterSupply(Wheat wheat) { Console.WriteLine(\u0026#34;I am working on type Wheat\u0026#34;); } } In main, If I create an object of type Crop and Wheat, an expected result will appear in console.\nstatic void Main(string[] args) { Crop crop = new Crop(); Wheat wheat = new Wheat(); CropWatering cropWatering = new CropWatering(); cropWatering.WaterSupply(crop); cropWatering.WaterSupply(wheat); } Output: I am working on type Crop I am working on type Wheat To demonstrate, compile-type, if we change the Wheat type to Crop, \u0026rsquo;new Wheat()\u0026rsquo; is ignored and WaterSupply(Crop crop) is called for object crop and wheat.\nstatic void Main(string[] args) { Crop crop = new Crop(); Crop wheat = new Wheat(); CropWatering cropWatering = new CropWatering(); cropWatering.WaterSupply(crop); cropWatering.WaterSupply(wheat); } Output: I am working on type Crop I am working on type Crop Overriding Overriding is run-time polymorphism. The methods/functions with same name and number/type of parameters are example of Overriding (Inheritance).\nclass Crop { public virtual void CropName() { Console.WriteLine(\u0026#34;Hey, My type is Crop\u0026#34;); } } class Wheat : Crop { public override void CropName() { Console.WriteLine(\u0026#34;Hey, My type is Wheat\u0026#34;); } } static void Main(string[] args) { Crop crop = new Crop(); Wheat wheat = new Wheat(); crop.CropName(); wheat.CropName(); } Output: Hey, My type is Crop Hey, My type is Wheat As type is determined at run-time thus new Crop() and new Wheat() is considered for object.\nstatic void Main(string[] args) { Crop crop = new Crop(); Crop wheat = new Wheat(); crop.CropName(); wheat.CropName(); } Output: Hey, My type is Crop Hey, My type is Wheat ","permalink":"https://inderpalaulakh.com/posts/dispatch/","summary":"\u003cp\u003eTo learn about Single \u0026amp; Double Dispatch, many design patterns, we need to understand Overloading and Overriding.\u003c/p\u003e\n\u003ch2 id=\"overloading\"\u003eOverloading\u003c/h2\u003e\n\u003cp\u003eOverloading is compile-time polymorphism. The methods/functions with same name but different number/type parameters are example of Overloading.\u003c/p\u003e\n\u003cp\u003eAs Overloading is compile-time, means during run-time the base type is considered. Example:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        class Crop\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            public virtual void CropName\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                Console.WriteLine\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Hey, My type is Crop\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        class Wheat : Crop\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            public override void CropName\u003cspan style=\"color:#f92672\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                Console.WriteLine\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Hey, My type is Wheat\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        /* An example of overloading \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eMethod with same name but different parameter type\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         * */\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        class CropWatering\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            public void WaterSupply\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eCrop crop\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                Console.WriteLine\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;I am working on type Crop\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            public void WaterSupply\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eWheat wheat\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                Console.WriteLine\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;I am working on type Wheat\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eIn main, If I create an object of type Crop and Wheat, an expected result will appear in console.\u003c/p\u003e","title":"Overloading \u0026 Overriding"},{"content":"The book “Don’t make me think” is written by Steve Krug. This is the first book that I read about UX(User Experience Design) design. This book is concise and has four sections.\nThe “guiding principles” talks about not puzzling the user to find required content. These principles guide to omit needless content, using conventions, images and explains the web page scanning habit of user (not reading complete content).\nThe section “Things you need to get right” has content to design navigation that helps user to find their way. The big bang theory of web design is about designing home page, using tag lines (nothing beats a good tagline), welcome blurb and testing home page usability.\nThe section “Making sure you got them right” is all about usability testing. Resolving conflicting thoughts between developers, designers, marketing and project managers, this section also talks about usability testing on 10 cents a day. Focusing on early usability tests, do it yourself usability testing and how often, this section importantly explains feedback loop. Finally, this section has guidance about “deciding what to fix” from feedback.\nThe final section is about Mobile UI design. Talking about significant difference between Web \u0026amp; Mobile App design, the section has some techniques for screen recording usability testing (using cameras, no screen mirroring).\nUsers browse to website with “The reservoir of goodwill” and the goodwill can be increased or diminished by many factors. Finally, the last topic of book has an eye-catching line:\n“Unless you’re going to make a blanket decision that people with disabilities aren’t part of your audience, you really can’t say your site is usable unless it’s accessible.”\nAfter reading this book, I learned concepts to enlighten user experience. The book helped me to think about conducting usability tests in early stages to avoid disasters, to discuss the importance of speaking user language for make user experience rich.\n","permalink":"https://inderpalaulakh.com/posts/my-book-donotmakemethink-post/","summary":"\u003cp\u003eThe book “Don’t make me think” is written by Steve Krug. This is the first book that I read about UX(User Experience Design) design. This book is concise and has four sections.\u003c/p\u003e\n\u003cp\u003eThe “guiding principles” talks about not puzzling the user to find required content. These principles guide to omit needless content, using conventions, images and explains the web page scanning habit of user (not reading complete content).\u003c/p\u003e\n\u003cp\u003eThe section “Things you need to get right” has content to design navigation that helps user to find their way. The big bang theory of web design is about designing home page, using tag lines (nothing beats a good tagline), welcome blurb and testing home page usability.\u003c/p\u003e\n\u003cp\u003eThe section “Making sure you got them right” is all about usability testing. Resolving conflicting thoughts between developers, designers, marketing and project managers, this section also talks about usability testing on 10 cents a day. Focusing on early usability tests, do it yourself usability testing and how often, this section importantly explains feedback loop. Finally, this section has guidance about “deciding what to fix” from feedback.\u003c/p\u003e","title":"Book Summary: Don’t make me think - Steve Krug "},{"content":"I am a Software Engineer focused on building reliable products and writing about practical software engineering.\nThis blog is where I publish notes from real projects, architecture decisions, and lessons learned while shipping software.\nWhat I Write About Software design patterns and clean architecture Backend and cloud engineering (including Azure) Engineering practices such as code review and maintainability Personal learning notes from books, experiments, and side projects Why This Site Exists I write to turn experience into reusable knowledge. If a post helps you avoid a bug, design a cleaner system, or move faster with confidence, it has done its job.\nWork With Me I am always open to thoughtful technical discussions, collaboration opportunities, and feedback on posts.\nEmail: aulakh.inderpal@gmail.com Quick Navigation Start here: /posts/ Browse by timeline: /archives/ ","permalink":"https://inderpalaulakh.com/about/","summary":"\u003cp\u003eI am a Software Engineer focused on building reliable products and writing about practical software engineering.\u003c/p\u003e\n\u003cp\u003eThis blog is where I publish notes from real projects, architecture decisions, and lessons learned while shipping software.\u003c/p\u003e\n\u003ch2 id=\"what-i-write-about\"\u003eWhat I Write About\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSoftware design patterns and clean architecture\u003c/li\u003e\n\u003cli\u003eBackend and cloud engineering (including Azure)\u003c/li\u003e\n\u003cli\u003eEngineering practices such as code review and maintainability\u003c/li\u003e\n\u003cli\u003ePersonal learning notes from books, experiments, and side projects\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"why-this-site-exists\"\u003eWhy This Site Exists\u003c/h2\u003e\n\u003cp\u003eI write to turn experience into reusable knowledge.\nIf a post helps you avoid a bug, design a cleaner system, or move faster with confidence, it has done its job.\u003c/p\u003e\n\u003ch2 id=\"work-with-me\"\u003eWork With Me\u003c/h2\u003e\n\u003cp\u003eI am always open to thoughtful technical discussions, collaboration opportunities, and feedback on posts.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eEmail: \u003ca href=\"mailto:aulakh.inderpal@gmail.com\"\u003eaulakh.inderpal@gmail.com\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"quick-navigation\"\u003eQuick Navigation\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eStart here: \u003ca href=\"/posts/\"\u003e/posts/\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eBrowse by timeline: \u003ca href=\"/archives/\"\u003e/archives/\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"About Me"}]