Writing Apps the Google-y Way (Brisbane)

Pamela Fox
Pamela FoxWeb Developer at Home
WRITING APPS THE GOOGLE-Y WAY Pamela Fox, YOW! Australia 2010 (Brisbane)
Who am I? twitter.com/pamelafox [email_address] pamelafox.org you get the idea...
Who am I? Google Maps API Google Wave API 2006 2010 2008 Google App Engine
Who am I? wave side projects 92 apps
Who am I? Java pYthon
What is App Engine? ,[object Object],[object Object]
What is a “web app”?
Static vs. Dynamic
Anonymous vs. Users
Intranet vs. Internet ~2 billion Hundreds - Thousands
What is a “web app”?
Some Google web apps
Some Google App Engine web apps www.gifttag.com www.buddypoke.com
Google apps on App Engine panoramio.com pubsubhubbub.appspot.com
How does App Engine work? ,[object Object],[object Object],[object Object]
Demo: Guestbook awesomest-app.appspot.com http://code.google.com/p/google-app-engine-samples/source/browse/trunk/guestbook appengine.google.com localhost build deploy monitor
App Engine architecture
App Engine architecture user task
App Engine architecture
App Engine architecture LIMIT CPU LIMIT Memory LIMIT Time
App Engine architecture hardware ports globals file system Groovy, JRuby, Mirah, Clojure, Scala
App Engine architecture 141,241,791 calls 1 GB data $0.15 GB/month 45,000,000 calls 657,000 -  46,000,000 calls *Always check docs for latest quotas. 192,672,000 calls 558 GB data $0.15 GB/month 7,000 - 1,700,000 calls $0.0001 per mail sent 46,000,000 calls  1,046 GB data sent 100,000 - 20,000,000 calls
The tricky bits
Datastore Entity Properties Key Entity Entity Entity Entity Path Kind Name/ID
Example: Speaker Entities Key Path Kind ID First Name Last Name Speaker1 - Speaker 1 Rod Johnson Key Path Kind ID First Name Last Name Middle Name Suffix Speaker2 - Speaker 2 Guy Steele L Jr.
Modeling Speaker Entities ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Saving Speaker Entities ,[object Object],[object Object],[object Object],[object Object],[object Object]
Updating Speaker Entities ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],LIMIT! (size/# of batch ops)
Queries & Indexes Query Index Index Index Index Query Query Query Query Query
Queries & Indexes SELECT * from Speaker ORDER BY lastname LIMIT! (# of results) key lastname Speaker3 Fox Speaker4 Hohpe Speaker1 Johnson Speaker2 Steele
Queries & Indexes SELECT * from Speaker ORDER by middlename key middlename Speaker2 L
Queries & Indexes SELECT * from Speaker WHERE keynote = True key keynote Speaker1 True Speaker2 True Speaker3 False Speaker4 False
Queries & Indexes SELECT * from Speaker WHERE keynote = False key keynote Speaker1 True Speaker2 True Speaker3 False Speaker4 False
Queries ,[object Object],[object Object],[object Object],[object Object],[object Object],LIMIT! (size of results)
Custom Indexes ,[object Object],[object Object],SELECT * from Speaker ORDER BY lastname, keynote key lastname keynote Speaker3 Fox false Speaker4 Hohpe false Speaker1 Johnson true Speaker2 Steele true
Custom Indexes ,[object Object],[object Object],SELECT * from Speaker WHERE lastname > 'Johnson'  and keynote = true key lastname keynote Speaker3 Fox false Speaker4 Hohpe false Speaker1 Johnson true Speaker2 Steele true
Impossible Indexes SELECT * from Speaker WHERE lastname < 'Steele'  and firstname > 'Gregory' ...not in subsequent rows! key lastname firstname Speaker3 Fox Pamela Speaker4 Hohpe Gregory Speaker1 Johnson Rod Speaker2 Steele Guy
Impossible Indexes SELECT * from Speaker WHERE lastname > 'Fox' ORDER BY firstname  ...not in the correct order! key lastname firstname Speaker3 Fox Pamela Speaker4 Hohpe Gregory Speaker1 Johnson Rod Speaker2 Steele Guy
Queries with Offset ,[object Object],SELECT * from Speaker LIMIT 2 OFFSET 2 1 2 ...slow! LIMIT! (# of offset) key lastname Speaker3 Fox Speaker4 Hohpe Speaker1 Johnson Speaker2 Steele
Queries with Cursors ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
More Properties class Talk(db.Model): title = db.StringProperty(required=True) abstract = db.TextProperty(required=True) speaker = db.ReferenceProperty(Speaker) tags = db.StringListProperty() pamela = Speaker.all().filter('firstname = ', 'Pamela').get() talk = Talk('Writing Apps the Googley Way', 'Bla bla bla', pamela, ['App Engine', 'Python']) talk.put() talk = Talk('Wonders of the Onesie', 'Bluh bluh bluh', pamela, ['Pajamas', 'Onesies']) talk.put()
Back-References pamela = Speaker.all().filter('firstname = ', 'Pamela').get() for talk in pamela.talk_set: print talk.title SELECT * from Talk WHERE speaker = Speaker3 key speaker Talk6 Speaker2 Talk1 Speaker3 Talk2 Speaker3 Talk5 Speaker4
Searching List Properties talks = Talk.all().filter('tags = ', 'python') .fetch(10) SELECT * from Talk WHERE tags = 'Python' LIMIT! (# of index rows) key lastname Talk1 App Engine Talk2 Pajamas Talk1 Python Talk2 Onesies
Update Transactions commit journal apply entities apply indexes A B
Entity Groups pamela = Speaker.all().filter('firstname = ', 'Pamela').get() talk1 = Talk('Writing Apps the Googley Way', 'Bla bla bla', pamela, ['App Engine', 'Python'], parent=pamela) talk2 = Talk('Wonders of the Onesie', 'Bluh bluh bluh', pamela, ['Pajamas', 'Onesies'], parent=pamela) db.put(talk1, talk2) def update_talks(): talk1.title = 'Writing Apps the Microsoft Way' talk2.title = 'Wonders of the Windows' db.put(talk1, talk2) db.run_in_transaction(update_talks)
Common Features
Counters 1 2 3 4 5 people have done something.
RageTube: Global Stats ragetube.net http://github.com/pamelafox/ragetube
RageTube: Global Stats SongStat yaycount viewcount title artist Key Path Kind Name (song) naycount mehcount
RageTube: Global Stats viewcount viewcount viewcount datastore memcache
RageTube: Global Stats class Song(db.Model): viewcount = db.IntegerProperty(default=0) title = db.StringProperty() artist = db.StringProperty() def get_viewcount(self): viewcount = self.viewcount cached_viewcount = memcache.get('viewcount-' + self.key().name(), self.key().kind()) if cached_viewcount: viewcount += cached_viewcount return viewcount @classmethod def flush_viewcount(cls, name): song = cls.get_by_key_name(name) value = memcache.get('viewcount-' + name, cls.kind()) memcache.decr('viewcount-' + name, value, cls.kind()) song.viewcount += value song.put() @classmethod def incr_viewcount(cls, name, interval=5, value=1): memcache.incr('viewcount-' + name, value, cls.kind()) interval_num = get_interval_number(datetime.now(), interval) task_name = '-'.join([cls.kind(), name.replace(' ', '-'),  'viewcount', str(interval), str(interval_num)]) deferred.defer(cls.flush_viewcount, name, _name=task_name) LIMIT! (# of tasks)
Ratings Rated by 500 users.
App Gallery: Ratings google.com/analytics/apps/
App Gallery: Ratings Comment Application total_ratings sum_ratings avg_rating rated_index comment_count rating
App Gallery: Ratings def UpdateAppCommentData(self, rating, operation): def UpdateCommentData(self, rating, operation): self.comment_count += 1 * operation self.sum_ratings += rating * operation self.total_ratings += 1 * operation self.avg_rating = int(round(self.sum_ratings / self.total_ratings)) self.rated_index = '%d:%d:%d' %  (self.avg_rating, self.total_ratings, self.index) self.put() db.run_in_transaction(UpdateCommentData, self, rating, operation) app.UpdateAppCommentData(rating, db_models.Comment.ADD) comment = db_models.Comment() comment.application = app comment.rating = rating comment.put() query.order('-avg_rating').order('-rated_index')
Geospatial Queries
City-Go-Round: Agencies citygoround.org https://github.com/walkscore/City-Go-Round
City-Go-Round: Geo Queries Agency GeoModel location (GeoPt) location_geocells (StringListProperty)
City-Go-Round: Geo Queries def fetch_agencies_near(lat, long, bbox_side_in_miles): query = Agency.all() bbox = bbox_centered_at(lat, long, bbox_side_in_miles) return Agency.bounding_box_fetch(query, bbox, max_results = 50) def bounding_box_fetch(query, bbox, max_results=1000,): results = [] query_geocells = geocell.best_bbox_search_cells(bbox) for entity in query.filter('location_geocells IN', query_geocells): if len(results) == max_results: break if (entity.location.lat >= bbox.south and entity.location.lat <= bbox.north and entity.location.lon >= bbox.west and entity.location.lon <= bbox.east): results.append(entity) return results
Full Text Search ,[object Object],Search Thingy It's like pizza, but in the cloud. Other Thingy This will make you smell as delicious as pizza.
Disclosed.ca: Search https://github.com/nurey/disclosed disclosed.ca
Disclosed.ca: Search Contract agency_name vendor_name description comments uri
Disclosed.ca: Search from search.core import SearchIndexProperty, porter_stemmer class Contract(db.Model): uri = db.StringProperty(required=True) agency_name = db.StringProperty(required=True) vendor_name = db.StringProperty(required=True) description = db.StringProperty() comments = db.TextProperty() search_index = SearchIndexProperty(('agency_name', 'vendor_name', 'description', 'comments'), indexer=porter_stemmer) results = Contract.search_index.search(sheep').fetch(20)
Disclosed.ca: Search Contract agency_name vendor_name description comments uri search_index (StringListProperty) SearchIndex
Disclosed.ca: Search SELECT FROM ContractSearch WHERE search_index = &quot;sheep&quot; key search_index ContractSearch1 charter ContractSearch1 june ContractSearch1 sheep ContractSearch2 sheep ContractSearch1 wood
More Learning http://ae-book.appspot.com http://code.google.com/appengine http://blog.notdot.net/
AppEngine: Now & Later &quot;Run your web apps on Google's infrastructure. Easy to build, easy to maintain, easy to scale.&quot; ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
Thanks for coming!
1 of 68

Recommended

Writing Apps the Google-y Way by
Writing Apps the Google-y WayWriting Apps the Google-y Way
Writing Apps the Google-y WayPamela Fox
1.5K views67 slides
Django O/R Mapper by
Django O/R MapperDjango O/R Mapper
Django O/R MapperIan Lewis
873 views18 slides
Exploiting Php With Php by
Exploiting Php With PhpExploiting Php With Php
Exploiting Php With PhpJeremy Coates
32.6K views71 slides
Power Theming by
Power ThemingPower Theming
Power Themingdrkdn
390 views73 slides
Writing Friendly libraries for CodeIgniter by
Writing Friendly libraries for CodeIgniterWriting Friendly libraries for CodeIgniter
Writing Friendly libraries for CodeIgniterCodeIgniter Conference
1.3K views64 slides
ABC of Perl programming by
ABC of Perl programmingABC of Perl programming
ABC of Perl programmingBo Hua Yang
650 views27 slides

More Related Content

What's hot

Ruby on discuz by
Ruby on discuzRuby on discuz
Ruby on discuzMu-Fan Teng
3.9K views82 slides
Symfony2 meets propel 1.5 by
Symfony2 meets propel 1.5Symfony2 meets propel 1.5
Symfony2 meets propel 1.5Francois Zaninotto
6.3K views42 slides
Plugin jQuery, Design Patterns by
Plugin jQuery, Design PatternsPlugin jQuery, Design Patterns
Plugin jQuery, Design PatternsRobert Casanova
19.8K views26 slides
DBIx::Class beginners by
DBIx::Class beginnersDBIx::Class beginners
DBIx::Class beginnersleo lapworth
26.1K views95 slides
Introduction to Perl Best Practices by
Introduction to Perl Best PracticesIntroduction to Perl Best Practices
Introduction to Perl Best PracticesJosé Castro
3.7K views135 slides
Dealing with Legacy Perl Code - Peter Scott by
Dealing with Legacy Perl Code - Peter ScottDealing with Legacy Perl Code - Peter Scott
Dealing with Legacy Perl Code - Peter ScottO'Reilly Media
12.8K views74 slides

What's hot(20)

Ruby on discuz by Mu-Fan Teng
Ruby on discuzRuby on discuz
Ruby on discuz
Mu-Fan Teng3.9K views
Plugin jQuery, Design Patterns by Robert Casanova
Plugin jQuery, Design PatternsPlugin jQuery, Design Patterns
Plugin jQuery, Design Patterns
Robert Casanova19.8K views
DBIx::Class beginners by leo lapworth
DBIx::Class beginnersDBIx::Class beginners
DBIx::Class beginners
leo lapworth26.1K views
Introduction to Perl Best Practices by José Castro
Introduction to Perl Best PracticesIntroduction to Perl Best Practices
Introduction to Perl Best Practices
José Castro3.7K views
Dealing with Legacy Perl Code - Peter Scott by O'Reilly Media
Dealing with Legacy Perl Code - Peter ScottDealing with Legacy Perl Code - Peter Scott
Dealing with Legacy Perl Code - Peter Scott
O'Reilly Media12.8K views
Searching ORM: First Why, Then How by sfarmer10
Searching ORM: First Why, Then HowSearching ORM: First Why, Then How
Searching ORM: First Why, Then How
sfarmer10547 views
DBIx::Class introduction - 2010 by leo lapworth
DBIx::Class introduction - 2010DBIx::Class introduction - 2010
DBIx::Class introduction - 2010
leo lapworth3.7K views
LPW: Beginners Perl by Dave Cross
LPW: Beginners PerlLPW: Beginners Perl
LPW: Beginners Perl
Dave Cross43.5K views
Don't Repeat Yourself, Repeat Others by John Nunemaker
Don't Repeat Yourself, Repeat OthersDon't Repeat Yourself, Repeat Others
Don't Repeat Yourself, Repeat Others
John Nunemaker19.5K views
Good Evils In Perl by Kang-min Liu
Good Evils In PerlGood Evils In Perl
Good Evils In Perl
Kang-min Liu13.8K views
Best Practices in Plugin Development (WordCamp Seattle) by andrewnacin
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)
andrewnacin27.1K views
Accelerated Native Mobile Development with the Ti gem by Wynn Netherland
Accelerated Native Mobile Development with the Ti gemAccelerated Native Mobile Development with the Ti gem
Accelerated Native Mobile Development with the Ti gem
Wynn Netherland954 views
jQuery Plugin Creation by benalman
jQuery Plugin CreationjQuery Plugin Creation
jQuery Plugin Creation
benalman22.7K views
Evolving Software with Moose by Dave Cross
Evolving Software with MooseEvolving Software with Moose
Evolving Software with Moose
Dave Cross2K views
WordPress London 16 May 2012 - You don’t know query by l3rady
WordPress London 16 May 2012 - You don’t know queryWordPress London 16 May 2012 - You don’t know query
WordPress London 16 May 2012 - You don’t know query
l3rady1.1K views

Viewers also liked

Google Wave Intro by
Google Wave IntroGoogle Wave Intro
Google Wave IntroAnjesh Tuladhar
1.3K views19 slides
Getting started with google wave by
Getting started with google waveGetting started with google wave
Getting started with google waveMohamed Amin Embi
818 views30 slides
Google Wave First Look by
Google Wave   First LookGoogle Wave   First Look
Google Wave First LookVijay Raj
662 views13 slides
Are you ready for Google Wave? by
Are you ready for Google Wave?Are you ready for Google Wave?
Are you ready for Google Wave?Pongsakorn U-chupala
582 views20 slides
20091014 Google Wave by
20091014 Google Wave20091014 Google Wave
20091014 Google WaveAlexander Benker
1.8K views34 slides
Google Wave Basics by
Google Wave BasicsGoogle Wave Basics
Google Wave BasicsBelmond Victor
1.1K views21 slides

Viewers also liked(15)

Google Wave First Look by Vijay Raj
Google Wave   First LookGoogle Wave   First Look
Google Wave First Look
Vijay Raj662 views
What Is Google Wave by rkeith
What Is Google WaveWhat Is Google Wave
What Is Google Wave
rkeith476 views
Google Wave API: Now and Beyond by Marakana Inc.
Google Wave API: Now and BeyondGoogle Wave API: Now and Beyond
Google Wave API: Now and Beyond
Marakana Inc.1.3K views
Google Wave 20/20: Product, Protocol, Platform by Pamela Fox
Google Wave 20/20: Product, Protocol, PlatformGoogle Wave 20/20: Product, Protocol, Platform
Google Wave 20/20: Product, Protocol, Platform
Pamela Fox1.7K views
Google Wave Introduction by Craig Dickson
Google Wave IntroductionGoogle Wave Introduction
Google Wave Introduction
Craig Dickson1.4K views
Email Is So 1973 by Red Magma
Email Is So 1973Email Is So 1973
Email Is So 1973
Red Magma6.8K views

Similar to Writing Apps the Google-y Way (Brisbane)

Having Fun Programming! by
Having Fun Programming!Having Fun Programming!
Having Fun Programming!Aaron Patterson
863 views175 slides
The bones of a nice Python script by
The bones of a nice Python scriptThe bones of a nice Python script
The bones of a nice Python scriptsaniac
2.9K views13 slides
Python - Getting to the Essence - Points.com - Dave Park by
Python - Getting to the Essence - Points.com - Dave ParkPython - Getting to the Essence - Points.com - Dave Park
Python - Getting to the Essence - Points.com - Dave Parkpointstechgeeks
935 views17 slides
Plone For Developers - World Plone Day, 2009 by
Plone For Developers - World Plone Day, 2009Plone For Developers - World Plone Day, 2009
Plone For Developers - World Plone Day, 2009Core Software Group
390 views17 slides
Building a friendly .NET SDK to connect to Space by
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceMaarten Balliauw
182 views47 slides
ScotRuby - Dark side of ruby by
ScotRuby - Dark side of rubyScotRuby - Dark side of ruby
ScotRuby - Dark side of rubyGautam Rege
1.3K views143 slides

Similar to Writing Apps the Google-y Way (Brisbane)(20)

The bones of a nice Python script by saniac
The bones of a nice Python scriptThe bones of a nice Python script
The bones of a nice Python script
saniac2.9K views
Python - Getting to the Essence - Points.com - Dave Park by pointstechgeeks
Python - Getting to the Essence - Points.com - Dave ParkPython - Getting to the Essence - Points.com - Dave Park
Python - Getting to the Essence - Points.com - Dave Park
pointstechgeeks935 views
Building a friendly .NET SDK to connect to Space by Maarten Balliauw
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to Space
Maarten Balliauw182 views
ScotRuby - Dark side of ruby by Gautam Rege
ScotRuby - Dark side of rubyScotRuby - Dark side of ruby
ScotRuby - Dark side of ruby
Gautam Rege1.3K views
Object Orientation vs. Functional Programming in Python by Python Ireland
Object Orientation vs. Functional Programming in PythonObject Orientation vs. Functional Programming in Python
Object Orientation vs. Functional Programming in Python
Python Ireland1K views
React.js Basics - ConvergeSE 2015 by Robert Pearce
React.js Basics - ConvergeSE 2015React.js Basics - ConvergeSE 2015
React.js Basics - ConvergeSE 2015
Robert Pearce1.7K views
NUS iOS Swift Talk by Gabriel Lim
NUS iOS Swift TalkNUS iOS Swift Talk
NUS iOS Swift Talk
Gabriel Lim2.2K views
Addmi 10.5-basic query-language by odanyboy
Addmi 10.5-basic query-languageAddmi 10.5-basic query-language
Addmi 10.5-basic query-language
odanyboy641 views
Decorators in Python by Ben James
Decorators in PythonDecorators in Python
Decorators in Python
Ben James1.8K views
Think Generic - Add API's To Your Custom Modules by Jens Sørensen
Think Generic - Add API's To Your Custom ModulesThink Generic - Add API's To Your Custom Modules
Think Generic - Add API's To Your Custom Modules
Jens Sørensen412 views
PyCon APAC - Django Test Driven Development by Tudor Munteanu
PyCon APAC - Django Test Driven DevelopmentPyCon APAC - Django Test Driven Development
PyCon APAC - Django Test Driven Development
Tudor Munteanu1.6K views
Javascript Primer by Adam Hepton
Javascript PrimerJavascript Primer
Javascript Primer
Adam Hepton550 views
Casting for not so strange actors by zucaritask
Casting for not so strange actorsCasting for not so strange actors
Casting for not so strange actors
zucaritask774 views

More from Pamela Fox

Teaching Programming Online by
Teaching Programming OnlineTeaching Programming Online
Teaching Programming OnlinePamela Fox
1.4K views48 slides
Engineering culture by
Engineering cultureEngineering culture
Engineering culturePamela Fox
4.1K views51 slides
Django Admin: Widgetry & Witchery by
Django Admin: Widgetry & WitcheryDjango Admin: Widgetry & Witchery
Django Admin: Widgetry & WitcheryPamela Fox
2.3K views16 slides
A Year of Hermit Hacking by
A Year of Hermit HackingA Year of Hermit Hacking
A Year of Hermit HackingPamela Fox
1.5K views20 slides
The Developer Experience by
The Developer Experience The Developer Experience
The Developer Experience Pamela Fox
1.3K views60 slides
Making JavaScript Libraries More Approachable by
Making JavaScript Libraries More ApproachableMaking JavaScript Libraries More Approachable
Making JavaScript Libraries More ApproachablePamela Fox
5.1K views30 slides

More from Pamela Fox(20)

Teaching Programming Online by Pamela Fox
Teaching Programming OnlineTeaching Programming Online
Teaching Programming Online
Pamela Fox1.4K views
Engineering culture by Pamela Fox
Engineering cultureEngineering culture
Engineering culture
Pamela Fox4.1K views
Django Admin: Widgetry & Witchery by Pamela Fox
Django Admin: Widgetry & WitcheryDjango Admin: Widgetry & Witchery
Django Admin: Widgetry & Witchery
Pamela Fox2.3K views
A Year of Hermit Hacking by Pamela Fox
A Year of Hermit HackingA Year of Hermit Hacking
A Year of Hermit Hacking
Pamela Fox1.5K views
The Developer Experience by Pamela Fox
The Developer Experience The Developer Experience
The Developer Experience
Pamela Fox1.3K views
Making JavaScript Libraries More Approachable by Pamela Fox
Making JavaScript Libraries More ApproachableMaking JavaScript Libraries More Approachable
Making JavaScript Libraries More Approachable
Pamela Fox5.1K views
How I became a born again vegetable-tarian by Pamela Fox
How I became a born again vegetable-tarianHow I became a born again vegetable-tarian
How I became a born again vegetable-tarian
Pamela Fox6.8K views
The Developer Experience by Pamela Fox
The Developer ExperienceThe Developer Experience
The Developer Experience
Pamela Fox14.4K views
No, Really, I'm Shy by Pamela Fox
No, Really, I'm ShyNo, Really, I'm Shy
No, Really, I'm Shy
Pamela Fox8.1K views
The Wonders of the "Onesie" by Pamela Fox
The Wonders of the "Onesie"The Wonders of the "Onesie"
The Wonders of the "Onesie"
Pamela Fox2K views
I’M A Barbie Girl In A CS World by Pamela Fox
I’M A Barbie Girl In A CS WorldI’M A Barbie Girl In A CS World
I’M A Barbie Girl In A CS World
Pamela Fox6K views
Collaborative Mapping with Google Wave by Pamela Fox
Collaborative Mapping with Google WaveCollaborative Mapping with Google Wave
Collaborative Mapping with Google Wave
Pamela Fox1.4K views
Google Products: Deep Dive on Google Maps by Pamela Fox
Google Products: Deep Dive on Google MapsGoogle Products: Deep Dive on Google Maps
Google Products: Deep Dive on Google Maps
Pamela Fox1.5K views
Google Products & Google Maps by Pamela Fox
Google Products & Google MapsGoogle Products & Google Maps
Google Products & Google Maps
Pamela Fox2.8K views
Mashups & APIs by Pamela Fox
Mashups & APIsMashups & APIs
Mashups & APIs
Pamela Fox2.3K views
A World of Words by Pamela Fox
A World of WordsA World of Words
A World of Words
Pamela Fox4.2K views
Web APIs & Google APIs by Pamela Fox
Web APIs & Google APIsWeb APIs & Google APIs
Web APIs & Google APIs
Pamela Fox1.5K views
Growing up Geek: My Dad, the Computer Scientist by Pamela Fox
Growing up Geek: My Dad, the Computer ScientistGrowing up Geek: My Dad, the Computer Scientist
Growing up Geek: My Dad, the Computer Scientist
Pamela Fox2.9K views
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructure by Pamela Fox
Living in the Cloud: Hosting Data & Apps Using the Google InfrastructureLiving in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Living in the Cloud: Hosting Data & Apps Using the Google Infrastructure
Pamela Fox1.3K views
Client Killed the Server Star by Pamela Fox
Client Killed the Server StarClient Killed the Server Star
Client Killed the Server Star
Pamela Fox5.4K views

Recently uploaded

voice logger software aegis.pdf by
voice logger software aegis.pdfvoice logger software aegis.pdf
voice logger software aegis.pdfNirmal Sharma
10 views1 slide
Amazon Music - Market Analysis by
Amazon Music - Market AnalysisAmazon Music - Market Analysis
Amazon Music - Market AnalysisAna Weathers
37 views11 slides
ZARA.pptx by
ZARA.pptxZARA.pptx
ZARA.pptxmerlinjenma529
21 views13 slides
terms_2.pdf by
terms_2.pdfterms_2.pdf
terms_2.pdfJAWADIQBAL40
15 views8 slides
UCA towards I5.0 OECD.pdf by
UCA towards I5.0 OECD.pdfUCA towards I5.0 OECD.pdf
UCA towards I5.0 OECD.pdfAPPAU_Ukraine
7 views16 slides
Leading in A Culture by
Leading in A CultureLeading in A Culture
Leading in A CultureSeta Wicaksana
11 views34 slides

Recently uploaded(20)

voice logger software aegis.pdf by Nirmal Sharma
voice logger software aegis.pdfvoice logger software aegis.pdf
voice logger software aegis.pdf
Nirmal Sharma10 views
Amazon Music - Market Analysis by Ana Weathers
Amazon Music - Market AnalysisAmazon Music - Market Analysis
Amazon Music - Market Analysis
Ana Weathers37 views
Assignment 4: Reporting to Management.pptx by BethanyAline
Assignment 4: Reporting to Management.pptxAssignment 4: Reporting to Management.pptx
Assignment 4: Reporting to Management.pptx
BethanyAline16 views
Bloomerang_Forecasting Your Fundraising Revenue 2024.pptx.pdf by Bloomerang
Bloomerang_Forecasting Your Fundraising Revenue 2024.pptx.pdfBloomerang_Forecasting Your Fundraising Revenue 2024.pptx.pdf
Bloomerang_Forecasting Your Fundraising Revenue 2024.pptx.pdf
Bloomerang47 views
See the new MTN tariffs effected November 28, 2023 by Kweku Zurek
See the new MTN tariffs effected November 28, 2023See the new MTN tariffs effected November 28, 2023
See the new MTN tariffs effected November 28, 2023
Kweku Zurek29.4K views
Discover the Finest Interior Painting Services in Miami Elevate Your Space wi... by Florida Painting Miami
Discover the Finest Interior Painting Services in Miami Elevate Your Space wi...Discover the Finest Interior Painting Services in Miami Elevate Your Space wi...
Discover the Finest Interior Painting Services in Miami Elevate Your Space wi...
PMU Launch - Guaranteed Slides by pmulaunch
PMU Launch - Guaranteed SlidesPMU Launch - Guaranteed Slides
PMU Launch - Guaranteed Slides
pmulaunch11 views
Top 10 Web Development Companies in California by TopCSSGallery
Top 10 Web Development Companies in CaliforniaTop 10 Web Development Companies in California
Top 10 Web Development Companies in California
TopCSSGallery26 views
India's Leading Cyber Security Companies to Watch.pdf by insightssuccess2
India's Leading Cyber Security Companies to Watch.pdfIndia's Leading Cyber Security Companies to Watch.pdf
India's Leading Cyber Security Companies to Watch.pdf
Presentation on proposed acquisition of leading European asset manager Aermon... by KeppelCorporation
Presentation on proposed acquisition of leading European asset manager Aermon...Presentation on proposed acquisition of leading European asset manager Aermon...
Presentation on proposed acquisition of leading European asset manager Aermon...
Episode 258 Snippets: Rob Gevertz of First Five Yards by Neil Horowitz
Episode 258 Snippets: Rob Gevertz of First Five YardsEpisode 258 Snippets: Rob Gevertz of First Five Yards
Episode 258 Snippets: Rob Gevertz of First Five Yards
Neil Horowitz45 views
SUGAR cosmetics ppt by shafrinn5
SUGAR cosmetics pptSUGAR cosmetics ppt
SUGAR cosmetics ppt
shafrinn524 views

Writing Apps the Google-y Way (Brisbane)

  • 1. WRITING APPS THE GOOGLE-Y WAY Pamela Fox, YOW! Australia 2010 (Brisbane)
  • 2. Who am I? twitter.com/pamelafox [email_address] pamelafox.org you get the idea...
  • 3. Who am I? Google Maps API Google Wave API 2006 2010 2008 Google App Engine
  • 4. Who am I? wave side projects 92 apps
  • 5. Who am I? Java pYthon
  • 6.
  • 7. What is a “web app”?
  • 10. Intranet vs. Internet ~2 billion Hundreds - Thousands
  • 11. What is a “web app”?
  • 13. Some Google App Engine web apps www.gifttag.com www.buddypoke.com
  • 14. Google apps on App Engine panoramio.com pubsubhubbub.appspot.com
  • 15.
  • 16. Demo: Guestbook awesomest-app.appspot.com http://code.google.com/p/google-app-engine-samples/source/browse/trunk/guestbook appengine.google.com localhost build deploy monitor
  • 20. App Engine architecture LIMIT CPU LIMIT Memory LIMIT Time
  • 21. App Engine architecture hardware ports globals file system Groovy, JRuby, Mirah, Clojure, Scala
  • 22. App Engine architecture 141,241,791 calls 1 GB data $0.15 GB/month 45,000,000 calls 657,000 - 46,000,000 calls *Always check docs for latest quotas. 192,672,000 calls 558 GB data $0.15 GB/month 7,000 - 1,700,000 calls $0.0001 per mail sent 46,000,000 calls 1,046 GB data sent 100,000 - 20,000,000 calls
  • 24. Datastore Entity Properties Key Entity Entity Entity Entity Path Kind Name/ID
  • 25. Example: Speaker Entities Key Path Kind ID First Name Last Name Speaker1 - Speaker 1 Rod Johnson Key Path Kind ID First Name Last Name Middle Name Suffix Speaker2 - Speaker 2 Guy Steele L Jr.
  • 26.
  • 27.
  • 28.
  • 29. Queries & Indexes Query Index Index Index Index Query Query Query Query Query
  • 30. Queries & Indexes SELECT * from Speaker ORDER BY lastname LIMIT! (# of results) key lastname Speaker3 Fox Speaker4 Hohpe Speaker1 Johnson Speaker2 Steele
  • 31. Queries & Indexes SELECT * from Speaker ORDER by middlename key middlename Speaker2 L
  • 32. Queries & Indexes SELECT * from Speaker WHERE keynote = True key keynote Speaker1 True Speaker2 True Speaker3 False Speaker4 False
  • 33. Queries & Indexes SELECT * from Speaker WHERE keynote = False key keynote Speaker1 True Speaker2 True Speaker3 False Speaker4 False
  • 34.
  • 35.
  • 36.
  • 37. Impossible Indexes SELECT * from Speaker WHERE lastname < 'Steele' and firstname > 'Gregory' ...not in subsequent rows! key lastname firstname Speaker3 Fox Pamela Speaker4 Hohpe Gregory Speaker1 Johnson Rod Speaker2 Steele Guy
  • 38. Impossible Indexes SELECT * from Speaker WHERE lastname > 'Fox' ORDER BY firstname ...not in the correct order! key lastname firstname Speaker3 Fox Pamela Speaker4 Hohpe Gregory Speaker1 Johnson Rod Speaker2 Steele Guy
  • 39.
  • 40.
  • 41. More Properties class Talk(db.Model): title = db.StringProperty(required=True) abstract = db.TextProperty(required=True) speaker = db.ReferenceProperty(Speaker) tags = db.StringListProperty() pamela = Speaker.all().filter('firstname = ', 'Pamela').get() talk = Talk('Writing Apps the Googley Way', 'Bla bla bla', pamela, ['App Engine', 'Python']) talk.put() talk = Talk('Wonders of the Onesie', 'Bluh bluh bluh', pamela, ['Pajamas', 'Onesies']) talk.put()
  • 42. Back-References pamela = Speaker.all().filter('firstname = ', 'Pamela').get() for talk in pamela.talk_set: print talk.title SELECT * from Talk WHERE speaker = Speaker3 key speaker Talk6 Speaker2 Talk1 Speaker3 Talk2 Speaker3 Talk5 Speaker4
  • 43. Searching List Properties talks = Talk.all().filter('tags = ', 'python') .fetch(10) SELECT * from Talk WHERE tags = 'Python' LIMIT! (# of index rows) key lastname Talk1 App Engine Talk2 Pajamas Talk1 Python Talk2 Onesies
  • 44. Update Transactions commit journal apply entities apply indexes A B
  • 45. Entity Groups pamela = Speaker.all().filter('firstname = ', 'Pamela').get() talk1 = Talk('Writing Apps the Googley Way', 'Bla bla bla', pamela, ['App Engine', 'Python'], parent=pamela) talk2 = Talk('Wonders of the Onesie', 'Bluh bluh bluh', pamela, ['Pajamas', 'Onesies'], parent=pamela) db.put(talk1, talk2) def update_talks(): talk1.title = 'Writing Apps the Microsoft Way' talk2.title = 'Wonders of the Windows' db.put(talk1, talk2) db.run_in_transaction(update_talks)
  • 47. Counters 1 2 3 4 5 people have done something.
  • 48. RageTube: Global Stats ragetube.net http://github.com/pamelafox/ragetube
  • 49. RageTube: Global Stats SongStat yaycount viewcount title artist Key Path Kind Name (song) naycount mehcount
  • 50. RageTube: Global Stats viewcount viewcount viewcount datastore memcache
  • 51. RageTube: Global Stats class Song(db.Model): viewcount = db.IntegerProperty(default=0) title = db.StringProperty() artist = db.StringProperty() def get_viewcount(self): viewcount = self.viewcount cached_viewcount = memcache.get('viewcount-' + self.key().name(), self.key().kind()) if cached_viewcount: viewcount += cached_viewcount return viewcount @classmethod def flush_viewcount(cls, name): song = cls.get_by_key_name(name) value = memcache.get('viewcount-' + name, cls.kind()) memcache.decr('viewcount-' + name, value, cls.kind()) song.viewcount += value song.put() @classmethod def incr_viewcount(cls, name, interval=5, value=1): memcache.incr('viewcount-' + name, value, cls.kind()) interval_num = get_interval_number(datetime.now(), interval) task_name = '-'.join([cls.kind(), name.replace(' ', '-'), 'viewcount', str(interval), str(interval_num)]) deferred.defer(cls.flush_viewcount, name, _name=task_name) LIMIT! (# of tasks)
  • 52. Ratings Rated by 500 users.
  • 53. App Gallery: Ratings google.com/analytics/apps/
  • 54. App Gallery: Ratings Comment Application total_ratings sum_ratings avg_rating rated_index comment_count rating
  • 55. App Gallery: Ratings def UpdateAppCommentData(self, rating, operation): def UpdateCommentData(self, rating, operation): self.comment_count += 1 * operation self.sum_ratings += rating * operation self.total_ratings += 1 * operation self.avg_rating = int(round(self.sum_ratings / self.total_ratings)) self.rated_index = '%d:%d:%d' % (self.avg_rating, self.total_ratings, self.index) self.put() db.run_in_transaction(UpdateCommentData, self, rating, operation) app.UpdateAppCommentData(rating, db_models.Comment.ADD) comment = db_models.Comment() comment.application = app comment.rating = rating comment.put() query.order('-avg_rating').order('-rated_index')
  • 57. City-Go-Round: Agencies citygoround.org https://github.com/walkscore/City-Go-Round
  • 58. City-Go-Round: Geo Queries Agency GeoModel location (GeoPt) location_geocells (StringListProperty)
  • 59. City-Go-Round: Geo Queries def fetch_agencies_near(lat, long, bbox_side_in_miles): query = Agency.all() bbox = bbox_centered_at(lat, long, bbox_side_in_miles) return Agency.bounding_box_fetch(query, bbox, max_results = 50) def bounding_box_fetch(query, bbox, max_results=1000,): results = [] query_geocells = geocell.best_bbox_search_cells(bbox) for entity in query.filter('location_geocells IN', query_geocells): if len(results) == max_results: break if (entity.location.lat >= bbox.south and entity.location.lat <= bbox.north and entity.location.lon >= bbox.west and entity.location.lon <= bbox.east): results.append(entity) return results
  • 60.
  • 62. Disclosed.ca: Search Contract agency_name vendor_name description comments uri
  • 63. Disclosed.ca: Search from search.core import SearchIndexProperty, porter_stemmer class Contract(db.Model): uri = db.StringProperty(required=True) agency_name = db.StringProperty(required=True) vendor_name = db.StringProperty(required=True) description = db.StringProperty() comments = db.TextProperty() search_index = SearchIndexProperty(('agency_name', 'vendor_name', 'description', 'comments'), indexer=porter_stemmer) results = Contract.search_index.search(sheep').fetch(20)
  • 64. Disclosed.ca: Search Contract agency_name vendor_name description comments uri search_index (StringListProperty) SearchIndex
  • 65. Disclosed.ca: Search SELECT FROM ContractSearch WHERE search_index = &quot;sheep&quot; key search_index ContractSearch1 charter ContractSearch1 june ContractSearch1 sheep ContractSearch2 sheep ContractSearch1 wood
  • 66. More Learning http://ae-book.appspot.com http://code.google.com/appengine http://blog.notdot.net/
  • 67.