Sencha Class System, Jacky Nguyen

  • 5,160 views
Uploaded on

Ext JS 4.x and Sencha Touch 2.0 went through a huge refactoring from the ground up with the new class system. It combines the familiar class-based programming style with the dynamic nature of …

Ext JS 4.x and Sencha Touch 2.0 went through a huge refactoring from the ground up with the new class system. It combines the familiar class-based programming style with the dynamic nature of JavaScript into a robust architecture which stands behind every single class written in the frameworks. This session will give you a complete picture of everything our new foundation has to offer as well as their benefits and best practices.

Jacky Nguyen is one of the core engineers behind Sencha frameworks. With his well-rounded knowledge and experiences on both server-side and client-side development as well as industry best practices, he is responsible for designing and improving Sencha frameworks’ overall architectures. He was the author of MooTouch, which has become a part of Sencha Labs. Jacky is passionate about bringing innovation to software development and developers.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
  • Thanks .. I've learned a bit Sencha since.
    Are you sure you want to
    Your message goes here
  • @tohagan applyFoo(newValue, oldValue) is correct, because we can use the following: applyAge: function(newAge, oldAge)...console.log(newAge + ' is a invalid age, must be a positive number. The current age is ' + oldAge);
    Are you sure you want to
    Your message goes here
  • Slide 33 shows
    processedValue = applyFoo(newValue, oldValue)

    but I think this should be

    processedValue = applyFoo(newValue)
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
5,160
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
211
Comments
3
Likes
12

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Wednesday, November 2, 11
  • 2. The Sencha Class System Jacky Nguyen, Sencha jacky@sencha.com @nktproWednesday, November 2, 11
  • 3. Best User ExperienceWednesday, November 2, 11
  • 4. Better Developer ExperienceWednesday, November 2, 11
  • 5. Class System Event System Data Package Widgets & Layouts ...Wednesday, November 2, 11
  • 6. Prototype-based Class-based = Predictability Sencha Class System Flexibility Programmer FamiliarityWednesday, November 2, 11
  • 7. ✓Consistent ✓Familiar Learn ✓DRY ✓Debuggable Develop ✓Testable ✓Automatic dependency resolution Deploy Better Developer ExperienceWednesday, November 2, 11
  • 8. Coding ConventionWednesday, November 2, 11
  • 9. Namespacing & Code Organization 1. OrganizationName.group[.subgroup].ClassName 2. One class per file 3. File name matches class name ‣ Ext.chart.Label -> Ext/chart/Label.js ‣ Ext.data.writer.Xml -> Ext/data/writer/Xml.js ‣ MyApp.field.Password -> MyApp/field/Password.jsWednesday, November 2, 11
  • 10. Class DefinitionWednesday, November 2, 11
  • 11. The Good Old Ext.extend() Ext.ns(My.sample); My.sample.Person = Ext.extend(Object, { constructor: function(name) { this.name = name; }, walk: function(steps) { alert(this.name + is walking + steps + steps); } });Wednesday, November 2, 11
  • 12. Introducing Ext.define() Ext.define(My.sample.Person, { constructor: function(name) { this.name = name; }, walk: function(steps) { alert(this.name + is walking + steps + steps); } }); var tommy = new My.sample.Developer(Tommy); tommy.walk(5); // alerts Tommy is walking 5 stepsWednesday, November 2, 11
  • 13. Ext.define() vs Ext.extend() Ext.define(My.sample.Person, { constructor: function(name) { this.name = name; }, walk: function(steps) { alert(this.name + is walking + steps + steps); } }); ‣Class definition is more than just inheritance ‣Automatic namespace allocation ‣Classes are now aware of their own names ‣Asynchronous vs. synchronousWednesday, November 2, 11
  • 14. InheritanceWednesday, November 2, 11
  • 15. Inheritance Ext.define(My.sample.Person, { constructor: function(name) { this.name = name; }, walk: function(steps) { alert(this.name + is walking + steps + steps); } }); Ext.define(My.sample.Developer, { extend: My.sample.Person, code: function(language) { alert(this.name + is coding in + language); } }); var tommy = new My.sample.Developer(Tommy); tommy.walk(5); // Tommy is walking 5 steps tommy.code(JavaScript); // Tommy is coding in JavaScriptWednesday, November 2, 11
  • 16. Inheritance Ext.define(My.sample.Developer, { extend: My.sample.Person, code: function(language) { /* ... */ }, walk: function(steps) { if (steps > 100) { alert(Are you serious? Thats too far! Im lazy...); } else { My.sample.Developer.superclass.walk.apply(this, arguments); this.callParent(arguments); } } }); var tommy = new My.sample.Developer(Tommy); tommy.walk(50); // alerts "Tommy is walking 50 steps" tommy.walk(101); // alerts "Are you serious? Thats too far! Im lazy..."Wednesday, November 2, 11
  • 17. MixinsWednesday, November 2, 11
  • 18. Mixins Sing Performer Play Instruments Composer Compose Songs Singer-songwriterWednesday, November 2, 11
  • 19. Mixins Ext.define(My.ability.Sing, { sing: function(songName) { alert("Im singing " + songName); } }); Ext.define(My.ability.PlayInstruments, { play: function(instrument) { alert("Im playing " + instrument); } }); Ext.define(My.ability.ComposeSongs, { compose: function(songName) { alert("Im composing " + songName); } });Wednesday, November 2, 11
  • 20. Mixins Ext.define(My.sample.Performer, { extend: My.sample.Person, mixins: { canSing: My.ability.Sing, canPlay: My.ability.PlayInstruments } }); Ext.define(My.sample.Composer, { extend: My.sample.Person, mixins: { canPlay : My.ability.PlayInstruments, canCompose: My.ability.ComposeSongs } }); Ext.define(My.sample.SingerSongwriter, { extend: My.sample.Person, mixins: { canSing : My.ability.Sing, canPlay : My.ability.PlayInstruments, canCompose: My.ability.ComposeSongs } });Wednesday, November 2, 11
  • 21. Mixins Ext.define(My.sample.Performer, { extend: My.sample.Person, mixins: { prototype of canSing: My.ability.Sing, canPlay: My.ability.PlayInstruments }, sing: function() { alert("Here we go!"); this.mixins.canSing.sing.call(this); alert("Im done singing!"); } }); var jamie = new My.sample.Performer("Jamie"); jamie.sing("November Rain"); // alerts "Here we go!" // alerts "Im singing November Rain" // alerts "Im done singing!";Wednesday, November 2, 11
  • 22. Dependency ManagementWednesday, November 2, 11
  • 23. Dependency Management <!-- ... --> <head> <!-- ... --> <script src="ext.js"></script> src="ext-all-debug.js"></script> <script src="My/sample/Person.js"></script> <script src="My/ability/PlayInstruments.js"></script> src="My/sample/Location.js"></script> <script src="My/ability/Sing.js"></script> src="My/sample/Developer.js"></script> <script src="My/sample/Performer.js"></script> <script> var tommy = new My.sample.Developer(Tommy); Tommy); Ext.create(My.sample.Developer, var jamie = new My.sample.Performer(Jamie); Jamie); Ext.create(My.sample.Performer, </script> </head> <!-- ... -->Wednesday, November 2, 11
  • 24. Dependency Management <!-- ... --> <head> <!-- ... --> <script src="ext.js"></script> <script> Ext.require([ My.sample.Developer, My.sample.Performer ]); Ext.onReady(function() { var tommy = new My.sample.Developer(Tommy); var jamie = new My.sample.Performer(Jamie); }); </script> </head> <!-- ... -->Wednesday, November 2, 11
  • 25. ConfigWednesday, November 2, 11
  • 26. Config Ext.define(My.sample.Person, { name: Anonymous, age: 0, gender: Male, constructor: function(config) { config = config || {}; Ext.apply(this, config); } }); var robert = new My.sample.Person({ name: Robert, age: 21 });Wednesday, November 2, 11
  • 27. Config Ext.define(My.sample.Person, { name: Anonymous, age: 0, gender: Male, constructor: function(config) { if (Ext.isObject(config)) { if (config.hasOwnProperty(name)) { this.name = config.name; } if (config.hasOwnProperty(age)) { this.age = config.age; } if (config.hasOwnProperty(gender)) { this.gender = config.gender; } } } });Wednesday, November 2, 11
  • 28. Config Ext.define(My.sample.Person, { name: Anonymous, age: 0, gender: Male, constructor: function(config) { if (Ext.isObject(config)) { if (config.hasOwnProperty(name)) { this.setName(config.name); } if (config.hasOwnProperty(age)) { this.setAge(config.age); } if (config.hasOwnProperty(gender)) { this.setGender(config.gender); } } }, });Wednesday, November 2, 11
  • 29. setName: function(name) { this.name = name; return this; }, getName: function() { return this.name; }, setAge: function(age) { this.age = age; return this; }, getAge: function() { return this.age; }, setGender: function(gender) { this.gender = gender; return this; }, getGender: function() { return this.gender; }Wednesday, November 2, 11
  • 30. Config Ext.define(My.sample.Person, { config: { name: Anonymous, age: 0, gender: Male }, constructor: function(config) { this.initConfig(config); } }); var robert = new My.sample.Person({ name: Robert, age: 21 }); robert.setName(Rob); alert(robert.getAge()); // alerts 21 robert.setAge(22); alert(robert.getAge()); // alerts 22Wednesday, November 2, 11
  • 31. Config: Deep Merging Ext.define(My.sample.Developer, { extend: My.sample.Person, config: { level: Junior, location: { city: Unknown, state: Unknown, country: Unknown } } }); var edward = new My.sample.Developer({ age: 26, level: Senior, location: { city: Palo Alto, state: CA, country: USA } }); edward.setName(Edward); alert(edward.getLocation().city); // alerts Palo AltoWednesday, November 2, 11
  • 32. Config: Setter’s Process ✓Validation ✓Filtering Before ✓Transformation ✓Actual assignment Set ✓Notification ✓Updating dependencies AfterWednesday, November 2, 11
  • 33. Config: Magic Methods getFoo() return this.foo setFoo() Before processedValue = applyFoo(newValue, oldValue) Set this.foo = processedValue After updateFoo(processedValue, oldValue)Wednesday, November 2, 11
  • 34. Config Ext.define(My.sample.Person, { /* ... */ applyAge: function(age) { if (typeof age != number || age < 0) { alert("Invalid age, must be a positive number"); return; } return age; }, updateAge: function(newAge, oldAge) { alert("Age has changed from " + oldAge + " to " + newAge); } }); var aaron = new My.sample.Person({ name: Aaron, age: -100 }); // alerts "Invalid age, must be a positive number" alert(aaron.getAge()); // alerts 0 alert(aaron.setAge(35)); // alerts "Age has changed from 0 to 35" alert(aaron.getAge()); // alerts 35Wednesday, November 2, 11
  • 35. Dependency Injection with Ext.factory()Wednesday, November 2, 11
  • 36. Dependency Injection Ext.define(My.sample.Location, { config: { city: Unknown, state: CA, country: USA } }); var nicolas = new My.sample.Developer({ location: { city: Palo Alto } }); alert(nicolas.getLocation() instanceof My.sample.Location); //alerts true alert(nicolas.getLocation().getCity()); // alerts Palo Alto var nicolas = new My.sample.Developer({ location: new My.sample.Location({ city: Austin, state: TX }) }); alert(nicolas.getLocation().getState()); // alerts TXWednesday, November 2, 11
  • 37. Dependency Injection nicolas.setLocation({ city: Austin }); // nicolas.getLocation().setCity(Austin); nicolas.setLocation(new My.sample.Location({ city: Austin, state: TX })); nicolas.setLocation(new My.sample.DetailedLocation({ longitude: -122.18235, latitude: 37.44923 }));Wednesday, November 2, 11
  • 38. Ext.factory() Ext.define(My.sample.Developer, { extend: My.sample.Person, config: { level: Junior, location: {} }, applyLocation: function(location, currentLocation) { return Ext.factory( location, My.sample.Location, currentLocation ); } }); given value from setLocation() default Class existing instanceWednesday, November 2, 11
  • 39. DebuggingWednesday, November 2, 11
  • 40. Debugging: NightmareWednesday, November 2, 11
  • 41. Debugging: Dream Comes TrueWednesday, November 2, 11
  • 42. Debugging: Dream Comes TrueWednesday, November 2, 11
  • 43. DeploymentWednesday, November 2, 11
  • 44. Deployment Ext.Loader.history === [ My.sample.Person, My.sample.Location, My.sample.Developer, My.ability.Sing, My.ability.PlayInstruments, My.ability.ComposeSongs, My.sample.Performer, Concatenate Minify app.js My.sample.Composer, My.sample.SingerSongwriter, /* ... */ ]; http://www.sencha.com/products/sdk-toolsWednesday, November 2, 11
  • 45. SummaryWednesday, November 2, 11
  • 46. Thank you!Wednesday, November 2, 11