Start free trial
EnglishEnglish
EspañolSpanish
简体中文Chinese
繁體中文Chinese (Traditional)
FrançaisFrench
DeutschGerman
日本語Japanese
PortuguêsPortuguese
ItalianoItalian
한국어Korean
РусскийRussian
NederlandsDutch
العربيةArabic
PolskiPolish
हिन्दीHindi
Tiếng ViệtVietnamese
SvenskaSwedish
ΕλληνικάGreek
TürkçeTurkish
ไทยThai
ČeštinaCzech
RomânăRomanian
MagyarHungarian
УкраїнськаUkrainian
IndonesiaIndonesian
DanskDanish
SuomiFinnish
БългарскиBulgarian
עבריתHebrew
NorskNorwegian
HrvatskiCroatian
CatalàCatalan
SlovenčinaSlovak
LietuviųLithuanian
SlovenščinaSlovenian
СрпскиSerbian
EestiEstonian
LatviešuLatvian
فارسیPersian
മലയാളംMalayalam
தமிழ்Tamil
اردوUrdu
Searching...
SoBrief
The Passing of the Great Race or the Racial Basis of European History

The Passing of the Great Race or the Racial Basis of European History

by Madison Grant 1916 148 pages
3.34
187 ratings
Amazon Kindle Audible
Try Full Access for 3 Days
Unlock listening & more!
Continue

Key Takeaways

1. Classical inheritance is obsolete; favor object composition

The child classes are all programming to an implementation, not an interface. Classical inheritance breaks the principle of encapsulation and tightly couples the child class to its ancestors.

The inheritance trap. Classical inheritance tightly couples child classes to their ancestors, breaking encapsulation and creating rigid, brittle hierarchies. When a parent class changes, the effects cascade unpredictably down the inheritance tree, often requiring massive refactoring. This architectural rigidity makes it incredibly difficult to adapt software to changing requirements over time.

Lego-like composition. Object composition allows developers to build complex systems by combining small, independent, reusable objects. Instead of predicting rigid taxonomies, you assemble features dynamically using techniques like:

  • Prototypal delegation (sharing methods via a prototype chain)
  • Concatenative inheritance (cloning properties from source objects)
  • Functional inheritance (using closures to mix in private state)

Dynamic object extension. JavaScript's classless nature means you can add, modify, or delete properties of any object at runtime. This dynamic flexibility renders complex design patterns like Singletons obsolete, reducing them to simple object literals. By embracing composition over inheritance, your code remains flexible, resilient, and easy to extend.

2. Functions are the ultimate building blocks of JavaScript applications

In JavaScript, objects are not a tacked-on afterthought. Nearly everything in JavaScript is an object, including functions.

First-class citizens. In JavaScript, functions are first-class objects, meaning they can be assigned to variables, passed as arguments, and returned from other functions. This capability enables functional programming paradigms, allowing developers to write highly expressive, concise, and reusable code. It elevates functions from simple subroutines to powerful data structures.

Core design principles. To write robust functions, developers must adhere to three foundational software engineering guidelines:

  • Don't Repeat Yourself (DRY): Encapsulate repeated patterns into reusable functions.
  • Do One Thing (DOT): Ensure each function has a single, well-defined responsibility.
  • Keep It Simple Stupid (KISS): Avoid overly clever, cryptic code in favor of readability.

Pure and stateless. Minimizing side effects is crucial for code reliability and horizontal scaling. Pure functions do not modify external state and always return the same output for the same inputs, making them highly testable and safe for concurrent execution. Writing stateless functions ensures that your application remains predictable and easy to debug.

3. Closures provide data privacy and state preservation

In a nutshell, a closure stores function state, even after the function has returned.

Encapsulating private state. Closures are created when an inner function references variables declared in an outer function's scope, even after the outer function has finished executing. This mechanism is the primary way to achieve true data privacy in JavaScript, shielding internal state from unauthorized external modification. It allows developers to mimic private variables found in classical languages.

Privileged access methods. By exposing specific methods that have access to the closed-over variables, you create a secure interface for your objects. This pattern replaces the need for classical private access modifiers found in other languages:

  • Private variables remain completely inaccessible to the outside world.
  • Exposed "privileged" methods act as controlled gateways to read or write the private data.
  • Object factories leverage closures to instantiate secure, instance-safe objects without the new keyword.

Asynchronous state preservation. Closures are indispensable for handling asynchronous callbacks and event listeners. They ensure that when an event fires—perhaps seconds or minutes after the initiating function has returned—the callback still has access to the exact environment in which it was born. This makes managing asynchronous flows intuitive and robust.

4. Program to an interface, not an implementation, using modules

If you design parts of a system to a modular interface contract instead, you can safely make changes without having a deep understanding of all of the related modules.

The modular contract. Modules are the essential building blocks of robust applications, encapsulating implementation details and exposing clean, public APIs. By programming to a stable interface rather than a concrete implementation, you decouple system components and prevent changes in one area from breaking another. This separation of concerns is vital for scaling development teams and codebases.

Characteristics of good modules. Well-designed modules behave like independent, pluggable components in an entertainment system:

  • Specialized: Focused on solving a single, specific problem.
  • Independent: Knowing as little as possible about other modules.
  • Decomposable: Easily isolated, tested, and run in a sandbox.
  • Substitutable: Capable of being swapped out for an alternative implementation of the same interface.

Standardizing module formats. JavaScript has evolved several module standards to manage dependencies across different environments. While the module pattern and AMD served client-side needs, CommonJS (Node-style) and ES6 modules have standardized synchronous and declarative dependency resolution. Utilizing modern bundlers allows developers to write clean, modular code that runs efficiently in any environment.

5. Separate presentation concerns from business domain logic (MV*)

The goal of MVC and related patterns is to separate data management from presentation.

Separation of concerns. Mixing business logic with user interface code creates highly coupled, fragile applications that are incredibly difficult to maintain. By separating these concerns, you ensure that your data models remain agnostic of how they are displayed, and your views remain agnostic of how data is stored. This allows designers and developers to work in parallel without stepping on each other's toes.

The MV* landscape. Modern JavaScript applications utilize various architectural patterns to structure this separation, collectively known as MV*:

  • Model: Manages application state, business rules, and data persistence.
  • View: Handles presentation, rendering templates, and capturing user interactions.
  • Controller/Presenter/ViewModel: Coordinates updates between the model and the view.

Template-driven rendering. Templates separate HTML structure from JavaScript logic, allowing developers to define UI layouts declaratively. Modern template engines compile these structures into executable functions, injecting dynamic data safely while preventing cross-site scripting vulnerabilities. This ensures that DOM manipulation remains predictable, performant, and isolated from core business rules.

6. Decouple modules using event aggregators instead of direct references

An aggregator eliminates the need for specialized mediators to keep an emitter and listener decoupled.

Loose coupling via events. Direct references between modules create tight coupling, making it difficult to modify or reuse individual components. Event-driven architecture allows modules to communicate asynchronously by broadcasting what happened, rather than commanding other modules what to do. This shifts the responsibility of coordination away from individual modules.

Choosing the right event model. Different communication scenarios require distinct event patterns to balance complexity and flexibility:

  • Event Emitters: Direct, object-specific notifications (e.g., a model notifying its view of a change).
  • Event Aggregators: A central message bus where any module can publish or subscribe to events anonymously.
  • Message Queues: Durable, managed queues that guarantee message delivery across distributed system tiers.

The power of anonymity. Using a central event aggregator, the publishing module does not need to know who is listening, and the subscribing module does not need to know who sent the message. This absolute anonymity makes it trivial to add, remove, or swap modules without modifying the rest of the application. It is the cornerstone of highly scalable, real-time web architectures.

7. Secure authentication requires key stretching, salting, and multifactor verification

Because of the threat of stolen passwords, any policy that relies solely on password protection is unsafe.

Defeating brute force. Storing passwords as simple, single-iteration cryptographic hashes is highly vulnerable to modern brute-force attacks and GPU-accelerated cracking. To protect user credentials, developers must employ key stretching algorithms like bcrypt or PBKDF2, which artificially slow down the hashing process to make brute-force attacks computationally impractical. This ensures that even if a database is compromised, the passwords remain secure.

Neutralizing rainbow tables. Attackers use precomputed tables of hashes, known as rainbow tables, to instantly look up stolen password hashes. To neutralize this threat, every password must be paired with a unique, cryptographically secure random salt before hashing:

  • Salts must be generated using secure entropy sources like Node's crypto.randomBytes().
  • A unique salt ensures that identical passwords produce completely different hashes.
  • Constant-time equality checks must be used during verification to prevent timing attacks.

Multifactor defense. True security requires combining multiple authentication factors: something the user knows (passwords), something the user has (mobile authenticator tokens), and something the user is (biometrics). Implementing time-based one-time passwords (TOTP) via speakeasy or Google Authenticator provides a robust second line of defense. This drastically reduces the risk of unauthorized access due to credential leaks.

8. Build self-describing, hypermedia-driven RESTful APIs (HATEOAS)

All application state transitions must be driven by client selection of server-provided choices that are present in the received representations or implied by the user’s manipulation of those representations...

Hypermedia as the engine. A truly RESTful API must be hypermedia-driven, meaning the server provides the client with all available actions and navigational links dynamically within the response. This principle, known as HATEOAS, decouples the client from hardcoded server endpoints, allowing the API to evolve without breaking client applications. It transforms the API into a discoverable, self-documenting web of resources.

Affordances and state transitions. Affordances are the controls embedded in a resource representation that tell the client what actions are possible:

  • Outbound links (href) allow navigation to related resources.
  • Query templates define how the client can search or filter data.
  • Non-idempotent actions (like POST) and idempotent actions (like PUT/DELETE) are explicitly declared.

Coding to the media type. To achieve maximum flexibility, client applications should be programmed to understand the rules of the media type (e.g., JSON-LD, Siren, or Jiron) rather than the specific data payload. This allows a single, generic client SDK to navigate and interact with completely different API services seamlessly. It represents the ultimate realization of service-oriented architecture.

9. Decouple code deployment from feature releases with feature toggles

A feature toggle system allows you to integrate features into your codebase even before they’re finished and ready to release.

Continuous deployment. Feature toggles (or feature flags) are a crucial tool for continuous integration and deployment, enabling developers to merge unfinished code into the main branch safely. By wrapping new features in conditional toggle checks, code can be deployed to production continuously without exposing incomplete features to users. This eliminates long-lived, painful feature branches.

Managing the feature lifespan. Features progress through a structured lifecycle from development to full integration:

  • Development: Hidden behind toggles, tested locally and in staging.
  • Production Testing: Toggled on only for internal QA or automated smoke tests in the live environment.
  • Gradual Rollout: Enabled for a small percentage of users (e.g., 10%) to monitor performance and business metrics.
  • Full Integration: The toggle is removed from the codebase once the feature is permanently adopted.

Dynamic runtime configuration. Feature toggles can be controlled dynamically at runtime based on user IDs, geographic locations, or account tiers. This allows product teams to perform canary releases, run A/B tests, and instantly roll back problematic updates without redeploying code. It shifts control of feature releases from engineering to product management.

10. Design for internationalization from the very first line of code

By far, the easiest way to support internationalization is to plan for it up front, as soon as you start building templates.

Upfront planning. Retrofitting internationalization (i18n) into an existing, mature codebase is an incredibly painful, error-prone, and expensive process. To avoid this, developers must establish a habit of running every user-facing string, date, number, and currency value through a localization library from day one. This simple discipline saves hundreds of hours of refactoring later.

Leveraging standard databases. Rather than rolling custom translation and formatting engines, developers should rely on established standards and libraries:

  • Globalize utilizes the Unicode Common Locale Data Repository (CLDR) for robust formatting.
  • Moment.js handles complex, locale-specific date and time formatting.
  • i18next provides powerful string translation, pluralization, and interpolation features.

Managing locale delivery. To optimize performance, avoid shipping the entire global translation catalog to every client. Instead, detect the user's preferred locale via browser headers or cookies, and dynamically bundle only the required translation files with the initial page payload. This ensures a fast, localized user experience without unnecessary bandwidth overhead.

Last updated:

Report Issue

Review Summary

3.34 out of 5
Average of 187 ratings from Goodreads and Amazon.

"The Passing of the Great Race" receives mixed reviews, with ratings ranging from 1 to 5 stars. Some readers praise it as a significant work on European racial history, while others condemn it as pseudoscience promoting white supremacy and eugenics. Critics argue it's based on obsolete concepts and biased interpretations of history. Some find it historically interesting but morally reprehensible. The book's influence on early 20th-century racial theories and its connection to Nazi ideology are frequently mentioned. Many readers express discomfort with its racist content.

Your rating:
3.98
101 ratings
Want to read the full book?

About the Author

Madison Grant was a multifaceted figure in early 20th-century America, known for his work in law, history, racial theory, eugenics, and anthropology. He gained prominence for his contributions to conservation efforts and his promotion of eugenics, particularly the "Nordic migration theory" and the concept of a "master race." Grant's influence extended to various philanthropic organizations, where he actively participated. He strongly advocated for restricting immigration and supported anti-miscegenation laws. His racial theories, though now widely discredited, had a significant impact on early 20th-century thought and policy, influencing both American and European ideologies related to race and eugenics.

Download PDF

To save this The Passing of the Great Race or the Racial Basis of European History summary for later, download the free PDF. You can print it out, or read offline at your convenience.
Download PDF
File size: 0.30 MB     Pages: 13

Download EPUB

To read this The Passing of the Great Race or the Racial Basis of European History summary on your e-reader device or app, download the free EPUB. The .epub digital book format is ideal for reading ebooks on phones, tablets, and e-readers.
Download EPUB
File size: 1.44 MB     Pages: 13
Want to read the full book?
Follow
Listen
Now playing
The Passing of the Great Race or the Racial Basis of European History
0:00
-0:00
Now playing
The Passing of the Great Race or the Racial Basis of European History
0:00
-0:00
1x
Queue
Home
Swipe
Library
Get App
Try Full Access for 3 Days
Listen, bookmark, and more
Compare Features Free Pro
📖 Read Summaries
Read unlimited summaries. Free users get 3 per month
🎧 Listen to Summaries
Listen to unlimited summaries in 40 languages
❤️ Unlimited Bookmarks
Free users are limited to 4
📜 Unlimited History
Free users are limited to 4
📥 Unlimited Downloads
Free users are limited to 1
Risk-Free Timeline
Today: Get Instant Access
Listen to full summaries of 26,000+ books. That's 12,000+ hours of audio!
Day 2: Trial Reminder
We'll send you a notification that your trial is ending soon.
Day 3: Your subscription begins
You'll be charged on Jul 6,
cancel anytime before.
Consume 2.8× More Books
2.8× more books Listening Reading
Our users love us
600,000+ readers
Trustpilot Rating
TrustPilot
4.6 Excellent
This site is a total game-changer. I've been flying through book summaries like never before. Highly, highly recommend.
— Dave G
Worth my money and time, and really well made. I've never seen this quality of summaries on other websites. Very helpful!
— Em
Highly recommended!! Fantastic service. Perfect for those that want a little more than a teaser but not all the intricate details of a full audio book.
— Greg M
Save 62%
Yearly
$119.88 $44.99/year/yr
$3.75/mo
Monthly
$9.99/mo
Start a 3-Day Free Trial
3 days free, then $44.99/year. Cancel anytime.
Unlock a world of fiction & nonfiction books
26,000+ books for the price of 2 books
Read any book in 10 minutes
Discover new books like Tinder
Request any book if it's not summarized
Read more books than anyone you know
#1 app for book lovers
Lifelike & immersive summaries
30-day money-back guarantee
Download summaries in EPUBs or PDFs
Cancel anytime in a few clicks
Scanner
Find a barcode to scan

We have a special gift for you
Open
38% OFF
DISCOUNT FOR YOU
$79.99
$49.99/year
only $4.16 per month
Continue
2 taps to start, super easy to cancel
Settings
General
Widget
Loading...
We have a special gift for you
Open
38% OFF
DISCOUNT FOR YOU
$79.99
$49.99/year
only $4.16 per month
Continue
2 taps to start, super easy to cancel