Transcription
Hello guys, here is Abdullah Zaluran. Today discussion is about software technical project manager, the ultimate guide.
So, if you are talking about this position, this one is a hybrid one at a startup. So, you are working at the business side as a coordinate project manager and the technical one working as a technical lead. You are filling the gap between business and technicality.
So, you should have a good knowledge across the software development life cycle. Starting from the planning phase, you discuss with the business team, you will do this feature or not, you are discussing ROI, return on investment, of every feature. Then, if you say yes, we will do this feature, you are going to the next phase, which is, uh, defining one. So, the team tries to, uh, put all the requirements, making it a mature one, creating user stories. And the next is the designing phase.
So, the designing phase, you implement a visual part like the UI/UX and the system design, the back-end side, for example, here, how the components and services, uh, talk to each other. And then going for, uh, building phase or coding phase. So, here is, uh, how the code will be written. And, uh, then, uh, going to testing phase, writing unit tests and integration tests, system testing, and manual testing across all over the system. And then you try to go for production at the deploying phase here. How you are merging your branches and going to production. And the final one is maintenance. If you find any bug here, so you should, uh, remove the technical debt. That adds the technical part.
So, every sprint should have two types of requirements: business requirements and technical requirements, like removing technical debt periodically. Period of time. Now, we should have an implementable plan and ready tools, all-in-one solution to do SDLC all over our company and to automate the things and, uh, covering any missing position.
So, firstly, I'm a big fan of using, uh, remote bus as an HR and finance platform. So, remote bus provides you all what you need regarding HR and, uh, something like contracts, payroll, invoices, bills, uh, day-offs for your own, uh, uh, employees. So, you just, as an employer, link your payment credentials and write the contract. And the same for the employee or contractor, he will link his credentials and the salary or payroll will be on time.
So, the next one is development and deployment, CI/CD. I'm a big fan of this combo. So, you are using GitHub with GitHub Copilot as AI coding assistance and, of course, VS Code. This is because of maturity and wide range of support and unifying things is a very good approach here. And if we talk about deployment, I will go for COI. COI is just an automatic layer above AWS, which is based in AWS and has all what you need here. Support you with domains and support you with serverless and the workers for background queues, database, serverless database, like name-based volumes and the storage. So, once you go with scope, you have a monitor all over your applications here and you remove all the DevOps headache.
So, let's go for process management. The best all-in-one solution I have ever seen is, uh, ClickUp and this one is called Zoho. So, at Zoho, you have, uh, an all-in-one platform. Once you open Zoho, you have access to all over the things. You don't need Slack. You don't need anything. So, you will not go with Jira with Slack with different things. No, no, no. You just have Zoho and Zoho has a built-in email, uh, built-in task scheduling and calls, meetings, and all what you need for your workspace. And they have a Kanban-based thing called Zoho Projects and have a Scrum one solution called Zoho Sprints, which links to our chat directly here.
So, this is the example for our team members: the CEO and the business side, and the technical project manager, and the tech team. Let's say we have a full stack one with a front-end and an AI engineer. So, how can you implement the SDLC now? This is according to different factors. So, if you have a good backlog and have a vision about at least two sprints, you will go for Scrum. And if you don't have this, you will go for Kanban just to chain your tasks from message to another, for example, done, doing, to-do, or in testing here. And according to it, you will choose Zoho, which one, Projects or Zoho Sprints.
So, if we talk about Kanban, we should have, uh, this example for Zoho Projects. You will have a user story which is called a task. And you will do definition of done, periodicity, and any dependent stories should be sequential. And you will have at least the designs and the owner or the assigned person. You will have a task list which is your own team members. So, we described that we have an artificial intelligence engineer and front-end and the back-end. And, uh, if we talk about how to implement the tasks and subtasks. So, you shouldn't have a task above 4 hours. Any task above four hours should be split into subtasks. And the same flow for, uh, issues.
Let's talk about technicality, starting from Git flow. How can we go to production? So, firstly, we have a master branch and, uh, dev branch. So, I will take a clone from the master to create a feature branch. And we'll take a clone from the master called release branch, which is testing or staging here. So, we will, uh, do our feature, then merge it to the release branch. And if we see it is okay, we will, uh, merge it to the master. And now the release acts as a restore point to our master. So, if we have two features, for example, we will have release and feature number one. And we have release with feature number two. And all of this is just a merge for the master or a restore point for the master. You can reset the master to any point if you have an issue, uh, an urgent one. And of course, you can fix the hotfix and merging it and creating a release branch for it. And any merge should be merged at the dev one, simply. That's it. And the naming convention should be, uh, the branch naming here, uh, the name of the team, front-end, back-end, AI, just a shortcut, front-end here, and the task list, then underscore, the task ID with task name. For example, this is the task ID at Zoho and this is the name of the task. And here we go. Any sequential tasks should be at one feature branch and just you can put it as commits inside it.
Let's go for coding standards here. So, I'm a big fan of using decoupled modular architecture rather than monolith or microservices. I don't love, uh, bad engineering or over-engineering here. So, to implement this decoupled modular one, we should have a mediator module which is called an app module here and used for initial things like dependency injection container and registering middlewares, anything like this. And any module need anything from another module should be used through the mediator. Web. So, at the end, you can decouple any module efficiently. So, for example, if we have an app module and we have an e-commerce module and a ride-hailing module, and I need just to remove the ride-hailing module, all what I do is just taking the module with the ride-hailing one. And the same for, uh, the other e-commerce module here. And we can implement modularity according to the business. So, if you are working app-based or domain-based, what is app-based? It is persona-based. So, for example, if we have a hiring system and we have an application for worker, application for customer, and another one for admin, another one for agency. So, we can implement it as modules. Any module is regarding his own person. And of course, we can implement it domain-based as I mentioned above.
So, what about module structure? So, I'm a big fan of making it simple and efficient and we have the benefit from this. So, for example, we have DTO layers. So, the DTO is just types, interfaces, validation, inferred validation scheme. All of this is just a DTO. So, you should know what you send and what you will receive at the front-end and the back-end side. Service layer. It is the business logic. So, the feature required to do something. So, this is the business logic. Repository is a data layer, not a database layer. So, meaning if we have, uh, a question repository, it should return an array of questions. I'm not care about getting the question from the database or environmental file or external API. This is according to the time factor, leading. If I needed a static one, I just put the things as a JSON inside the environmental variable or just an external file without implementing a CRUD operation. Here, utils is a logical logic or non-business logic. So, you will put anything not, uh, related to business logic, just, uh, formatting your date or capitalizing wording, something like this. And the naming convention should be build language and the framework. Stick to camel case or, uh, snake case here. As we discussed, repository is a data layer, not only database layer, but also retrieve from different sources of data like caching, API, env, etc. And this record contains ID or key, OTB, and the value, mail. The same for the second record here, authentication, and the value is found here.
So, uh, if we talk about this and using repository pattern, and we have two types of ORMs. So, ORMs retrieve the data from the database. So, if we have a data mapper, so data mapper examples like Prisma, and the type, it just returns the record as a plain object from the database, meaning this object doesn't carry any other database logic. So, for example, once I get the setting here, find it, I cannot say setting update because the database logic is not here. So, of course, you need to implement a specific class, a dedicated class for repository to retrieve the data and edit it and change the pagination logic, change the shape of data, hide something, get something, set something here. But if we are working with active record patterns, which is a feature-rich one like Laravel and Lucid, so once you retrieve, uh, this setting, you are retrieving a model instance, not only a plain object. So, you can, uh, do update and all the database logic because it carries database logic here. So, if you need to implement a repository pattern, you just have the database logic, so you can merge to it the cache and DBI without creating an extra layer of complication like this, which is the most common approach today. So, you need to create a method interface for repository, then bind it to the service layer. All this is complication because if we check our code here, we try to find by ID, which is finded here with the same parameters, and the same for all. So, you can use, uh, composition at BB using a trait. So, you can separate your cache layer at a separate trait and the same for API env. Not inheritance, but composition. And you can drop it. So, once you have the model, you will have all the logic of the repository and you can utilize it, not just a database source, but also a full repository. And they will give you the example across three main frameworks: Nest, which is Node.js based at the back-end, and Laravel, and Nest.
Let's go with Prisma here, and I have this in the point called settings. It will return, call the service layer. So, the service layer will get the repo here. And if it doesn't find the setting, you can do your exception business logic here. Let's go for the setting repo here. I want to retrieve it from, I will implement a wrapper method called get all. And you can use it, uh, without this wrapper. And you can use with, for example, uh, I may say from, uh, env, from API, from database directly here. This will make you change just the method name inside the service. But if you plan to never change anything in the service, you just go for get all and call the needed method here. So, I want to retrieve the setting from cache. So, I will run my project here.
Now we can check our API here using Nest DevTool. I want to check API/setting. It returns the needed data here. The key is OTP, value, mail. The same for authentication. So, it returns it from what? From cache. So, as you can see here, finding from, uh, config. This is the first time using the cache because inside this cache one, as we can see here, this method, it returns it from the config, which is from the environment variable, then it cached it. So, the first time will be from the config. But if we retry again here, so, of course, it will get from cache. And if we retry again, it still gets it from the cache.
Let's change our logic without affecting all of, uh, service. I want to go here, say from, uh, caching from config here directly. It will say the following: it retrieved from config here. And the same if we change from, uh, from AI. So, we have, uh, another endpoint, try to fetch it from another endpoint here, returning all. And it will be internal or external one. Not a big deal right now, just for the example. And if we check, uh, our, uh, console here, it said retrieved from AI. And let's go from another database source, which is database itself here. So, I want to say, uh, from DB here. Yeah, we'll make it from DB. And once we check, it gets the data from the database source as we need it. So, you cannot change all the logic without affecting your service. This is at the data mapper. When let's go, uh, for the Laravel Eloquent instead of this Prisma data mapper, using Laravel is very easy. Let's track /AI/setting. So, this endpoint will go to setting service list method. And the service here calls the model as a repository because at Laravel, our model carries our database logic. So, we can merge any other functionality like getting from env, from cache, from API as a trait using composition. This is the simplest way without any boilerplate, without any complication. So, let's go from AI. This one, we can couple and decouple it easily. And now we have a from AI logic and from env, for example, here. Let's go for it. So, I get the environment variable of setting. This one, as you can see here, I want to open it now. It will return the setting. Then I will do hydrate for this JSON. So, let's go and try our endpoint right now. So, this is /API/setting. It works fine as we need. Here it is, OTP and mail, and authentication. And let's go from changing from cache to from AI. The same logic, uh, will be founded here. And if we change it to from env or from config, yeah, from cache also. All this one is working fine here. So, I want to return the same result here.
Let's check our NestJS ORM decorator-based approach. This is our, uh, setting controller and routing to /get here. So, it calls the setting service, get all. And this one calls the setting repository, get all. And the setting repository is using the entity of type Now. And it uses dependency injection of, uh, Nest. So, the config service and the HTTP service is ready. And the cache manager is ready. So, it will be used for the needed method here. So, this method is get all. So, it retrieves a setting from cache. So, if I do a refresh here, it returns it from cache. So, let's go for this approach. This one is using the cache manager. Okay, let's go from env. It will still work. So, our logic is still fine. It will do a reload here. Yeah, it is working. And it says that get from config, as we said here, will get from config using the config service and parsing the JSON. The same from DB. The same for the others, using the HTTP code here, from DB. Yeah, it works. It is just starting. Now it works. Let's go from AI. The same result will be founded. So, you should do, uh, as we say it, right.