single page applications with coffeescript [polish]
TRANSCRIPT
![Page 1: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/1.jpg)
Single Page Applications
Andrzej Krzywda
Use cases with CoffeeScript, DCI, AOP, TDD
![Page 2: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/2.jpg)
Kto lubi pisać w JavaScript?
![Page 3: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/3.jpg)
Agenda
• Frontend - Zmiana sposobu myślenia
• Single Page Application
• Frontend - architektura
![Page 4: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/4.jpg)
Zmiana sposobu myślenia
![Page 5: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/5.jpg)
Dumny programista backendów
![Page 6: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/6.jpg)
“JavaScript? My zajmujemy się
poważnymi projektami”
(2007 - 2008)
![Page 7: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/7.jpg)
Rails consulting since 2007
![Page 8: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/8.jpg)
“OK, zrobimy autocompletion”
![Page 9: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/9.jpg)
“Znajdźmy jakiś plugin railsowy, który to
generuje i nie patrzmy do środka”
![Page 10: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/10.jpg)
“Czy ceny mogą się zmieniać bez przeładowania?”
![Page 11: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/11.jpg)
“Renderujmy JavaScript po stronie serwera”
![Page 12: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/12.jpg)
“Pokazywanie słówek bez przeładowania”
![Page 13: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/13.jpg)
Backendy - RubyFrontendy - Coffee
![Page 14: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/14.jpg)
Social games for brands
(gierki i konkursy na FB i strony firmowe)
![Page 15: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/15.jpg)
“Gra w kółko i krzyżyk, potem wybór
nagrody”
![Page 16: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/16.jpg)
Hybryda
![Page 17: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/17.jpg)
Pierwsza wersja naszej platformy tak działała.
![Page 18: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/18.jpg)
Platforma GameBoxed==
jeden backend, wiele frontendów
market
![Page 19: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/19.jpg)
Gdzie renderujemy html?
![Page 20: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/20.jpg)
Cały html na frontendzie, serwer tylko zwraca JSON.
![Page 21: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/21.jpg)
HTML na frontendzie nie różni się od HTML
na backendzie
![Page 22: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/22.jpg)
<p>W tej sesji gry niesamowite umiejętności strzeleckie pozwolily Ci osiągnąć nowy rekord:<br> <b>{{playerMaxScore}} punktów.</b></p>
<a class="button ok_button">DALEJ</a>
handlebar
![Page 23: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/23.jpg)
Rewolucja
![Page 24: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/24.jpg)
Frontend to osobna aplikacja
![Page 25: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/25.jpg)
Market 2.0
![Page 26: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/26.jpg)
Pusher
web sockets
![Page 27: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/27.jpg)
Pusher
![Page 28: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/28.jpg)
Zmiana sposobu myślenia
• Faza 1: No JavaScript
• Faza 2: JQuery explosion
• Faza 3: Page/Widget object
• Faza 4: Single Page Application
W której fazie jest Twój projekt?
![Page 29: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/29.jpg)
Single Page Application
Gmail, Twitter, Facebook, Trello
![Page 30: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/30.jpg)
![Page 31: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/31.jpg)
CoffeeScriptbetter JS
Class oriented language
![Page 32: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/32.jpg)
Same zalety
![Page 33: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/33.jpg)
JS == assembler
![Page 34: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/34.jpg)
Coffee > Ruby
![Page 35: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/35.jpg)
underscore.js
![Page 36: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/36.jpg)
GameBoxed używa tylko Coffee do
frontend’ów
![Page 37: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/37.jpg)
Polecamy!
![Page 38: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/38.jpg)
Single Page Application
Architektura
![Page 39: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/39.jpg)
Trygve
MVC, DCI
![Page 40: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/40.jpg)
Zapomnijmy o MVC z backendu!
![Page 41: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/41.jpg)
Nie ma MVC na backendzie
![Page 42: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/42.jpg)
Nie ma View na backendzie
![Page 43: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/43.jpg)
Prawdziwe MVC(w uproszczeniu - zmiana w modelu
powoduje automatyczną zmianę w GUI)
(Rails, Struts, Spring - nie są MVC!)
![Page 44: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/44.jpg)
GUI - model
![Page 45: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/45.jpg)
Modele• Game
• Player
• GameSession
• Round
• Prize
• Friend (Invitation)
• Life (LifeRequest...)
• Team
![Page 46: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/46.jpg)
Views
• PrizeComponent
• FriendsComponent
• GameArea
• Popups
![Page 47: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/47.jpg)
Pierwsze podejście
![Page 48: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/48.jpg)
Popupy
• Wyświetl popup z zespołem gracza
• Po naciśnięciu OK, wyświetl popup z nagrodami
![Page 49: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/49.jpg)
Callbacks
![Page 50: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/50.jpg)
triggerActionsAfterMove: (move, callback) => @getBonusWhenStartCrossed(move) @getBonusWhenLandedOnCellWithFriends(@board.currentCell()) @pickCardAndNotifyIfAny(@board.currentCell(), callback)
![Page 51: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/51.jpg)
pickCardAndNotifyIfAny: (cell, callback) => console.debug "pickCardAndNotifyIfAny #{cell.position}" card = @drawCard(cell) if not card console.debug "no card picked" callback?() return console.debug "card found: #{card.identifier}" card.onPicked(@) if card.onPicked? @eventBroker.trigger("player:picked_card:#{card.identifier}", card, callback) @eventBroker.trigger("player:picked_card", card)
![Page 52: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/52.jpg)
class engine.monopoly.controllers.CardItemBargainContoller constructor: (@services, @game) -> @helper = new CardHelperForUsecases(@services)
setup: => @services.eventBroker.bind('player:picked_card:CardItemBargain', @execute)
execute: (card, callback) => @popup = @helper.showCardGenericPopupAndBindOnOK( (=> @applyFormDataToBargain(card, callback)), null) @popup.bind("popup:opened", => @popup.find('input').focus())
applyFormDataToBargain: (card, callback) => offer = @popup.find('input').val() new CardItemBargain(@services, @game).execute(card, offer, callback)
![Page 53: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/53.jpg)
Eventy
![Page 54: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/54.jpg)
class engine.shooter.components.StageResultWon
constructor: (@eventBroker) -> _.extend(@, Backbone.Events) super() @templateId = "stage_result_won"
addMeToScreen: (root, me) => $("#gameArea").append(me)
configureElement: (me) => me.find('.okButton').mousedown (event) => @hide() @eventBroker.trigger('stage:result:shown')
![Page 55: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/55.jpg)
class engine.shooter.models.Game
constructor: (@serverSide, @eventBroker) -> super(@eventBroker) @levels = [] @guns = []
registerEvents: (eventBroker) => eventBroker.bind('game:start:requested', @start)
eventBroker.bind("player:clicked:inside-target", @playerTriggeredShotInsideTarget) eventBroker.bind("player:clicked:magazine:reload", @playerWantsToReload)
eventBroker.bind("stage:start:clicked", @startStageClicked) eventBroker.bind('countdown:stage:finish', @finishCurrentStage)
eventBroker.bind("stage:result:shown", @loadNextStageOrFinishGame)
![Page 56: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/56.jpg)
Wymagana duża dyscyplina
![Page 57: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/57.jpg)
Gdzie jest główne flow?
![Page 58: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/58.jpg)
Use casesUsecaseController
DCI
![Page 59: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/59.jpg)
Game Designer
Piotrek
![Page 60: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/60.jpg)
Tomek - programista
(praca zdalna w praktyce)
![Page 61: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/61.jpg)
class engine.invite_and_win.GameUseCase constructor: (@game, @player) -> ObjectHelper.addRole(@player, engine.shared.models.PlayerWithFriends)
@facebookHQ = new engine.invite_and_win.FacebookHQ()
tryToEnterGameArea: () => if @amIEnteringGameFirstTime() if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam(@facebookHQ.friendsInviting)
@teachPlayerHowToPlay()
else #n-th time... if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam(@facebookHQ.friendsInviting)
if not @playerLikesFanpage() @askPlayerToLikeFanpage()
if @haveNotYetPickedFavPizzaCountry() @askPlayerToDeclareHisFavCountry()
![Page 62: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/62.jpg)
Use case używa dziedzinę
![Page 63: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/63.jpg)
Ani use case, ani dziedzina, nie wiedzą
nic o GUI
![Page 64: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/64.jpg)
Ani use case, ani dziedzina, nie wiedzą
nic o persistence
![Page 65: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/65.jpg)
Use case’y mogą działać z innym GUI i innym
persistence
![Page 66: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/66.jpg)
Gdzie jest DCI?
![Page 67: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/67.jpg)
Data Context Interaction
Trygve
![Page 68: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/68.jpg)
Dane pozostają w obiektach
Data
![Page 69: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/69.jpg)
Obiekty są dosyć “cienkie”
![Page 70: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/70.jpg)
class engine.shared.models.Player constructor: () -> @rank = null @maxScore = 0
![Page 71: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/71.jpg)
Use case to zachowanieContext
![Page 72: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/72.jpg)
Obiekty mają wstrzykiwane role
Interaction
![Page 73: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/73.jpg)
Role są dodawane runtime!
![Page 74: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/74.jpg)
class engine.invite_and_win.GameUseCase constructor: (@game, @player) -> ObjectHelper.addRole(@player, engine.shared.models.PlayerWithFriends)
tryToEnterGameArea: () => if @amIEnteringGameFirstTime() if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam(@facebookHQ.friendsInviting)
@teachPlayerHowToPlay()
else #n-th time... if @amICommingFromInvitation() @tellPlayerHeIsPartOfTeam(@facebookHQ.friendsInviting)
if not @playerLikesFanpage() @askPlayerToLikeFanpage()
if @haveNotYetPickedFavPizzaCountry() @askPlayerToDeclareHisFavCountry()
rola
![Page 75: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/75.jpg)
OOP != COP
![Page 76: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/76.jpg)
class engine.shared.models.PlayerWithFriends extends Mixin setup: => @friends = [] @invitedFriends = [] @acceptedFriends = []
setInvitedFriends: (facebookUids) => for facebookUid in facebookUids friend = new Friend({facebookUid: facebookUid}) @invitedFriends.push(friend)
setFriends: (friends) => @friends = friends
addFriend: (friend) => existing = @getFriendByFacebookUid(friend?.facebookUid) if not existing? @friends.push(friend)
![Page 77: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/77.jpg)
class engine.invite_and_win.GameGuiConfiguration constructor: (@gameUseCase, @game, @gui, @services, @sharedComponents) -> execute: () => Around(@gameUseCase, 'tryToEnterGameArea', @checkFbInvitation) After (@gameUseCase, 'tryToEnterGameArea', @showTeamArea) After (@gameUseCase, 'tryToEnterGameArea', @showButtonInviteOrPostPicture) Around(@gameUseCase, 'tellPlayerHeIsPartOfTeam', @showTeamPopup) Around(@gameUseCase, 'askPlayerToLikeFanpage', @showLikePopup) Around(@gameUseCase, 'teachPlayerHowToPlay', @showTutorialPopup) Around(@gameUseCase, 'playerWantsToKnowWinnersWithPrize', @showWinnersPopup) Around(@gameUseCase, 'playerWantsToKnowPrizes', @showPrizesPopup) Around(@gameUseCase, 'askPlayerToDeclareHisFavCountry', @showDeclareCountryPopup) Around(@gameUseCase, 'iAcceptMyFriendInvitationToATeam', @onIAcceptMyFriendInvitationToATeam)
![Page 78: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/78.jpg)
Around(@gameUseCase, 'tellPlayerHeIsPartOfTeam', @showTeamPopup)
![Page 79: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/79.jpg)
showTeamPopup: (proceed, friendsInviting) => data = {inviting_friends: friendsInviting} popup = @popupsComponent.showPopup('team_popup', data) popup.bind('popup:closed', => proceed(friendsInviting))
![Page 80: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/80.jpg)
Persistence
![Page 81: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/81.jpg)
ServerSide
![Page 82: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/82.jpg)
class engine.shared.server.ServerSide constructor: (@gameBasicDetails) -> @gameEngineUrl = "/engine/games/#{@gameBasicDetails.id}" @gameUrl = "/games/#{@gameBasicDetails.id}" @errors = []
gameDetailsLoaded: (gameDetails, callback) => callback(gameDetails)
fetchGameDetails: (callback, errback) => $.ajax( type: "GET" url: "#{@gameEngineUrl}.json" success: (gameDetails) => @gameDetailsLoaded(gameDetails, callback) error: errback )
![Page 83: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/83.jpg)
My ładujemy dane na starcie
![Page 84: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/84.jpg)
Można ładować w trakcie
![Page 85: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/85.jpg)
Testowanie
![Page 86: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/86.jpg)
![Page 87: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/87.jpg)
scenario "player enters and has no friends", -> @player.enterGame(@playerWithNoFriends) @player.shouldSeeMainAreaWithInviteButton() @player.shouldSeeRemainingFriendsToCompleteTeam(4)
scenario "player enters and has collected part team", -> @player.enterGame(@playerWith3AcceptedFriends) @player.shouldSeeMainAreaWithInviteButton() @player.shouldSeeRemainingFriendsToCompleteTeam(1)
scenario "player enters and has collected whole team", -> @player.enterGame(@playerWith4AcceptedFriends) @player.shouldSeeMainAreaWithPostToWallButton()
![Page 88: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/88.jpg)
TDD
![Page 89: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/89.jpg)
Acceptance tests
with test.ServerSide
![Page 90: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/90.jpg)
Reużycie?
![Page 91: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/91.jpg)
Jak reużyć kod po obu stronach?
![Page 92: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/92.jpg)
Nie wiem.
![Page 93: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/93.jpg)
Czy Google spozycjonuje SPA?
![Page 94: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/94.jpg)
Tak.Ale trzeba renderować
html po stronie serwera
![Page 95: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/95.jpg)
Frameworks
![Page 96: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/96.jpg)
My nie potrzebujemy
![Page 97: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/97.jpg)
Ty prawdopodobnie też nie potrzebujesz.
![Page 98: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/98.jpg)
Krytyka Backbone.js
![Page 99: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/99.jpg)
powiązanie danych z widokami
![Page 100: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/100.jpg)
a gdzie logika biznesowa?
![Page 101: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/101.jpg)
Backbone Models
![Page 102: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/102.jpg)
Przydatne do API, ale nie używajmy ich jako
dziedziny
![Page 103: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/103.jpg)
Relations/objects mismatch
![Page 104: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/104.jpg)
Resources/objects mismatch
![Page 105: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/105.jpg)
Libraries - yesFrameworks - no
![Page 106: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/106.jpg)
Bardzo ważne pytanie
![Page 107: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/107.jpg)
A może Twój projekt powinien być
SinglePageApp?
![Page 108: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/108.jpg)
Co jest lepsze dla użytkowników?
![Page 109: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/109.jpg)
tl;dr
• Frontend to osobna aplikacja
• Używaj CoffeeScript
• Nie używaj frameworków
• Pisz use case’y w kodzie
• Poczytaj o DCI
• Twórz fajne frontendy
![Page 110: Single Page Applications with CoffeeScript [Polish]](https://reader036.vdocument.in/reader036/viewer/2022081414/5550fa9ab4c9057b478b49f5/html5/thumbnails/110.jpg)
Dziękuję!@andrzejkrzywda
http://andrzejkrzywda.com
Pytania?
(ostatnio sporo bloguję o frontendach)