Angular
Good Practices

Rainer Stropek | @rstropek

1. There are no
"best" practices

There are not "best" practices

  • There are general guidelines that have proven to be useful
  • Patterns and practices heavily depend on the project and its environment
    • Avoid one-size-fits-all mentality
    • Project: Size, complexity, requirements (e.g. offline mode), maturity
    • Environment: Experience (general, with ng), # of devs, tools, constraints

There are not "best" practices

  • Striving for "best" practices can prevent reaching real-world goals
    • Danger: Spend time for research instead of getting things done
  • Applying wrong "best" practices can lead to unwanted results
    • Over-engineering (=too complex, opportunity costs)
    • Overly smart code (=hard to read and maintain)
    • Conflicts, many "best" practices are subjective

Do's and dont's

  • Always ask "Why?"
    • If you have no good answer, don't follow a "best" practice
  • Have a plan and a vision
    • Clear near-term view on development, long-term vision
  • Don't fixate on "best" practices
    • Patterns and practices should be able evolve
    • Regularly question established practices
    • Don't let the desire for conformity prevent innovation and progress
  • My 5D rule for good practices:
    • Develop
    • Document
    • Demonstrate
    • Discuss
    • Double-check

2. Keeping up to date

Keeping up to date

  • Do not fall behind too much with Angular updates
    • One major release every 6 months
    • 6 months of active support with updates and patches
    • 12 months of critical fixes and security updates
  • Tip: Update at least ~every 12 months
    • Update whenever it fits to project schedule

3. How to structure your Angular app

KISS 😘 and LIFT πŸ›—

  • Keep it simple as long as you can
  • LIFT guidelines
    • Locating our code is easy
    • Identify code at a glance
    • Flat structure as long as we can
    • Try to stay DRY (Don't Repeat Yourself)
  • Avoid...
    • ...splitting your app into packages/repos if you don't need separation
    • ...spreading code related to one feature over the entire code base
    • ...nesting your folder structure unnecessarily deep
      (ng: up to 10 files in a folder)
  • Do... (exceptions prove the rule)
    • ...use descriptive (long) names (e.g. files, folders, modules, types)
    • ...create separate files for each component
    • ...put a component with multiple files in a separate folder
  • Source code in src
  • Core or Common for services used throughout the app
  • SharedΒ for reusable components, pipes, directives, etc.
  • Traditionally with modules
    • One root module app.module.ts
    • Folders/modules for feature areas (e.g. heroes, villains)
  • New projects/code: Consider libraries with standalone components
  • Consider lazy loading if beneficial
    • Works with and without modules

Demo
Time!

4. Where to put logic?

Logic in services

  • Put logic that is not or loosely connected to view into services. Examples:
    • Talking to the server
    • Filtering/sorting/grouping logic
    • Calculation logic
  • Put reusable logic into services
  • Use services to share data
  • Single responsibility per service

Logic in components

  • Never put view logic in templates
    • Put view logic in component classes

5. Do proper
data binding

Data Binding

  • Data binding can be the reason for performance problems
    • KISS still applies
    • Don't waste time optimizing code if performance is adequate
  • Use pipes to transform value
    • Much fewer transformations compared to functions
  • Consider OnPushΒ detection strategy
    • Can reduce overhead for change detection and data binding
    • ⚠️ Has potential unwanted side effects
  • Be reactive!

Demo
Time!

6. Do use Strict mode

Strict Mode

  • TypeScript strict mode πŸ”—
  • Angular strict checks πŸ”—
  • Enable whenever possible
    • New projects
    • Projects where quality requirements are high
    • Projects that are actively developed
    • Consider enabling on project-level

How to handle undefined/null?

  • TypeScript
    • Optional Chaining operator (?.)
    • Nullish Coalescing (??)
    • Non-null assertation operator (!)
    • Type guards
function isDefined<T>(value: T | null | undefined): value is T {
  return value !== null && value !== undefined;
}

How to handle undefined/null?

  • Angular
    • Safe navigation Operator (?.)
    • Conditional rendering with *ngIf
    • (Reactive) form validation to prevent submitting nulls

7. Do write
automated tests

Built-in Testing Techniques

  • Unit tests
    • Test small units of logically connected elements
      (e.g. functions, services, component classes)
    • Angular CLI: Uses Jasmine and Karma by default
  • Component DOM testsπŸ”—
    • Tests component logic and template
    • Components are tested in isolation
    • Mocking of dependencies is possible/recommended

3rd Party Testing Tools

8. What Else?

  • Speed-up builds by using Nx
  • @nrwl/angular πŸ”— for managing larger applications
    • Microfrontends
    • Built-in integration with Storybook, Jest, and Cypress

NgRx πŸ”—

  • State management system based on Redux
  • For managing state in larger applications

Q&A

Rainer Stropek | @rstropek