惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
S
Schneier on Security
The Hacker News
The Hacker News
P
Proofpoint News Feed
Spread Privacy
Spread Privacy
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
I
Intezer
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Schneier on Security
Schneier on Security
Security Latest
Security Latest
AWS News Blog
AWS News Blog
B
Blog RSS Feed
Microsoft Security Blog
Microsoft Security Blog
有赞技术团队
有赞技术团队
博客园 - 叶小钗
The Last Watchdog
The Last Watchdog
O
OpenAI News
月光博客
月光博客
Hacker News: Ask HN
Hacker News: Ask HN
阮一峰的网络日志
阮一峰的网络日志
S
Security @ Cisco Blogs
Google Online Security Blog
Google Online Security Blog
云风的 BLOG
云风的 BLOG
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Latest news
Latest news
P
Palo Alto Networks Blog
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
Google DeepMind News
Google DeepMind News
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
Apple Machine Learning Research
Apple Machine Learning Research
U
Unit 42
PCI Perspectives
PCI Perspectives
博客园 - 聂微东
SecWiki News
SecWiki News
宝玉的分享
宝玉的分享
Forbes - Security
Forbes - Security
H
Heimdal Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Hugging Face - Blog
Hugging Face - Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
Troy Hunt's Blog
博客园 - 三生石上(FineUI控件)
Application and Cybersecurity Blog
Application and Cybersecurity Blog
罗磊的独立博客
WordPress大学
WordPress大学
D
Darknet – Hacking Tools, Hacker News & Cyber Security

Minko Gechev's blog

skillgrade Unit Tests for AI Agent Skills You Should Care About AI Generative Development LLM-first Web Framework Reactive framework in ~200 lines of JavaScript Managing Angular Are LLMs going to replace us? Prefetching Heuristics Design Patterns in Open Source Projects - Part I What I learned doing 125 public talks - Part I Dynamic imports solve all the problems, right? 5 Angular CLI Features You Didn't Know About Angular quicklink Preloading Strategy Introducing Bazel Schematics for Angular CLI Building TypeScript Projects with Bazel Joining Google Playing Mortal Kombat with TensorFlow.js. Transfer learning and data augmentation Fast, extensible, configurable, and beautiful linter for Go Introducing Guess.js - a toolkit for enabling data-driven user-experiences on the Web Machine Learning-Driven Bundling. The Future of JavaScript Tooling. JavaScript Decorators for Declarative and Readable Code 3 Tricks For Using Redux and Immutable.js with TypeScript Follow Your Dream Career with Open Source. Personal Story. Redux Anti-Patterns - Part 1. State Management. Faster Angular Applications - Understanding Differs. Developing a Custom IterableDiffer Faster Angular Applications - Part 2. Pure Pipes, Pure Functions and Memoization Faster Angular Applications - Part 1. On Push Change Detection and Immutability Understanding Dynamic Scoping and TemplateRef Implementing a Simple Compiler on 25 Lines of JavaScript Developing Statically Typed Programming Language WebVR for a Gamified IDE 7 Angular Tools That You Should Consider Announcing ngrev - Reverse Engineering Tool for Angular Implementing Angular's Dependency Injection in React. Understanding Element Injectors. Distributing an Angular Library - The Brief Guide Angular in Production Ahead-of-Time Compilation in Angular 2.5X Smaller Angular 2 Applications with Google Closure Compiler Using Stripe with Angular (Deprecated) Building an Angular Application for Production Implementing the Missing "resolve" Feature of the Angular 2 Router Scalable Single-Page Application Architecture Managing ambient type definitions and dealing with the "Duplicate identifier" TypeScript error Static Code Analysis of Angular 2 and TypeScript Projects Enforcing Best Practices with Static Code Analysis of Angular 2 Projects ViewChildren and ContentChildren in Angular Dynamically Configuring the Angular's Router Angular 2 Hot Loader Lazy Loading of Route Components in Angular 2 Aspect-Oriented Programming in JavaScript Flux in Depth. Store and Network Communication. Using JSX with TypeScript Flux in Depth. Overview and Components. Even Faster AngularJS Data Structures Boost the Performance of an AngularJS Application Using Immutable Data - Part 2 Angular2 - First Impressions Build Your own Simplified AngularJS in 200 Lines of JavaScript Persistent State of ReactJS Component Boost the Performance of an AngularJS Application Using Immutable Data Processing Binary Protocols with Client-Side JavaScript Stream your Desktop to HTML5 Video Element Multi-User Video Conference with WebRTC Asynchronous calls with ES6 generators Binary Tree iterator with ES6 generators WebRTC chat with React.js AngularJS in Patterns (Part 3) AngularJS in Patterns (Part 2). Services. Using GitHub Pages with Jekyll! AngularJS in Patterns (Part 1). Overview of AngularJS Singleton in JavaScript Express over HTTPS What I get from the JavaScript MV* frameworks Remote Desktop Client with AngularJS and Yeoman The magic of $resource (or simply a client-side Active Record) AngularJS Inheritance Patterns AngularAOP v0.1.0 Advanced JavaScript at Sofia University AngularJS style guide Lazy prefetching of AngularJS partials VNC client on 200 lines of JavaScript Aspect-Oriented Programming with AngularJS CSS3 flipping effect Practical programming with JavaScript Why I should use publish/subscribe in JavaScript JavaScript, the weird parts Functional programming with JavaScript plainvm Looking for performance? Probably you should NOT use [].sort (V8) JavaScript image scaling ELang Caching CSS with localStorage Self-invoking functions in JavaScript (or Immediately Invoked Function Expressions) Asus N56VZ + Ubuntu 12.04 (en) Asus N56VZ + Ubuntu 12.04 Debian Squeeze + LXDE on Google Nexus S (or having some fun while suffering) HTML5 image editor Курсови проекти – ФМИ Carousel Gallery SofiaJS...
Design Patterns in Open Source Projects - Part II
2021-01-24 · via Minko Gechev's blog

This blog post introduces another design pattern into the context of ngrev. If you’re not yet familiar with the project, I’d strongly recommend taking 2 minutes to the introduction and “Project Overview” sections in the first part of the series.

If you did not take the time, ngrev is an Electron app that visualizes the structure of an Angular app, showing the relationships between components, modules, and providers. The UI retrieves the data for each view using an instance of a state object. You can read more about the state pattern and its application in ngrev here.

ngrev is an Angular app developed with TypeScript. At the same time, however, the post is conceptual, so even if you’re not familiar with Angular, TypeScript, or Web development, you should be able to extract value.

Composite Pattern

In software engineering, the composite pattern is a structural design pattern. The composite pattern describes a group of objects treated the same way as a single instance of the same type of object. A composite intends to “compose” objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.

The composite pattern is arguably one of the most popular design patterns. You find its applications all over software engineering and computer science. For example, in file systems the leaves are the individual files and the composites are directories because they can contain other directories and files. In compiler design we can find the leaves being terminals and the composites being non-terminal AST nodes.

In the case of ngrev, both the composites and the leaves are instances of the state classes. The way we use the composite pattern here is attractive in at least two ways - the fact that we’re using the pattern itself and the mechanism it interacts with the state design pattern.

To understand why the composite design pattern helps us in ngrev, let us look at two of the views in the application:

Module Dependencies

Each NgModule in Angular can depend on 0 or more other modules. This view shows the dependencies of the AnnounceBarModule. ngrev implements this functionality with the ModuleTreeState class.

Module Declarations

Additionally, each module could have many declarations; for example, the SharedModule from the second image declares and exports SearchResultComponent and SelectComponent. In ngrev, we implement this functionality with the ModuleState class.

Now let us look at the default view of ngrev:

App

This view shows a visualization of the dependencies between all the modules in our app and the declarations/exports for each one of them. Internally, ngrev implements it with the AppState class.

Even for a small apps like angular.io this could get quite messy; that’s why we have the more specific views from above. But also notice that there’s an overlap between the 3 visualizations - the application view is a composition of the views showing module dependencies and module declarations.

What do I mean by composition? If we suppose that ModuleState and ModuleTreeState return sets of nodes and edges, their union will be a subset of the nodes and edges AppState returns.

Having noticed this relation, we can express it with code in the following way:

export class AppState extends State {
  private states = [
    ...this.createModuleStates(),
    ...this.createModuleTreeStates()
  ];

  //...

  getData(): VisualizationConfig<any> {
    const data: VisualizationConfig<any> = {
      graph: {
        nodes: new Set(),
        edges: new Set()
      }
    };
    this.states.forEach((state: State) => {
      const { graph } = state.getData();
      graph.nodes.forEach((node: Node<any>) => data.graph.nodes.add(node));
      graph.edges.forEach((edge: Edge) => data.graph.edges.add(edge));
    });
    return data;
  }
}

In the snippet above, we first create the collection of states. createModuleStates and createModuleTreeStates instantiate state objects for each of the application modules. I haven’t showed their implementation for simplicity.

After that, when the UI process requests the data for visualizing the application view, the background process will indirectly invoke appState.getData(). The method will invoke getData for each of the nested states in states and add the corresponding nodes and edges to the result sets.

That’s it! This is entirely how the composite pattern implementation in ngrev works.

Use Cases

The gang of four book explains MVC as the interaction between the patterns Strategy, Observer, and Composite. MVC uses composite for the user interface.

Applications developed with modern Web frameworks and libraries such as Angular and React are expressed as compositions of components. In Angular, you could often think of directives and components with bare HTML nodes as “leaf” classes and components using directives or other components as “composite” classes.

The composite design pattern is also heavily used in compilers - especially during interpretation and source code generation. Each AST node is either a terminal (leaf) or a non-terminal (composite).

I’m spending most of my days thinking about developer tooling and frameworks, so that’s why my examples probably look a bit niche. If you’ve recently used the composite design pattern in other contexts, please leave a comment below.

What’s Next?

It’s great you decided to read this article, but this is just part of the story. To get a better idea of how the composite pattern works, I’d encourage you to read the source code implementing it.

I hope you enjoyed this article! Until next time and happy coding!