Hone logo
Hone
Problems

Angular Dependency Tracking Service

Dependency tracking in Angular applications can be invaluable for debugging, performance optimization, and understanding the flow of data. This challenge asks you to create a service that tracks component dependencies (inputs and outputs) and provides a way to visualize or analyze these dependencies. This will help you understand how changes in one component can affect others, leading to more maintainable and efficient applications.

Problem Description

You need to build an DependencyTrackerService that monitors component inputs and outputs. The service should be injectable into Angular components and provide methods to register and retrieve dependency information. The service should track the component's name, a list of input dependencies (other components providing data), and a list of output dependencies (components consuming data from this component).

Key Requirements:

  • Registration: Components should be able to register themselves with the service, providing their name and a list of their input and output dependencies.
  • Retrieval: The service should provide a method to retrieve the dependency information for a given component name.
  • Data Structure: Use a suitable data structure (e.g., a Map or object) to store the dependency information efficiently.
  • Clear Interface: The service should have a clean and well-defined interface for registration and retrieval.
  • No External Libraries: Solve this using only standard TypeScript and Angular features.

Expected Behavior:

  • When a component registers with the service, its name and dependencies are stored.
  • Retrieving dependency information for a registered component returns the stored data.
  • Retrieving dependency information for an unregistered component returns undefined or an appropriate error indicator.

Edge Cases to Consider:

  • Circular dependencies (Component A depends on Component B, and Component B depends on Component A). While you don't need to prevent them, consider how the service will handle them (e.g., infinite loops when traversing dependencies).
  • Component names that are not unique. The service should handle this gracefully (e.g., overwrite existing entries or throw an error).
  • Empty dependency lists (a component has no inputs or outputs).
  • Null or undefined input/output dependency names.

Examples

Example 1:

Input:
Component A registers with the service:
  Name: 'ComponentA'
  Inputs: ['ComponentB']
  Outputs: ['ComponentC']

Component B registers with the service:
  Name: 'ComponentB'
  Inputs: []
  Outputs: []

Component C registers with the service:
  Name: 'ComponentC'
  Inputs: []
  Outputs: []

Output:
dependencyTrackerService.getDependencies('ComponentA') returns: { name: 'ComponentA', inputs: ['ComponentB'], outputs: ['ComponentC'] }
dependencyTrackerService.getDependencies('ComponentB') returns: { name: 'ComponentB', inputs: [], outputs: [] }
dependencyTrackerService.getDependencies('ComponentC') returns: { name: 'ComponentC', inputs: [], outputs: [] }
dependencyTrackerService.getDependencies('ComponentD') returns: undefined

Explanation: The service correctly stores and retrieves dependency information for registered components. It returns undefined for unregistered components.

Example 2:

Input:
Component A registers with the service:
  Name: 'ComponentA'
  Inputs: []
  Outputs: ['ComponentB', 'ComponentC']

Component B registers with the service:
  Name: 'ComponentB'
  Inputs: ['ComponentA']
  Outputs: []

Output:
dependencyTrackerService.getDependencies('ComponentA') returns: { name: 'ComponentA', inputs: [], outputs: ['ComponentB', 'ComponentC'] }
dependencyTrackerService.getDependencies('ComponentB') returns: { name: 'ComponentB', inputs: ['ComponentA'], outputs: [] }

Explanation: Demonstrates a simple circular dependency. The service should not crash, but the retrieval might show the circular relationship.

Constraints

  • Component Names: Component names are strings.
  • Dependency Lists: Input and output dependencies are arrays of strings (component names).
  • Performance: The service should be able to handle a reasonable number of components (e.g., up to 100) without significant performance degradation. Retrieval should be O(1) on average.
  • Error Handling: The service should not throw errors if a component is not found. Return undefined instead.

Notes

  • Consider using a Map for efficient key-value storage of component names and dependency information.
  • Think about how you will design the service's interface to be easy to use and extend.
  • You don't need to implement a visual representation of the dependencies; the focus is on the data tracking and retrieval.
  • The service should be injectable into Angular components using the Angular dependency injection system.
  • Focus on the core functionality of tracking and retrieving dependencies. Error handling and edge case management are important, but don't over-engineer the solution.
Loading editor...
typescript