How to not develop Angular application
Hello geeks, let me tell you something… Angular is fantastic framework not just to use but to scale. In this article I'll tell you how to not make it blunderbuss decision.
After working on Angular for more than 5 years straight, I came across some interesting problems which projects were facing due to lack of awareness on UI guidelines. Looking back at learnings I took from those assignments I came to write down this article about common nature of design problems faced by me.
Mentioned below are the some of my own curated antipatterns I want to talk about.
Creating a complicated project structure-
Trust me it is very important to follow readable, extendable & maintainable file structure specially in any framework where decomposability is one of core feature of your framework.
- Don't follow component driven hierarchy instead follow feature driven one. Arrange components under modules & make module represent your application feature.
E.g. I have toolbar, header, one data table on my page like shown below I recommend to go for feature one as it is somewhat unrestricted.
//component driven
--header
|---toolbar.component.ts
--body
|---datatable.component.ts
//feature driven
--navigations
|---toolbar.component.ts
--dataload
|---datatable.component.ts
2. Prefer to use modules mapped to features not technical blocks. I mean don't map your modules to technical entities like sidebar, menu bar, header, footer, data panel, data table instead go for structuring based on its use & purpose e.g. menu links, user widgets, data content.
Confusing the definition of reusability
- Putting down the clear definition on what is reusable & what's not in early stage of development is always better.
- Segregation of core & common UI components. Have brainstorming on what is core elements of your UI, usually it is essential things of app like pipes, AUTH guards, resolvers, authentication logic, constants, HTTP interceptors, login/ logout screens, validators etc.
- Common can include reusable things like header, footer, navbar, sidebar any other UI block which is appearing multiple times in your application UI. It can include things which are referenced multiple times in your app like models, interfaces, classes, type definitions, directives, forms, Enums definitions.
- Apart from models (classes) & interfaces, DTOs can be used to group data together.
Making unmaintainable services
There are 2 scenarios
- Its good to organize services file in separate /service folder instead of putting it under every modules if your service is less cohesive.
- If your services have considerable dependency on module level things lets say Enums, constants, type definition put it in module/services.
Do not inject services in root rather scope them to their usage.
Using JavaScript in Angular
Make best use of ES6 via Typescript. It help in adding syntactic sugar which results in less Line of Code. Plain vanilla JavaScript code should be avoided over Typescript.
Not leveraging typescript at its full potential
- Use strict types instead of any.
- Create custom types wherever applicable.
- Promote object oriented + functional design.
- Generics- go for it, trust me it will reduce line of code.
Duplicating the styles rules
Try to global styling rules if it is referenced at multiple places.
Ignoring performance tradeoffs
- Less use of template variables. Remember each 2 way binded variable is eligible for change detection.
- Don't go with default change detection mechanism strategy rather looks for customizing it as per application need. Optimize Runtime Performance using OnPush, ChangeDetection .By default, Angular uses the ChangeDetectionStrategy.Default change detection strategy on all components, meaning it will undergo change detection with nearly any user interaction. This is not very efficient. Components should be re-rendered if the @Input changes. We should use ChangeDetectionStrategy.OnPush strategy for Component Decorater. The same goes for pipes. we should add ‘pure: false’ to the pipe decorater.
- Avoid *ngFor without trackBy.
- Avoid impure pipes.
- Cache the http calls.
- RxJS is must- Cascaded subscriptions should be avoided.
- Avoid writing logic in templates, it helps to decouple templates from logic and can be changed in future if required with minimal impact.
- Network calls must always be made in a service- dependency injection is a performance savior.
- Lazy load the modules.
- Do not directly import a module in a lazy loaded feature.
- Look for memory leaks in Observable — either use async Pipe or takeUntil(). Clean-up subscriptions while unmounting a component.
- ESLint issues should be addressed.
- Do not add filtering and sorting logic to pipes — do it in components or services before binding the model in templates.
Not knowing server side rendering :(
Not using environment.ts for right purpose
Use it for common metadata about environment like , http connection, instance properties. For Docker related configuration environment.ts is ideal place to sit.
Believing console.log() is a debugging
Nobody wants a code which is not adding any value in production make your application look clean.
Unawareness about design patterns
Be mindful on applying design patters like SOLID, DRY , Creational, Structural, Behavioral.