Get the most out of JavaScript for building web applications through a series of patterns, practices, and case studies in the service of clean coding
Key Features
Understand the true purpose of code and the problems it solves for your end-users and colleagues
Discover the tenets and enemies of clean code considering the effects of cultural and syntactic conventions
Use modern JavaScript syntax and design patterns to craft intuitive abstractions
Maintain code quality within your team via wise adoption of tooling and advocating best practices
Learn the modern ecosystem of JavaScript and its challenges like DOM reconciliation and state management
Express the behavior of your code both within tests and via various forms of documentation
About
Building robust apps starts with creating clean code. In this book, you’ll explore techniques for doing this by learning everything from the basics of JavaScript through to the practices of clean code. You’ll write functional, intuitive, and maintainable code while also understanding how your code affects the end user and the wider community.
The book starts with popular clean-coding principles such as SOLID, and the Law of Demeter (LoD), along with highlighting the enemies of writing clean code such as cargo culting and over-management. You’ll then delve into JavaScript, understanding the more complex aspects of the language. Next, you’ll create meaningful abstractions using design patterns, such as the Class Pattern and the Revealing Module Pattern. You’ll explore real-world challenges such as DOM reconciliation, state management, dependency management, and security, both within browser and server environments. Later, you’ll cover tooling and testing methodologies and the importance of documenting code. Finally, the book will focus on advocacy and good communication for improving code cleanliness within teams or workplaces, along with covering a case study for clean coding.
By the end of this book, you’ll be well-versed with JavaScript and have learned how to create clean abstractions, test them, and communicate about them via documentation.
Features
Write maintainable JS code using internal abstraction, well-written tests, and well-documented code
Understand the agents of clean coding like SOLID principles, OOP, and functional programming
Explore solutions to tackle common JavaScript challenges in building UIs, managing APIs, and writing states
Author(s): James Padolsey
Publisher: Packt
Year: 2020
Cover
Title Page
Copyright and Credits
About Packt
Contributors
Table of Contents
Preface
Section 1: What is Clean Code Anyway?
Chapter 1: 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
Chapter 2: 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
Chapter 3: 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
Chapter 4: 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
Chapter 5: 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
Chapter 6: 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
Chapter 7: 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
Chapter 8: 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
Chapter 9: 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
Chapter 10: 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
Chapter 11: 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
Chapter 12: 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
Chapter 13: 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
Chapter 14: Writing Clean Tests
Testing the right thing
Writing intuitive assertions
Creating clear hierarchies
Providing final clarity
Creating clean directory structures
Summary
Chapter 15: Tools for Cleaner Code
Linters and formatters
Static typing
E2E testing tools
Automated builds and CI
Summary
Section 5: Collaboration and Making Changes
Chapter 16: Documenting Your Code
Aspects of clean documentation
Concept
Specification
Instruction
Usability
Documentation is everywhere
Writing for non-technical audiences
Summary
Chapter 17: 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
Chapter 18: 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
Chapter 19: 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
Other Books You May Enjoy
Index