TJ's Soapbox of Angular Practices
Generally speaking, Angular is relatively hand-holdy when it comes to what tech to use regarding testing, stylization, etc. There are always other options though, and Angular doesn't necessarily use the best one out of the box.
Additionally, it makes sense to at least be aware of some recommended coding styles when it comes to developing an Angular application.
This soapbox is a collection of those thoughts on various subjects for Angular projects.
Angular comes preinstalled with Jasmine set up, but it's somewhat outdated and unreliable when it comes to being able to mock dependencies. A more modern solution that is recommended is Jest.
Things to keep in mind:
- Every new feature should have corresponding unit tests to test any and all conditional paths.
- Mock called functions when possible, to ensure you are only testing one function at a time
- Avoid testing large object comparisons, instead opting to test specific attributes exist on both objects
- This avoids brittle tests and keeps the tests themselves smaller and more readable
- Avoid testing 3rd party libraries.
- These libraries, especially in Angular, prove to be difficult to test properly and should really have their tests handled by the contributors of said library.
The newest version of Angular has dropped support for TSLint, in favor of ESLint - due to it's ability to lint both JS and TS files.
Things to keep in mind:
- Dont reinvent the wheel, use an imported linting configuration
- Install relevant linter extension for IDE
- Confirm entire team is configured correctly, to avoid linting mismatch issues
For Angular, Prettier is the top of the game for auto code cleanup, and with a little work it can mesh nicely with existing linters
Things to keep in mind:
- Don't reinvent the wheel, fall back on the default configurations as much as possible
- Install relevant prettifying extension for IDE
- If using Prettier, make sure it's version locked in
package.json
- Code styles can change drastically even between patch versions, and if two developers have two different versions they're going to be ping-ponging Prettier changes back and forth
When it comes to making sure that tests pass, the build succeeds, linting and prettifying are run, etc - Git Hooks are the answer. They allow you to hook in to Git processes to ensure various commands are run, with the most often used ones being pre-commit
and pre-push
.
For Angular (and really any node project) Husky is a great choice for implementing these - as it allows you to configure Git Hooks in code, and automatically installs them on every developers machine, taking away the manual step of making sure they're configured and working correctly.
Generally speaking, it's good for Angular code to follow the Angular Coding Style Guide developed and released by Angular themselves. It is recommended that any developer working on Angular be familiarized with this guide, as overviews a lot of common patterns that make Angular development much cleaner and easier.
The below outlines some additional consistency standards not mentioned in that guide, and also not captured by standard Linters or Prettifiers.
Please keep in mind that every developer has opinions, but consistency trumps opinion so it’s important a standard is selected and followed to maintain the health of the repository.
In other words, that standard doesn't have to be this one, but it should be some one.
When coding, follow the pattern set out by pieces of code doing similar things. If you’re making a module, look at other modules. A service, look at other services. A component. look at other components.
This rule will help you 99.9% of the time. Again, consistency is key so following the existing pattern will likely be your answer to how you should style new code.
If you feel an existing pattern is incorrect bring it up to the team for a discussion, so that the team can move existing code over to follow the new pattern, rather than have multiple standards at once.
Avoid unpatterned and inconsistent import statements
Import statements should follow the consistent pattern of:
<Angular imports>
<3rd party imports>
<Internal open source library imports (currently none)>
<Local imports>
Avoid use of _
preceding a private property when not necessary, IE when not using getters and setters of the same name, instead opting for a readable variable name
Avoid overuse of comments.
Not every function or piece of code needs a comment - in an ideal world all code should speak for itself, with standards of variable naming and code styling helping to that end.
Instead opt for using JS Doc style comments where it makes sense - when a piece of code may not be straightforward or make sense at first glance
Avoid inconsistent file names
It's recommended that a naming scheme be decided and stuck to, whether it be kebab-case
, camelCase
or some other pattern. This avoids mixing of file naming in the application making file finding easier and imports cleaner.
IE:
- billing-payments.service.ts
- payments.guard.ts
- add-webhooks.component.ts
Avoid flat folder structures.
Instead opt to put nested components and code pieces into similarly nested folders.
This allows for more modularized component orgnization, and makes it easier to quickly find separate parts of the codebase.
IE:
webhooks/
--add-webhooks/
----add-webhooks.component.ts
----add-webhooks.component.html
--webhooks.component.html
--webhooks.component.ts
--webhooks.module.ts
Avoid unpatternened and inconsistent code ordering in components.
Code within a component could, for example, follow the consistent pattern of:
<Class variables excluding getters and setters>
<Constructor>
<Implementation functions such as ngOnInit()>
<Getters and Setters>
<Public functions>
<Private functions>
Avoid templating directly in the component declaration using template
, instead creating an html file specific to the component and load it via templateUrl
Avoid using overly complex variable setting on inputs and outputs in any components used
Instead opt to set the variable in the component code in a Getter or Setter.