Upload
estella-bennett
View
218
Download
2
Tags:
Embed Size (px)
Citation preview
Erich GammaDistinguished EngineerVSPlatform Tools/Monaco
Surviving Application Scale JavaScript - TypeScript in the Trenches
3-583
Web based development tools, platform, and cloud services
What do we do?
Team Foundation Server
IE F12 Source Code Viewer
TypeScript Playground
WinJS Playground
OneDrive
Visual Studio Online Monaco
The Road to Monaco
Small 50 kLOC
ModulesClasses
Promises
10% Typescript
Medium100 kLOC
“AMD”Lazy Loaded Contributions
50% Typescript
Larger200 kLOC
ComponentsAPI
Dependency Injection
100% Typescript
patterns
TypeScript
2011
2013
2012
size
We enjoy programming in JavaScript, but…
Organizing a large and growing code base Need to come up with “compensating” patterns for classes and
modules/namespaces
Refactoring JavaScript code is difficult “JavaScript code ‘rots’ over time” “Writing JavaScript code in a large project is like carving code in stone”
Describing APIs Keep the description in synch with the implementation
Concerns with JavaScript
Optional and structural typing Fewer type annotations are necessary than you think
Classes, modules Formalization of common JavaScript patterns
Interfaces Interfaces named object types for describing the shape of JavaScript
objects
TypeScript to the Rescue…
TypeScript at Work: Interfaces
interface IModelChangeAccessor {insertText(position:IPosition, text:string): IEditorPosition;deleteText(range:IRange): IDeleteTextResult;
}
interface IEditableTextModel {change(callback:
(changeAccessor:IModelChangeAccessor)=>any): …}
Interfaces to be implemented
TypeScript at Work: Interfaces
export interface IValidationFilter {(resource:IEventEmitter): boolean;
}
public constructor(filter:IValidationFilter) {}
new Validator((resource)=>this.includeModel(resource));
Callbacks
TypeScript at Work: Interfaces
interface ICommonEditorOptions {selectOnLineNumbers?:boolean;glyphMargin?:boolean;roundedSelection?:boolean;theme?:string;readOnly?:boolean;//…
}
Option bags
TypeScript at Work: Interfaces
var options:IBuildData = JSON.parse(req.responseText);
export interface IBuildData {requestId:string;logOutput?:string;buildOutput?:BuildOutput;killOutput?:KillOutput;
}
JSON structures
TypeScript at Work: Interfaces
declare module WinJS { module Binding {
//... } } class Promise<T> { //... }}
External types from other libraries
Promises Pattern
promise.then(onFulfilled, onRejected);An object representing a value which may not yet have been computed onFulFilled
called after a promise is fulfilled, with the promise’s value as its first argument
onRejected called after a promise is rejected, with the promise’s reason as its first argument
http://promises-aplus.github.io/promises-spec/https://github.com/promises-aplus/promises-spec/blob/master/implementations.md
promise.then((result) => {...}, (err) => {...});
class Promise<T> { then<U>(success?: (value: T) => Promise<U>, error?: (error: any) => Promise<U>, progress?: (progress: any) => void): Promise<U>; //…}
export interface ITypeDeclarationSupport { findTypeDeclaration(position:Editor.IPosition):Promise<IReference>;}
TypeScript at Work: Generics
https://github.com/borisyankov/DefinitelyTyped
TypeScript Type Definitions
TSD: a package manager to search and install TypeScript definition files directly from the DefinitelyTyped repository.
TypeScript at Work: Modules
We started with internal modules
The Road to Monaco
Small 50 kLOC
ModulesClasses
InterfacesPromises
10% Typescript
Medium100 kLOC
“AMD”Lazy Loaded Contributions
50% Typescript
Larger200 kLOC
ComponentsAPI
Dependency Injection
100% Typescript
patterns
TypeScript
2011
2013
2012
size
Modules are open undisciplined name space contributions…
You can have cyclic dependencies without noticing…
Name spaces have no relationship to the code organization on disk Renaming files/name spaces is no fun…
Code organization started to rot
Code Organization Pains
Growing Pains: Order Matters…
Growing Pains: Dependencies…
“… our dependency graph was such a mess that each area had a dependency on just about every other area.”
Growing Pains: Eager loading
Separately loaded code referenced using external module names
Implemented in separate source files Entities are private unless exported
TypeScript: External Modules
File main.ts:import adder= require("./adder"); adder.add(3,4);
File adder.ts: export function add(op1: number, op2: number):number {
return op1+op2;}
CommonJS used by node.js
Asynchronous Module Definition (AMD) requires an AMD compliant module loader, e.g. requireJS
TypeScript: Module Patterns
define(‘main’, [‘adder'], function(adder) { // code goes here adder.add()});
var adder = require(“adder”);adder.add()
tsc --module amd main.ts
tsc --module commonjs main.ts
AMD in TypeScript vs. JavaScript
AMD in JavaScript
define([‘…./winjs.base‘, ‘…./zoneWidget’], function(WinJS, ZoneWidget) { … });
AMD in TypeScriptimport WinJS= require('vs/base/lib/winjs');import ZoneWidget = require('vs/editor/zoneWidget');
Server uses node.js Migrated server to TypeScript once a node.d.ts file became available
Client migrated to AMD and converted to TypeScript
Common module syntax enables code sharing between client and server
Monaco
“It feels like fresh showered. Self contained modules, no more cycles, no more globals, clean file system structure”
After the AMD Migration Impressions
AMD Applied – Lazy Loadingcsharp.ts
export class CSMode extends AbstractMode { constructor() { super('vs.languages.csharp'); } // lots of code …. }
csharp.contribution.ts
modeRegistry.registerMode( [‘text/x-csharp'], new Platform.Descriptor( 'vs/languages/csharp/csharp', ‘CSMode'));
Registered on start-up Loaded on demand
Pain: “global” CSS files Want to package CSS files with the JS files into modules Want to express CSS file dependencies in code
AMD loader plugins Required module path can refer to a plugin “plugin!/” We implemented a css loader plugin, that allows to define:
define(["require", "vs/css!./actionbar", ...], …) CSS dependencies expressed in a pragma
AMD Applied – CSS Dependencies
The Road to Monaco
Small 50 kLOC
ModulesClasses
InterfacesPromises
10% Typescript
Medium100 kLOC
“AMD”Lazy Loaded Contributions
50% Typescript
Larger200 kLOC
ComponentsAPI
Dependency Injection
100% Typescript
patterns
TypeScript
2011
2013
2012
size
Migration is code clean-up but real work… Velocity around 300 LOCs per hour No implicit ‘anys’ No missing return types
Towards 100% TypeScript
“As I did conversions, I began typing various object literals I was passing around as interfaces. Soon enough, I realized how inconsistent I was, the same data was flowing around in at least 3 different formats. This is because of the easiness through which you can create literals in JavaScript …. Need some placeholder for data?... Just create a new literal object.”
Reuse TypeScript code as ‘binary’ JS components with a declarations file
Example using TypeScript language services as a component Compiler and language services > 30kLOC of TypeScript
Generates a typescriptservices.d.ts
Componentization
tsc –declarations –out typescriptservices.js typescript.ts
We were on the bleeding edge… …but we expected it and had plenty of band aid
We would do it again, the benefits outweigh the pains Confidence, refactoring agility, tooling, fun
We would start with TypeScript (and CommonJS/AMD) from the beginning
TS Retrospective
Friday 2:00-3:00pm Building Websites using VSOnline Monaco Chris Dias
Related Talks
TypeScript www.typescriptlang.org
AMD http://requirejs.org/docs/whyamd.html
TFS use of TypeScript http://
blogs.msdn.com/b/bharry/archive/2012/10/24/typescript-a-real-world-story-of-adoption-in-tfs.aspx
Monaco VS Online Get started with the Monaco Channel9 Series Keep informed on the Monaco Blog
Resources
for MSDN Ultimate subscribers
Go to http://msdn.Microsoft.com/specialoffers
SPECIAL OFFERSPartner Program
Your Feedback is Important
Fill out an evaluation of this session and help shape future events.
Scan the QR code to evaluate this session on your mobile device.
You’ll also be entered into a daily prize drawing!
© 2014 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.