
Senior Software Engineer and Team Lead
United Postal Service, UPS (Delivery Solutions)Senior Frontend Developer & Technical Lead
Triply(Freelancing Contract)Senior Frontend Developer & Technical Lead
Reliance Industries LimitedCross Platform App Developer Intern
AHY ConsultingJunior Web Developer
Reliance Industries LimitedSenior Web Developer
Reliance Industries Limited
Angular

TypeScript

React

Next.js

Python
.png)
Docker

Git

Kubernetes

CI/CD

Azure DevOps
Jira

Confluence

Adobe XD
Figma

Jest

Jasmine

Sentry
Project Overview: We built a tool that helps companies become more eco-friendly in how they and their employees travel. The platform, triply, makes it easy for companies to see where they're at, figure out where they want to go in terms of being green, and track their progress.
What I Did:
Project Overview:
NMACC is a premier cultural and exhibition space in Mumbai, which is one of India's largest cultural centers. This was an extensive application that required multiple different modules, and internal/admin portals as well as online ticket booking facilities. The project was developed from scratch by my team and I, and even today there is an average of 10000+ users that visit the site on a daily basis.
What I Did:
Project Overview: It was a food ordering application that served as a bridge between 100000+ employees pan India and 20+ on-campus vendors, as well as several off-campus partner vendors, facilitating seamless order placement and management.
What I did:
Project Overview
For Reliance, I developed a carpooling app to facilitate easier, eco-friendly commutes for employees. This platform connects drivers with passengers within the company, streamlining travel to and from work.
What I Did:
Yes, I'm Uday Menon. I'm a senior front-end engineer. I have six years of work experience now in the same role. I'm also a technical lead. I started working in 2018 at Reliance Industries Ltd., which is India's top Fortune 500 company as a junior web developer. I started working on Angular in 2018 itself. From 2018 to 2022, I was in Reliance Industries, where I moved from being a junior web developer to a senior web developer, and eventually a senior web developer and a technical lead specializing in Angular and Mean Stack. In my time at Reliance, I've got exposure to using different kinds of technologies apart from Angular, such as Kubernetes, Docker, Kafka, and the environment was primarily based on Azure DevOps. So we also created CI-CD pipelines in Azure DevOps and integrated different tools and utilities for continuous development and integration of our Angular application. And to also ensure that the code was up to the standard and up to the mark, we also integrated many bug detection tools such as SonarQube. And we also add tests written in Jasmine and Karma to make sure that each unit of code also ran well. Apart from being an Angular developer, I was also a technical lead. As a technical lead, I led a team of 15 cross-platform, cross-functional developers. And that is, they were front-end and back-end developers, and we developed about 9-10 projects. Some of the projects include a food ordering application where we created an application for all the employees of the company to order food from the partner vendors, a carpooling applications, an application during COVID-19 where we had to provide medical help to all of the employees and their families. Apart from this, I also worked for over a year and a half at a remote company, in a remote job for a company in Austria called Tripoli. The company was a sustainable mobility company, and here I was the senior front-end developer and also the team lead. As a senior front-end developer, we leveraged different in-house as well as external third-party APIs such as a Google Maps API to identify a user's location and the distance they are from the company, and so on. We also had a machine learning algorithm that was integrated into the application to monitor various factors such as the average carbon footprint, the time taken for an employee to perform different activities like cycling, driving, etc. to reach the workplace, and this was sold as a product to different companies. So here as a team lead, I also made sure that since it was a smaller company and I had to make sure that there were many processes that are set in place which are not yet developed, I created a complete CI-CD pipeline from scratch using Azure DevOps itself, and we also leveraged Kafka to ensure that the data is consistent, and if one of the services was down, we made sure that Kafka continually relayed the message to the services and brought them up to speed when any service is back up. So I have a total of six years of experience as a mean stack developer specializing in Angular, and that is my background.
Okay. Uh, when interfacing with APIs in Angular, we generally use something, uh, some of the RxJS features such as a subject. Uh, what that subject or behavior subject what that, uh, does is in case there is any kind of error, the observables have functions within them that allow us to handle these errors. For example, the observe an observable can simply emit a new value using the next method, next callback method. But in case of an error, there's also an error callback method. So if an API fails, uh, so the observable will know that the API has failed, and it will receive an error object. This can be accessed by the user or the developer using the error callback method. And Another thing that can be used in case we do not want to use subscriptions is we can also make use of, uh, promises or async await and, uh, or a simple event, try catch block, and ensure that whenever there is an error, we catch that error and, uh, show the appropriate error to the user by using something like a Toast service or creating a custom model window and just showing the user that x, y, zed is the error in the program. For example, if you're fetching data from the server and, uh, server returns some random error like, uh, invalid request, we can simply, uh, create a model and show the user that, uh, you could not fetch the data because the input is missing x, y, zed properties. And, uh, we can just make the front end more user friendly by incorporating certain little things like, uh, this and ensuring that at the end of the complete cycle, the user is not left wondering that, uh, the API has failed and for what reason it has failed. So we can also have, uh, interceptors called HTTP interceptors that intercepts the HTTP requests. And what these interceptors do is when an HTTP call is made, they intercept the request midway, and, uh, you can handle certain checks or, uh, put certain things like, uh, authentication token or authorization cookie. One of these things, we can embed that onto the request and send it over to the server. So what this does is it makes the application more secure. And also in case of any error handling, uh, the interceptor will be the 1st point of contact. After that, it will come to the application where any further processing can be
So in Angular, we can primarily use, uh, Jasmine and Karma for unit testing. A simple way that I have personally used for unit testing in Angular router is take this basic route, and it's possible that some of the routes have guards, like, for example, an authentication guard. So for the unit testing, we pass the route along with the authentication object, such as the authentication, uh, or temporary authentication token. And in the unit test, we test that if the authentication token is valid. Only then the user will be allowed to navigate to that particular route, and it will be redirected to, uh, either a page not found or some alternative route. Uh, so the key is to divide a large application into smaller modules. So when we have modules, the advantages we can lazy load these modules and also apply certain guards on the entire module using the canload method that is provided by Angular. So what it does is before each route is loaded, the canload method executes, and it checks if, uh, the user is, uh, authorized to go into a particular page. If not, it won't load load the module at all. If yes, then it will not only load the module, but it will, uh, also allow the user to access its child components. So the one of the ways that you can effectively unit test is by splitting it into modules and also by testing it with small roads with mock data.
There are different ways in which we can optimize an angular application. One of the main things that we can do is we can use some in case of using structural directives like ng for what happens is the DOM is manipulated and lots of data is added. If suppose a parent component changes, then the child component has to rerender the entire data even if only one or two of the entire data is changed. So we can use something known as a track by function track by ensure that only the data that is changed in the array is modified. And it doesn't in we don't have to rerender the entire application or the array. Another is we can use the on push chain detection strategy. So in traditional chain decision change detection strategy, what happens is the entire hierarchy from the root to the footer is checked in case any changes made. But in case of on push, only those components whose input parameters, the ones that are defined using at input, only those components for whom the input has changed, only those components will be checked for changes, will be re-rendered using change detection, whereas the other components will not be re-rendered at all, this will lead to better performance. Another thing is of late is we can use AOT compilation instead of just-in-time compilation. What AOT compilation does is it compiles the pre-build, pre-compiles the code at build time itself, unlike just-in-time compilation. This makes sure that when the code is rendered out of the browser, it is much faster. Another thing is we can make use of web workers, web workers are useful to delegate the task. So if there are certain tasks that can be delegated to the web workers to make the Angular run faster, we can delegate those tasks to the web worker while Angular will focus on performing the less intensive tasks. Then we can minimize the size of the bundle. So JavaScript by default bundles everything together, and we can minimize the size of that bundle by either using Babel or other JavaScript libraries that will simply minify the bundle before it is built and sent on to the server. Lazy loading. Lazy loading is something that is very popular in optimizing the performance of an application. So we can divide the application into multiple different modules, for example if it's a food ordering application, we can have an orders module, we can have a users module, we can have a restaurant module, and only as and when the modules are required, for example when the user goes into the restaurant, only then we will need the menu module, the menu module will be loaded as and when needed. So that is another way in which it can be done, in which we can achieve optimization. We can also use certain memorization techniques which are not just Angular specific but it is JavaScript specific. So if you know that for a particular function, the output function A, the output is xyz for a particular input, then the next time that function is called with the same input, we will not have to execute the function again, instead we will just pass it to a memorization function and that will simply return the value that was stored in the cache.
Okay. So in my last, uh, job, I had the opportunity to incorporate internalization in the Angular application for multiple languages. So the process of internalization is simple. We get uh, a I eighteen package that comes prebuilt with Angular. And, uh, what this I eighteen package does is it allows us to add support for different, uh, languages. So suppose we have, uh, an HTML div tag that shows some text. For example, view cars. Right? View cars. If that, uh, div is simply marked as at the rate II eighteen, It tells Angular that this, uh, div is marked for internalization. So depending on the language that is selected, for example, if a language like Hindi is selected, then that show cards will be transferred to something in Hindi like, which is Hindi for show cards. So that way, just by using such a simple I eighteen directive that is provided by the internalization package, we can simply, uh, internationalize the entire application. A more effective way to do it is create a separate translation file. So for each file, we can have the translation file for that, and and that will contain maybe an interface or even a simple object that contains all the translations, the i18 and translations. So depending on which language is chosen, the appropriate, uh, analyzation object will be loaded. For example, we can have a key set of key value pairs of different keys and objects, and the key will be the any key that we want to give for a particular word, and the value will be we can have multiple values for different languages. So based on the language that is currently selected, uh, the I18n library or the internationalization library can allow for multiple different supports, and it can also be modularized by using multiple different
Yeah. So Angular, by default, is built on TypeScript, Angular 2 plus. So AngularJS initially was, uh, built on JavaScript, but over time, as we came to Angular 2, it was built on TypeScript. And one of the main, uh, necessities was using was its ability to have strong typing features. So I'll give you an example. Suppose we have a location object that we're receiving from the API. Now if you without TypeScript, we don't know what properties are coming in the location. We don't know what properties we can expect to get in the location. But instead, we can simply create an interface called location. And in that interface, we can have a set of property that we expect to get from the API. So now when we we receive data from the API, we can store the data in an object and have that object expect, uh, that it receives an object of type location. So when we store the data, it will immediately give us a syntax error or a compile time error that shows us that x y zed properties were expected, but it is not found. So that is one of the main ways in which we can use typing features. Additionally, we can use typing for things like in other programming languages, for example, Java or c. We have, uh, different data types like integers, numbers, double, etcetera. Similarly, we have data types in TypeScript as well such as, uh, numbers. We have objects. We have, uh, undefined. We have multiple, uh, their string. We have multiple different types. And based on the data type that we expect, we can, uh, say that a particular variable is also expecting that data type. And if the value stored in that variable is not a better type, again, we'll get a compile time error or a syntax error. Additionally, it can also be used for, uh, functions, where a function is expecting a particular return type. For example, we have a function, calculate distance, and we know that the distance will be a number. So we can say that the function is will expect a return value of type number, uh, which we cannot do in JavaScript otherwise. So TypeScript allows us for that. So whenever we call function calculate distance, if that function, for any reason, returns anything except other than a distance or a number or even null, we can use the or operator to also accept multiple values. For example, if you know a function is will return either a number or null, we can use the or operator, that is the pipe operator, and say that the function is either going to return, uh, value of number or value of none. So and if it is not either of this value, again, we either get a compile time error. Or in some cases, when we are fetching data from an API, we might even get a run timer. So, uh, the strong typing features help not only in identifying compile time error, but also in identifying runtime errors. And using these typing features, we can create certain linting systems. So, for example, we can create a system that when we upload our code to the repository or get GitHub action sequence will run that will check the entire code and look for any type errors. If there are any type mismatches, the code will not even be allowed to be pushed onto the Sentil repository. This ensures that the application stays clean and free from any bugs at all times.
Okay, so in the given code, we have a class product that identifies a type product that is trying to define a type product. And we have a product service in which we have an array of product array, that is an array of type product. And when it is trying to add a product into the array, if we see and while checking it checks that if there is an ID of the same ID that is given, if it already exists, then an error is thrown, showing that product already exists. If not, then the product is pushed into the array, that is what it is trying to achieve, okay. So, I see that in the product class, while the constructor is accepting ID and name, there are no assignments. So, for example, when we create a new product, we do not know that there are no assignments, for example, this dot ID equal to ID, there are no local or private variables into which these assignments are stored in which these assignments are stored. So, that can create a problem. So, if we make a check to try to find the ID, if there is no assignment of the ID, then there is no way for the product ID to be checked. The issue that I see here is, we are not catching the error anywhere, which is just using it inside the if statement. So, what that will do is in case there is an error in catching the product, in adding the product, then it will first it will throw an error saying product already exists, but then it will again try to push the product as it is not being the error is not being caught anywhere. So, what this will do is although it will throw an error, but it will also try to push it into the product array, which will create an error and potentially can potentially block the application and stop its execution.
To respond to the style of development, but it's not. Okay. So initially, I can see that the for the first, uh, media query, the min width is given as 600 pixel. Whereas for the 2nd media query, min width is given as, uh, max width is given as 500 pixel. So up to 500 pixel, the width will be 75%, and after up to 5 99 pixel. And, uh, after 600 pixel, the width will be 50% of the original width. It's not applying. Since you've already given the width is 100%, we do not have any context of the parent width of the responsive div. It is possible that, uh, the dev has limited content. For example, it just has a text inside it, and that, uh, dev is just around that text. So even if we give the width as 100% or 50% or 75%, it will only take as much width as required. In case, uh, it doesn't have a parent container that is of a specified fixed width. So that could be one of the potential issues due to which at different screen sizes, it is not, uh, reflecting. It is also possible that the width of the parent div of the responsive div is, uh, lesser than 600 pixel. So what that does is if the screen size is 600 pixel and if the the length size of the parent width is lesser less than 600 pixel, then regardless of whatever change in size after 600 pixel, it will not apply the width property as the min width is 600 pixel.
Okay, so change detection is a tricky topic when it comes to angular because there are lots of potential activities that can trigger changes. For example, a user click something like a set timeout, something like some activities completed in one child component and it emits that activity to the parent component. So many different activities can trigger changes. So one of the first things that we can do is implement an on-push change detection strategy which is a newer change detection strategy, it wasn't there in the earlier versions of angular. What this does is it keeps track of all the files that are all the components in which the input parameter that the parameter with add input changes. So the input parameter does not change for a particular component, whenever the change detection cycle is triggered, that component will not be re-rendered. So that component will be optimized for change detection. Apart from the on-push strategy, what I can think of is using the ng-zone. So what ng-zone does is it helps us to run certain code either outside the angular zone or inside the angular zone or force inside the angular zone. So by default, all components run inside the angular zone. But suppose we have certain third party libraries, for example, a Google Maps API where the map changes that change cannot be read by angular because that change is happening externally. So what we can do is we can force change detection by leveraging ng-zone and using ng-zone.run and ng-zone.run will ensure that the changes that are occurring in the Google Maps, it is able to manually trigger change detection whenever those changes are occurring. And similarly, in ng-zone, we can also make sure that certain computations run outside of the angular zone. Suppose we have certain heavy computations, we can use ng-zone.run outside angular. What this will do is it will make sure that any heavy computation that have to be carried out, it runs outside angular and it does not occur every time there is a change. So if there is a heavy computation and this is not implemented, each time there is a change that computation will occur again. And it can create lots of bottlenecks and create a laggy user experience. Sometimes we can also make use of the ng-do-check lifecycle hook. So by default, the ng-on-changes lifecycle hook listen for changes in the inputs of the particular component. But sometimes like in case, for example, in case of a nested object or a complex object, what happens is certain properties change, but we are not able to detect those changes. So that can be done with the help of ng-do-check, ng-do-check runs after ng-on-changes and ng-on-init, it starts running after that. And each time there is a change in the property, ng-do-check will be able to capture that change in that property. We can implement a custom change detection strategy for the system.
Okay. So to perform an end to end testing, using dot NET, we can firstly create a central service. For example, if we are using something like Swagger, uh, what that does is we can use Swagger. We can use a command using this all the, uh, changes in Swagger are automatically updated into a service set of service files in that Angular application. So whenever something like a model, API endpoint, expected input, output, anything changes, those changes will automatically leveraged into our those changes will automatically be made into our application, and it will be stored in the services folder. So now when we have to, uh, make or perform certain tests, what we can do is we can simply write a unit test. The unit test will call that, uh, particular API endpoint, and it will just compare to see if, first, the the request body that is being sent, if it matches the model that has been defined by the API in Swagger. If not, the test fails then, and it gives an error saying that the model does not match. X, y, zed. Secondly, we can try passing that object. If the object is valid, we pass that to the API and see the response. And then we see the response is as expected. Like, we can also define another model or have a predefined model that is defined in the by the Swagger documentation. And we can see that see if the model matches that that is mentioned in the documentation. In case there is a match, we can move on. If not, we can return an error saying that the the request is successful, but the response is not of, uh, the type expected. Okay.
So I'll give you a step by step approach that the way I would, uh, approach this. So firstly, I would have a central repository for all the APIs. Something like, uh, Swagger does the job. You can have a list of all the APIs divided according to the name of the controller, and each controller will have a set of endpoints. For example, if you have a food ordering application, we'll have a controller for order. We'll have a controller for payments. We'll have a controller for user info. And each of the controller, for example, order, will have endpoints like, uh, fetch order, place order, etcetera. And use for user, you might have fetch user info, uh, set user info, all those kinds of endpoints. So we have a central repository of endpoints. Then what we can do is we can use a library such as Codegen. And using Codegen, we can create, uh, automatically run the codegen command. And what that will do, it will go to Swagger, fetch a list of all the APIs that are there along with their models, and it will update that in the Angular codebase. So each time a back end developer makes any change in the API, that change will be reflected in Angular itself, and we can see the new services as well as the new uh, models. Once that is done, next, what we can do is we can create a set of generalized HTTP methods. So using the HTTP module, I'll create a central service that will have the basic methods such as get, post, put, delete. These 4 methods the basic 4 methods, the CRUD operations, that will be defined in there along with any authentication headers. So the method will be simple. It will take in the headers as well as, uh, the risk request body. And inside this, it will uh, call the API, and it will simply return an observable to the service. Now that the central service is done, now we can create, specific services. For example, we can create a service for orders. We can create a service for booking for viewing the menu in the front end. I'll take an example of orders. So in fetch orders, we'll call the get API that we previously defined in the central services, and we'll also just pass in the endpoint name. So we can have a central list of head either endpoints or we can have a predefined set of functions. We will simply call the endpoint, and the get service will fetch the corresponding model and see if the model is matching if the model and everything is matching. It will simply, uh, the API will get an observable in return. Now this, uh, observable can we can subscribe to in different components. So using dependency in injections, different components can consume the central service that we have created. And just call the service that we created in the orders service, for example. So in the component, we'll just call fetch order. In return, we'll and we just subscribe to that. We don't have to call it. You can just subscribe to it since it's already returning an observable. We will simply subscribe, uh, to the observable. And as in when the observable fetches data, we will get the data, and that that data can be updated on the template. So this is the end to end cycle that I would follow for integrating, uh, .net or any back end API with the Angular framework. Thank you.