Envision Digital

JTC Job Management Module

Job Management Module (JMM) is a web application built to facilitate the management of tens of thousandstens of thousands of assets managed by the Jurong Town Corporation (JTC)

Skills

TypeScriptSassReactGitLabPostmanNode.jsJestJenkinsAntDesign

Project Details

JTC manages multiple portfolios of buildings across Singapore, and Facilities Management Companies (FMCs) are responsible for handling feedback, defects, and maintenance.

The features which I worked on include the Property Registry, Asset Registry, Lift Breakdown Report list, and Data Export and Import modules. While it is impossible to show the actual application, I will provide a high-level overview of the problems faced.

JMM OverviewOverview (specifics omitted)

A "property" in Property Registry is actually arranged in a hierarchical manner: Estate, Property Group, Building, Space. Each property may contain assets, such as a lift, and a lift may have a breakdown report. All modules required CRUD functionality, and the two registries required a batch import and export function using Excel spreadsheets.

Problems and lessons

Modals, forms, and state management

To enable CRUD and filtering functionality, a lot of forms and modals were required, which also meant complex state management. Client-side state was managed using zustand. The forms were complex and required a lot of input validationinput validation and conditional rendering.conditional rendering.

JMM ModalFields to be rendered conditionally based on form input

With each modal and form accepting different inputs, the React components had to be carefully designed to be reusable and flexible to extension (Open-Closed Principle). This could be achieved by leveraging TypeScript.TypeScript.

JMM Model organisationSeparate concrete models for each form

As each form field had a general structure with slight variations in each module, I implemented a StrategyStrategy pattern to render the required fields and enforce their validations based off the specific module.

If a new module were to be added with separate requirements, an extension would be simple without modifying existing code.

Refactoring just enough

JMM RefactorComparison of a modal from Asset (left) and Property Registry (right)

With each new module requirement, I had to refactor the existing code to be more modular and reusable. For example, after the Property Registry was completed, the requirement of an Asset Registry was added. The Asset Registry had a similar structure to the Property Registry, but assets had different fields, validation requirements, and were not arranged in a hierarchy like properties.

Components which were closely tied to the Property Registry were refactored to be more generic and reusable. This was simply done through passing props from parent components.

However, this led to a trade-off between reusabilityreusability and readabilityreadability . I had to be careful to refactor just enough to be reusable, but not too much that it would be accepting millions of props and be difficult to read. There is also a time and place for refactoring, and I had to be careful not to over-engineer when it was not necessary.

Jest and CI/CD

While conducting unit and integration testsunit and integration tests is by no means the most exciting task for a developer, I learnt that it is especially important in the later stages of development. I wrote tests which were configured to run in the Jenkins pipeline to ensure broken code was not merged into the main branch. Through React Testing Library, I could mimic a user's interaction with the application including actions such as form inputs and button presses, and verify their expected behaviour with Jest.

Additionally, I had to fix code smellscode smells detected by SonarQube in our pipeline, which taught me about many issues that I had never considered to be bad coding practices. All this taught me the importance of writing clean, maintainable code, and to never neglect the importance of testing in a large scale application.

© 2024 | Designed and built by Amos Tan
Powered by GatsbyJS