Bitcoin

The Case for Factory Functions: Reducing Bugs and Technical Debt in Angular + Microservices Projects

In modern, corroservice -based applications, management of consistency and data reliability is a persistent challenge. When developing the front with Angular / React, we are often at the mercy of the changes in the Backend API, partial data responses and an unpredictable user input. Despite the progress of typing typing typing, many teams are still suffering from execution errors such as “impossible to read the” X “non -defined” property, broken user interface states and backend validation failures due to poorly trained objects. In short, the construction of manual objects invites small, drift

duplication and cod bases; Problems that consist as the application and the team develop. A recurring scheme emerges:Construction of manual objects

where developers instantly instantly instantly defining each property. Although this approach seems fast at the start, it introduces hidden risks as applications develop in complexity.

This article explores why the use of factory functions with partial types is a higher approach, especially in angular projects that consume several microservices. Factory functions not only eliminate unfained fields and execution accidents, but also considerably improves the team's maintainability, testability and long -term speed. By centralizing both the definition of type and its factory function In one place, we create a clear source of truth for each data structure. This proactive strategy guarantees not only the forms of coherent objects through the application, but also considerably simplifies maintenance when Backend contracts evolve. By applying reasonable default values ​​at the time of creation, wereduce bugs ,,Simplify tests And Our applications to the test Against diagram changes and service instability. In the following sections, we decompose the risks of creating manual objects, the nucleusAdvantages of factory functions

Examples of the real world where production systems saved by default, and how a small initial investment in a clean factory model bears fruit in an exponential way as the systems are on the scale of systems.

The risks of construction of manual objects

const userProfile: UserProfile = { id: 'abc123', name: 'John Doe' }; 
//{ id: 'abc123', name: 'John Doe' } <-- this may be a response from an API call, 
//or you manually want to set it this way for whatever reason

In large -scale applications, in particular those built at the top of several Backend microservices, the construction of manual objects quickly becomes a source of hidden technical debt. When the developers create objects online by specifying each property manually, several risks emerge: let's take a look at an initial concept when you manually create your object:

const userProfile: UserProfile = {
  id: 'abc123',
  name: 'John Doe',
  email: '[email protected]',
  isPremiumUser: true,
  lastLogin: new Date(),
  //...potentially many more fields
};

Suppose now that Leprofile User has more fields:

type UserProfile = {
  id: string;
  name: string;
  email?: string;
  isPremiumUser?: boolean;
  lastLogin?: Date;
};

But we want to define the ID and the name only; It's cleaner, looks more pleasant, or you are just in a hurry; You might be tempted to modify the type like this:

  1. Certain reasons why is probably a bad idea:
  2. The data model is now not really reliable. In reality, fields like emails and lastlogin may be necessary at the time of execution.
  3. You lose type safety because now, everywhere in your application, Typecript thinks that email may be missed even in places where it should exist.
  4. You invite bugs, you probably no longer need you? ; So why try your luck, you must also constantly write guards like – → If (userprofile.email): even in places where it should never be missed.

You weaken the Backend communication because when you return the loads useful to an API, the fields can be wrongly omitted. Instead of weakening your types, a better solution is to keep the type strict and use a factory function with partial

export function createUserProfile(init: Partial = {}): UserProfile {
  return {
    id: init.id ?? '',
    name: init.name ?? '',
    email: init.email ?? '',
    isPremiumUser: init.isPremiumUser ?? false,
    lastLogin: init.lastLogin ?? new Date(0),
  };
}

To create objects flexible and safely without compromising the integrity of the application type:

const userProfile = createUserProfile({ id: 'abc123', name: 'John Doe' });

This method preserves the complete safety of userprofile throughout the application, while allowing partial initialization during the creation of objects.

Some problems you can expect with the creation of manual objects Missing or not defined properties

– Backend services evolve. New fields are added and existing ones are changing. Manually instantial objects often leave the new or updated fields aside, … could lead to execution errors as unlikely, is not a broken user function or elements. These bugs are difficult to detect at the time of compilation and often only surface during tests at an advanced or worse stage, in production. Fragile and duplicate code

– Without creation of centralized objects, the same object structure must be recreated manually between components, services and tests. This duplication increases the risks of inconsistency. If a new field required is added, each manual instantiation must be found and updated individually, a tedious process and subject to errors that makes your day bad. More difficult tests and debug

– Tests are often based on simulated objects. If the default values ​​are not systematically applied, test models may subtly differ from production data forms. This leads to false positives or to missed edge cases during tests, undermining the value of your test suite. You might think it's not a big problem now, but your application could become extremely complicated software on which other people should start working. Unreliable data sent to backends

– In financial or commercial applications, sending incomplete or ill -trained data to Backend services may have serious consequences. The creation of manual objects increases the risk of sending useful, unlikely or otherwise invalid loads which cause validation errors Backend or, worse, the corruption of silent data (SDC).Over time, while the construction of manual objects continues, the models of your application, data contracts and backend expectations gradually “

Separate, “create inconsistencies that are difficult to detect but costly to repair.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button

Adblocker Detected

Please consider supporting us by disabling your ad blocker