JavaScript & TypeScript
Softwarequalität
Clean Code in JavaScript: Develop reliable, maintainable, and robust JavaScript
James Padolsey, 2020
Inhaltsverzeichnis des Buches
- Preface
- Who this book is for
- What this book covers
- To get the most out of this book
- Download the example code files
- Download the color images
- Conventions used
- Get in touch
- Reviews
- Section 1: What is Clean Code Anyway?
- Setting the Scene
- Why we write code
- Code as intent
- Who is the user?
- What is the problem?
- Truly understanding the problem domain
- Writing code for humans
- Communicating intent
- Readability
- Meaningful abstractions
- The tower of abstraction
- The layers of clean code
- Summary
- The Tenets of Clean Code
- Reliability
- Correctness
- Stability
- Resilience
- Efficiency
- Time
- Space
- Efficiency's effects
- Maintainability
- Adaptability
- Familiarity
- Usability
- User stories
- Intuitive design
- Accessibility
- Summary
- The Enemies of Clean Code
- Enemy #1 JavaScript
- Enemy #2 Management
- Pressure to ship
- Bad metrics
- Lack of ownership
- Enemy #3 Self
- Showing off with syntax
- Stubborn opinions
- Imposter syndrome
- Enemy #4 The cargo cult
- Cargo culting code
- Cargo culting tools and libraries
- Summary
- SOLID and Other Principles
- The Law of Demeter
- SOLID
- Single responsibility principle
- Open-closed principle
- Liskov substitution principle
- Interface segregation principle
- Dependency inversion principle
- The abstraction principle
- Over-abstraction
- Under-abstraction
- Balanced abstraction
- Functional programming principles
- Functional purity
- Immutability
- Summary
- Naming Things Is Hard
- What's in a name?
- Purpose
- Concept
- Contract
- Naming anti-patterns
- Needlessly short names
- Needlessly exotic names
- Needlessly long names
- Consistency and hierarchy
- Techniques and considerations
- Hungarian notation
- Naming and abstracting functions
- Three bad names
- Summary
- Section 2: JavaScript and Its Bits
- Primitive and Built-In Types
- Primitive types
- Immutability of primitives
- Primitive wrappers
- The falsy primitives
- Number
- String
- Boolean
- BigInt
- Symbol
- null
- undefined
- Objects
- Property names
- Property descriptors
- Map and WeakMap
- The prototype
- When and how to use objects
- Functions
- Syntactic context
- Function bindings and this
- Execution context
- super
- new.target
- arguments
- Function names
- Function declarations
- Function expressions
- Arrow functions
- Immediately Invoked Function Expressions
- Method definitions
- Async functions
- Generator functions
- Arrays and iterables
- Array-like objects
- Set and WeakSet
- Iterable protocol
- RegExp
- Regular expression 101
- RegExp flags
- Methods accepting RegExp
- RegExp methods and lastIndex
- Stickiness
- Summary
- Dynamic Typing
- Detection
- The typeof operator
- Type-detecting techniques
- Detecting Booleans
- Detecting numbers
- Detecting strings
- Detecting undefined
- Detecting null
- Detecting null or undefined
- Detecting arrays
- Detecting instances
- Detecting plain objects
- Conversion, coercion, and casting
- Converting into a Boolean
- Converting into a String
- Converting into a Number
- Converting into a primitive
- Summary
- Operators
- What is an operator?
- Operator arity
- Operator function
- Operator precedence and associativity
- Arithmetic and numeric operators
- The addition operator
- Both operands are numbers
- Both operands are strings
- One operand is a string
- One operand is a non-primitive
- Conclusion - know your operands!
- The subtraction operator
- The division operator
- The multiplication operator
- The remainder operator
- The exponentiation operator
- The unary plus operator
- The unary minus operator
- Logical operators
- The logical NOT operator
- The logical AND operator
- The logical OR operator
- Comparative operators
- Abstract equality and inequality
- Strict equality and inequality
- Greater than and less than
- Lexicographic comparison
- Numeric comparison
- The instanceof operator
- The in operator
- Assignment operators
- Increment and decrement (prefix and postfix) operators
- Prefix increment/decrement
- Postfix increment/decrement
- Destructuring assignment
- Property access operators
- Direct property access
- Computed property access
- Other operators and syntax
- The delete operator
- The void operator
- The new operator
- The spread syntax
- The comma operator
- Grouping
- Bitwise operators
- Summary
- Parts of Syntax and Scope
- Expressions, statements, and blocks
- Expressions
- Statements
- Forming statements with semicolons
- Blocks
- Scopes and declarations
- Variable declarations
- Let declarations
- Const declarations
- Function declarations
- Closures
- Summary
- Control Flow
- What is control flow?
- Imperative versus declarative programming
- The movement of control
- Invocation
- Returning
- Yielding
- Yielding to a yield
- Complexity of yielding
- Breaking
- Continuing
- Throwing
- Statements of control flow
- The if statement
- The for statement
- Conventional for
- for...in
- for...of
- The while statement
- The do...while statement
- The switch statement
- Breaking and fallthrough
- Returning from a switch directly
- Case blocks
- Multivariant conditions
- Handling cyclomatic complexity
- Simplifying conditional spaghetti
- Asynchronous control flow
- The Event Loop
- Native asynchronous APIs
- Callbacks
- Event subscribing/emitting
- Promises
- async and await
- Summary
- Section 3: Crafting Abstractions
- Design Patterns
- The perspective of a designer
- Architectural design patterns
- MVC
- A working example of MVC
- MVVM
- MV\* and the nature of software
- JavaScript modules
- Modular design patterns
- Constructor patterns
- When to use the Constructor pattern
- Inheritance with the Constructor pattern
- The Class pattern
- When to use the Class pattern
- Static methods
- Public and private fields
- Extending classes
- Mixing-in classes
- Accessing a super-class
- The Prototype pattern
- When to use the Prototype pattern
- The Revealing Module pattern
- The Conventional Module pattern
- When to use the Conventional Module pattern
- The Singleton Class pattern
- When to use the Singleton Class pattern
- Planning and harmony
- Summary
- Real-World Challenges
- The DOM and single-page applications
- DOM binding and reconciliation
- DOM reconciliation
- React's approach
- Messaging and data propagation
- Frontend routing
- Dependency management
- Module definition - then and now
- npm and package.json
- Bundling and serving
- Security
- Cross-Site Scripting
- Content Security Policy
- Subresource Integrity
- Cross-Site Request Forgery
- Other security vulnerabilities
- Summary
- Section 4: Testing and Tooling
- The Landscape of Testing
- What is a test?
- The simple assertion
- Many moving parts
- Types of testing
- Unit testing
- Integration testing
- E2E and functional testing
- Test-Driven Development
- Summary
- Writing Clean Tests
- Testing the right thing
- Writing intuitive assertions
- Creating clear hierarchies
- Providing final clarity
- Creating clean directory structures
- Summary
- Tools for Cleaner Code
- Linters and formatters
- Static typing
- E2E testing tools
- Automated builds and CI
- Summary
- Section 5: Collaboration and Making Changes
- Documenting Your Code
- Aspects of clean documentation
- Concept
- Specification
- Instruction
- Usability
- Documentation is everywhere
- Writing for non-technical audiences
- Summary
- Other Peoples' Code
- Inheriting code
- Exploring and understanding
- Making a flowchart
- Finding structure and observing history
- Stepping through the code
- Asserting your assumptions
- Making changes
- Minimally invasive surgery
- Encoding changes as tests
- Dealing with third-party code
- Selection and understanding
- Encapsulating and adapting third-party code
- Summary
- Communication and Advocacy
- Planning and setting requirements
- Understanding user needs
- Quick prototypes and PoCs
- Communication strategies
- Listen and respond
- Explain from the user's perspective
- Have small and focused communications
- Ask stupid questions and have wild ideas
- Pair programming and 1:1s
- Identifying issues and driving change
- Raising bugs
- Driving systemic change
- Summary
- Case Study
- The problem
- The design
- The implementation
- The Plant Selection application
- Creating the REST API
- Creating the client-side build process
- Creating the component
- Summary