Legacy JavaScript (on hold) 🇵🇱 🇬🇧 2 days
Why this course?
Approach tackling legacy JS holistically.
First, perform strategic analysis to find where the dragons are
and focus on the code that matters most.
Second, learn refactoring tactics to gradually make code better.
Agenda
Strategic analysis of large JS codebases
We'll use behavioral code analysis based on Git history to
perform architectural audits of famous open-source JS codebases:
- Frontend frameworks (e.g. React, Angular, Vue)
- Backend frameworks (e.g. Express, Next.js)
- Business Apps (e.g. Netlify CMS, Spectrum)
- Bundlers (e.g. Parcel, Webpack)
- Test frameworks (e.g. Jest, Mocha, Tape)
In the process we'll:
- discover hotspots to focus our effort on complex parts that change often
- find unexpected temporal coupling that's invisible in the code structure alone
- use code age as a driver to split mixed responsibility packages and extract libraries
- discover excessive coordination needs and incorrect team boundaries
- simulate knowledge loss when your best developer leaves
This part is based on excellent tool codescene.io.
We'll follow up our analysis with legacy code review identifying common issues and possible corrective actions to deal with:
- classes and functions with mixed responsibilities
- primitive obsession, missing abstraction and mixed levels of abstraction
- technology-driven architecture leading to shotgun surgery
- some code duplication (because sometimes copy-paste is a good thing)
Tactical refactoring of JS code
In the coding section we'll go through three refactoring katas:
- changing complex business logic from procedural to object-oriented to functional style
- decoupling hardcoded dependencies
- untangling legacy DOM code mixed with business logic
In the process we'll:
- lock down behavior with text-based approval/snapshot testing
- describe the actual behavior with targeted characterization unit tests
- find seams in legacy code to alter behavior of a program without editing in place
- identify misplaced behavior and extract classes/functions
- remove excess conditional logic and introduce missing abstraction
- use code coverage to detect dead code
- find feature envy code breaking Law of Demeter
- refactor towards DI injectable code
- cover DOM based code with jsdom based unit tests
- wait for asynchronously rendered nodes in DOM tests
- free our code from "this" shenanigans