Youdon’tknowangular@joshj
You.
Don’t.
Know.
Angular.
Youdon’tknowangular@joshj
#01
Mobile Architect //
Transamerica
Mobile Architect,
Entrepreneur, FPV
Pilot & Whiskey Fan.
INTR.
ODU.
CTI.
ON.
Youdon’tknowangular@joshj
You.
Don’t.
Know.
Angular.
Youdon’tknowangular@joshj
Youdon’tknowangular@joshj
Money comes raining
down and life is as it
should be…
Youdon’tknowangular@joshj
Usually it’s this…
Youdon’tknowangular@joshj
Youdon’tknowangular@joshj
Architecture.
“…in the end, architecture boils down to
whatever the important stuff is.”
- Martin Fowler
Youdon’tknowangular@joshj
Architecture.
“the decisions that are hard to change”
Youdon’tknowangular@joshj
Architecture.
• Code Craftsmanship
• Flow Strategies
• I/O Strategies
• Readability
Youdon’tknowangular@joshj
Think Like an
Architect.
Youdon’tknowangular@joshj
Youdon’tknowangular@joshj
Craftsmanship
Code
Youdon’tknowangular@joshj
Code.
Crafts.
man.
ship.
Find ways to love the code you
are working on.
Youdon’tknowangular@joshj
Build a working document your
team can get behind.
Code.
Crafts.
man.
ship.
Youdon’tknowangular@joshj
If you have a team: Have
training / idea sharing times.
(If not, take a class)
Code.
Crafts.
man.
ship.
Youdon’tknowangular@joshj
Be a Zen Master Architect.
Code.
Crafts.
man.
ship.
Youdon’tknowangular@joshj
FlowStrategies
#03
Youdon’tknowangular@joshj
Nomenclature
Almost anything can be a service. A service is typically a class with a narrow,
well-defined purpose. It should do something specific and do it well.
Service
The component or set of methods that will be using our service.
Consumer
Youdon’tknowangular@joshj
Bicycle Wheel
Flow.
stra.
teg.
ies.
Youdon’tknowangular@joshj
Bicycle Wheel
Service
Flow.
stra.
teg.
ies.
Youdon’tknowangular@joshj
Bicycle Wheel
Service
Consumers
Flow.
stra.
teg.
ies.
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
export	class	Logger	{	
		log(msg:	any)			{	console.log(msg);	}	
		error(msg:	any)	{	console.error(msg);	}	
		warn(msg:	any)		{	console.warn(msg);	}	
}Service
Consumer
export	class	HeroService	{	
		private	heroes:	Hero[]	=	[];	
		constructor(	
				private	backend:	BackendService,	
				private	logger:	Logger	
		)	{	}	
		getHeroes()	{	
				this.backend.getAll(Hero).then(	(heroes:	Hero[])	=>	{	
						this.logger.log(`Fetched	${heroes.length}	heroes.`);	
						this.heroes.push(...heroes);	//	fill	cache	
				});	
				return	this.heroes;	
		}	
}
Youdon’tknowangular@joshj
Bicycle Wheel
Service
Consumers
Flow.
stra.
teg.
ies.
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Bicycle Wheel
Service
Consumers
Consumers
Consumers
Consumers
Consumers
Youdon’tknowangular@joshj
Bicycle Wheel
Flow.
stra.
teg.
ies.
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
import	{	NgModule	}						from	'@angular/core';	
import	{	BrowserModule	}	from	'@angular/platform-browser';	
@NgModule({	
		imports:						[	BrowserModule	],	
		providers:				[	Logger	],	
		declarations:	[	AppComponent	],	
		exports:						[	AppComponent	],	
		bootstrap:				[	AppComponent	]	
})	
export	class	AppModule	{	}
Service
Youdon’tknowangular@joshj
Bicycle Wheel
Flow.
stra.
teg.
ies.
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Bicycle Wheel
Youdon’tknowangular@joshj
Waterfall
Flow.
stra.
teg.
ies.
Youdon’tknowangular@joshj
Waterfall
ServiceFlow.
stra.
teg.
ies.
Youdon’tknowangular@joshj
Service NavControllerFlow.
stra.
teg.
ies.
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Youdon’tknowangular@joshj
Don’t Use Events(Unless you absolutely have to…)
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Waterfall
Service NavController
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Waterfall
Service
Consumer
NavController
PageComponent
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Waterfall
Service
Consumer
Consumer Child
NavController
PageComponent
ButtonComponent
Youdon’tknowangular@joshj
@Injectable()	
export	class	NavigationService	{	
		public	navigate()	{	
				//	Do	something	
		}	
}
Service
Youdon’tknowangular@joshj
@Injectable()	
export	class	NavigationService	{	
		public	navigate()	{	
				//	Do	something	
		}	
}
export	class	MyPageComponent		{	
		constructor	(	
				private	navigationService:	NavigationService	
		)	{}	
}
<nav-button	[navigationService]="navigationService">
Service
Consumer
Youdon’tknowangular@joshj
@Injectable()	
export	class	NavigationService	{	
		public	navigate()	{	
				//	Do	something	
		}	
}
export	class	MyPageComponent		{	
		constructor	(	
				private	navigationService:	NavigationService	
		)	{}	
}
export	class	NavButtonComponent		{	
		@Input()	navigationService:	NavigationService;	
		onButtonClick()	{	
				this.navigationService.navigate();	
	}	
}
<nav-button	[navigationService]="navigationService">
Service
Consumer
Consumer Child
Youdon’tknowangular@joshj
import	{	NavigationService	}	from	'./shared/navigation.service';	
@Component({	
		selector:	'nav-button',	
		template:	`<button	(click)="navigationService.navigate()">Navigate</button>`	
})	
export	class	NavButtonComponent		{	
		@Input()	navigationService:	NavigationService;	
}
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Waterfall
Service
Consumer
Consumer Child
NavController
PageComponent
ButtonComponent
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
The Molecule
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
https://angular-realworld.stackblitz.io
Modular
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
https://angular.io/guide/ngmodule
NgModules
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Functional
Blocks
Shared
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Shared
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies. export	*	from	'./article-helpers';	
export	*	from	'./buttons';	
export	*	from	'./layout';	
export	*	from	'./list-errors.component';	
export	*	from	'./models';	
export	*	from	'./services';	
export	*	from	'./shared.module';	
export	*	from	'./show-authed.directive';
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
import	{	ArticleListComponent	}	from	'../shared';
import	{	ArticleListComponent	}	from	'../shared/article-
helpers/article-list.component';
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Module
Folder
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
• Organized
• Easy to reference
• Self contained
• Safer for teams
Benefits
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Module
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
NgAppModule
import	{	NgModule	}	from	'@angular/core';	
import	{	BrowserModule	}	from	'@angular/platform-browser';	
import	{	FormsModule	}	from	'@angular/forms';	
import	{	AppComponent	}	from	'./app.component';	
import	{	HelloComponent	}	from	'./hello.component';	
import	{	NavButtonComponent	}	from	'./nav-
button.component';	
@NgModule({	
		imports:						[	BrowserModule,	FormsModule	],	
		declarations:	[	AppComponent,	HelloComponent,	
NavButtonComponent],	
		bootstrap:				[	AppComponent	]	
})	
export	class	AppModule	{	}
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies. Imports
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Imports
@NgModule({	
		imports:						[	BrowserModule,	FormsModule	],	
		declarations:	[	AppComponent,	HelloComponent,	
NavButtonComponent],	
		bootstrap:				[	AppComponent	]	
})	
export	class	AppModule	{	}
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
Imports
import	{	ArticleModule	}	from	'./article/article.module';	
@NgModule({	
		declarations:	[],					
		imports:	[	
				ArticleModule,	
		],	
		providers:	[],	
		bootstrap:	[AppComponent]	
})	
export	class	AppModule	{	}
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
import	{	ModuleWithProviders,	NgModule	}	from	'@angular/
core';	
import	{	RouterModule	}	from	'@angular/router';	
import	{	ArticleComponent	}	from	'./article.component';	
import	{	ArticleCommentComponent	}	from	'./article-
comment.component';	
import	{	ArticleResolver	}	from	'./article-
resolver.service';	
import	{	MarkdownPipe	}	from	'./markdown.pipe';	
import	{	SharedModule	}	from	'../shared';
article.module.ts
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
const	articleRouting:	ModuleWithProviders	=	
RouterModule.forChild([	
		{	
				path:	'article/:slug',	
				component:	ArticleComponent,	
				resolve:	{	
						article:	ArticleResolver	
				}	
		}	
]);
article.module.ts
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
@NgModule({	
		imports:	[	
				articleRouting,	
				SharedModule	
		],	
		declarations:	[	
				ArticleComponent,	
				ArticleCommentComponent,	
				MarkdownPipe	
		],	
		providers:	[	
				ArticleResolver	
		]	
})	
export	class	ArticleModule	{}	
article.module.ts
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
https://angular.io/guide/ngmodule
NgModules
Youdon’tknowangular@joshj
Flow.
stra.
teg.
ies.
https://angular-realworld.stackblitz.io
Molecule
Youdon’tknowangular@joshj
I/O Stratagies.
Youdon’tknowangular@joshj
#01
Whenever data
enters or leaves the
application have a
strategy for hiding
the source or the
target from the
application as a
whole.
I/O
Stratagies.
Youdon’tknowangular@joshj
I/O Stratagies.
Youdon’tknowangular@joshj
I/O Stratagies.
Components
Services
Adapters
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Article Component http()
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Article Component
Article Service http()
getArticles()
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Article Component
API Service http()
getArticles()
this.apiService.get()Article Service
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Article Component
ApiService
apiHttpStrategy
getArticles()
this.apiService.get()Article Service
apiFileStrategy
Youdon’tknowangular@joshj
@NgModule({	
		declarations:	[	
		],	
		imports:	[	
		],	
		providers:	[	
				{	
						provide:	ApiService,	
						useFactory:	(http:	Http,	jwtService:	JwtService)	=>	{	
								if	(environment.production)	{	
										return	new	ApiService(http,	jwtService);	
								}	else	{	
										return	new	MockApiService(http,	jwtService);	
								}	
						},	
						deps:	[Http,	JwtService]	
				}	
		],	
		bootstrap:	[AppComponent]	
});	
I/O.
stra.
teg.
ies.
Youdon’tknowangular@joshj
I/O Stratagies.
Components
Services
Adapters
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Article Component http()
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Article Component
Analytics Service http()
event()
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Article Component
Analytics Service event()
this.analytics.event()
Google Strategy http()
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Article Component
Analytics Service
Crashlytics Firebase
event()
this.analytics.event()
Youdon’tknowangular@joshj
export	class	AnalyticsService	{	
		private	strategies:	Array<any>	
		constructor(	
				private	crashlyticsAnalytics:	CrashlyticsAnalyticsService,	
				private	firebaseAnalyticsService:	FirebaseAnalyticsService,	
				private	googleAnalyticsService:	GoogleAnalyticsService	
		)	{	
				this.strategies	=	[	
						crashlyticsAnalytics,	
						firebaseAnalyticsService,	
						googleAnalyticsService	
				]	
		};	
		public	event()	{	
				for	(let	strategy	of	this.strategies)	{	
						strategy.event();	
				}	
		};	
}
Youdon’tknowangular@joshj
I/O Stratagies.
Youdon’tknowangular@joshj
Readability
Youdon’tknowangular@joshj
“Any fool can write code that a
computer can understand. Good
programmers write code that humans
can understand.”
Martin Fowler
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
The rule of
“huh”
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
L.I.F.T
• Locate
• Identify
• Flat
• Try to be DRY
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Import line spacing
import	{	Injectable	}	from	'@angular/core';	
import	{	Http	}							from	'@angular/http';	
import	{	Hero	}	from	'./hero.model';	
import	{	ExceptionService}	from	'../../core';
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Component
Selector
Names
selector:	'toh-hero-button',
<toh-hero-button></toh-hero-button>
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Don’t Abbreviate your
constructor arguments or
instantiated classes.
constructor(	
				private	navigationService:	NavigationService,	
				private	myElementReference:	MyElementReference	
)	{	
				this.fooAwesome	=	new	FooAwesome();	
};
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
constructor(	
				private	navServ:	NavigationService,	
				private	el:	MyElementReference	
)	{	
				this.foo	=	new	FooAwesome();	
};	
No…
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Small Functions
		private	specificTask()	{	
				var	doSomethingWell	=	true;	
				var	doSomethingSpecific	=	true;	
				return	(doSomethingWell	&&	doSomethingSpecific);	
		}
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Use a Code Tool
Youdon’tknowangular@joshj
I/O.
stra.
teg.
ies.
Use Semicolons;
seriously.
Youdon’tknowangular@joshj
Think Like an
Architect.
Youdon’tknowangular@joshj
END.
@joshj //
joshjensen.com

ConnectTech2017 - You don't know Angular