An application to display interactive slide presentations.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

316 lines
9.0 KiB

(presentation-data
:slides
(array
(slide-data :heading "Driving code with data" :body "Macoy Madson")
(slide-data :heading "Setting the stage" :trigger "show-ground")
(slide-data :heading "Setting the stage" :trigger "enter-wizard")
(slide-data :heading "Setting the stage" :trigger "enter-boar")
(slide-data :heading "Setting the stage"
:body "(Art by Pixel-boy)")
(slide-data :heading "First pass"
:is-code true
:body "if shouldShootFireball():
{
makeFireball();
}
for each fireball:
{
updateFireballs();
}")
(slide-data :heading "What about ice storms?"
:is-code true
:body "if shouldShootFireball():
{
makeFireball();
}
else if shouldShootIceStorm():
{
makeIceStorm();
}
for each fireball in fireballs:
{
updateFireball(fireball);
}
for each iceStorm in iceStorms:
{
updateIceStorm(iceStorm);
}")
(slide-data :heading "We want" :body "rock smash
magma ball
heat seeker
boomerang
...")
(slide-data :heading "We have a problem")
(slide-data :heading "Second pass: sharing code"
:is-code true
:body "for each projectile in projectiles:
updateProjectile(projectile);
function updateProjectile(projectile):
projectile.x += projectile.velocityX
if projectile.isFireball:
if projectile.x > 500:
projectile.velocityX = 5;
else if projectile.isIceStorm:
...")
(slide-data :heading "It works, but..."
:body "The code is a mess:
- Special cases everywhere
- No easy way to add new types or classes of things
- No clear centralization of functionality
- Complexity spreads: There is rarely only one place
where all behavior is kept!")
(slide-data :heading "What are computers good at?")
(slide-data :heading "What are computers good at?"
:body "Storing and manipulating data")
(slide-data :heading "Describe the behavior in data"
:is-code true
:body "struct Power
{
struct OnActivate
{
String makeParticle;
vec2 startVelocity;
} onActivate;
struct OnUpdate
{
MovementType movement;
vec2 acceleration;
} onUpdate;
struct OnEnemyHit
{
StatusEffect effect;
int magnitude;
} onEnemyHit;
}")
(slide-data :heading "Parameterized powers"
:is-code true
:body "Power fireball =
{
onActivate =
{
makeParticle = \"fireball\",
startVelocity = {5.f, 0.f},
},
onUpdate =
{
movement = MovementType_Projectile,
},
onEnemyHit =
{
effect = StatusEffect_Damage,
magnitude = 200,
},
}")
(slide-data :heading "We can now make variations"
:body "But all special new types need a programmer.
Lots of one-off booleans: doTheSpecialIceStormThing")
(slide-data :heading "Can we take the data approach
even further?")
(slide-data :heading "Generic \"operation\" structure"
:is-code true
:body "struct Operation
{
OperationType type;
String argumentA;
String argumentB;
}
enum OperationType
{
makeParticle,
setVelocityX,
setMovementType,
doCombatEffect,
}")
(slide-data :heading "Now we have more control"
:is-code true
:body "Power fireball =
{
onActivate =
{
{type = makeParticle, argumentA = \"fireball\",
{type = setVelocityX, argumentA = \"5\"},
},
onUpdate =
{
{type = setMovementType,
argumentA = \"MovementType_Projectile\"},
},
onEnemyHit =
{
{type = setVelocityX, argumentA = \"0\"},
{type = doCombatEffect,
argumentA = \"StatusEffect_Damage\",
argumentB = \"200\"},
},
}")
(slide-data :heading "Great, but we want more power!"
:body "Do X only if Y is true
Do X only sometimes, e.g. randomly")
(slide-data :heading "Our operations are data"
:body "What if operations change how they themselves are executed?")
(slide-data :heading "New operations"
:is-code true
:body "Label
GoToLabel
SetValue
IfValueEquals
Else
End
...")
(slide-data :heading "Operations now change control flow"
:is-code true
:body "for each operation, operationIndex in power.onUpdateOperations:
if operation.type == IfEquals:
if operation.argumentA != operation.argumentB:
operationIndex = findEndOperation()
else if operation.type == makeParticle:
makeParticle(operation.argumentA)
...")
(slide-data :heading "We can now make huge variations")
(slide-data :heading "But we hate writing these"
:body "{type = IfEquals, argumentA = \"positionX\", argumentB = \"500\"},
{type = setVelocityX, argumentA = \"5\"},
{type = Else},
{type = setVelocityX, argumentA = \"15\"},
{type = End}
...")
(slide-data :heading "But we hate writing these"
:body "All these {} and , are slowing us down")
(slide-data :heading "Let's imagine a better syntax"
:is-code true
:body "IfEquals positionX 500
setVelocityX 5
Else
setVelocityX 15
End")
(slide-data :heading "How should we implement this?"
:is-code true
:body "for each word in file:
if word == \"IfEqual\":
operations.append({IfEqual, ...});
else if word == \"MakeParticle\"
...")
(slide-data :heading "Looks familiar?"
:is-code true
:body "for each word in file:
if word == \"IfEqual\":
operations.append({IfEqual, ...});
else if word == \"MakeParticle\"
...
vs.
if projectile.isFireball:
if projectile.x > 500:
projectile.velocityX = 5;
else if projectile.isIceStorm:
...")
(slide-data :heading "We can do better!"
:is-code true
:body "struct OperationReader
{
String name;
OperationType type;
int numArguments;
}
OperationReader readers =
{{\"IfEquals\", IfEqual, 2},
{\"MakeParticle\", MakeParticle, 1},}
")
(slide-data :heading "Our parser is now data-driven"
:is-code true
:body "for each word, index in file:
for each reader in operationReaders:
if word == reader.name:
Operation operation;
operation.type = reader.type;
operation.arguments =
readArguments(reader.numArguments, file, &index)
function readArguments(numArguments, file, *wordIndex):
arguments = []
each in range(numArguments):
arguments.append(file[wordIndex])
wordIndex++")
(slide-data :heading "Our parser is now data-driven"
:body "This gives us several benefits:
- Easier to add new operations
(One line rather than copy-pasting if block)
- Easier to bake in per-operation validation
- Possible to enumerate all possible operations, which
makes autocomplete, help, typo suggestions possible")
(slide-data :heading "Now we're off to the races"
:trigger "power-cycle-display"
:is-code true)
(slide-data :heading "We just made a programming language!"
:body "That wasn't so hard, was it?")
(slide-data :heading "The spectrum of flexibility"
:body "Hard-coded
Configurable / parametric
Partially programmable
Fully programmable")
(slide-data :heading "There are risks with
full programmability"
:body "
- Need tools for debugging
- Less expressive power than native language
- Performance impact
- Spreading to problems it wasn't designed for
- Feature creep without language redesign
- Non-programmers doing programming")
(slide-data :heading "Questions to ask")
(slide-data :heading "Questions to ask" :body "Can I express this problem with data?")
(slide-data :heading "Questions to ask" :body "Can I express this problem with data?
Can I author that data in a better way?")
(slide-data :heading "Questions to ask" :body "Can I express this problem with data?
Can I author that data in a better way?
How do I expect the problem, data,
and feature to grow?")
(slide-data :heading "Questions to ask" :body "Can I express this problem with data?
Can I author that data in a better way?
How do I expect the problem, data,
and feature to grow?
How are they actually growing?")
(slide-data :heading "Questions to ask" :body "Can I express this problem with data?
Can I author that data in a better way?
How do I expect the problem, data,
and feature to grow?
How are they actually growing?
Am I building a complicated generic
system before knowing it is necessary?")
(slide-data :heading "In conclusion"
:body "Doing this is not hard,
knowing when to do this, and to what extent,
can be hard.")
(slide-data :heading "In conclusion"
:body "Doing this is not hard,
knowing when to do this, and to what extent,
can be hard.
That doesn't mean it shouldn't be done, but does
mean it should be done carefully.")
(slide-data :heading "Questions?"
:trigger "random-power-cycle"))