With Great Nerdery Comes Great Responsibility
-
Upload
john-anderson -
Category
Internet
-
view
375 -
download
0
description
Transcript of With Great Nerdery Comes Great Responsibility
With Great Power Comes Great Responsibility
John SJ Anderson § @genehack PPW2014 § 2014-11-08
With Great Power Comes Great Responsibility
John SJ Anderson § @genehack PPW2014 § 2014-11-08
Nerdery
image: http://25.media.tumblr.com/tumblr_m69bglG75B1r72cw7o1_500.jpg
is there anybody in here that hasn't heard that? you're the product.
image: https://c1.staticflickr.com/7/6170/6185789175_41f41c843d_z.jpg
and i don't mean to just pick on Facebook here -- the "you're the product" business model is industry standard.
image: https://twitter.com/danlyke/status/529826711324876802
hell, even if you _are_ paying for a service, that doesn't stop the service owner from making you into the product
image: http://www.forbes.com/sites/kashmirhill/2014/10/28/att-says-its-testing-unkillable-tracker-on-customers-smartphones/
My name is John and this is my manifesto
i have feels.
many feels
image: http://www.hnldesign.nl/wp-content/uploads/2013/02/The-Manifesto-Manifesto.jpg
We're nerds. We can do better.
the people in this room have the ability to do things that not many people can do. we need to step up and do something about this.
We can do better for our friends and family too.
and we need to do it in such a way that we lift up the people we care about. we can't just make tools for ourselves, we have to make tools for normal people too.
Some recent exemplary efforts
not everything is bad news. there are other people that have started trying to do stuff about this too.
ftrain's tilde.club
screencap by speaker
brennen's squiggle.city
screencap by speaker
full of stuff that looks like this.
see, here's the thing -- the internet didn't use to be like this.
image: http://img1.wikia.nocookie.net/__cb20110515062056/simpsons/images/3/38/Abe.png
i got on the internet in 1989. i read usenet groups on a vt220 at the university of iowa. (before endless september!)
image: http://i.imgur.com/2MhE2.jpg
years later, in 1998, i started one of the first weblogs and was partof an incredibly active and vibrant community that was convinced -- at least some of us were convinced -- that what we were doing, sharing our thoughts and cross-linking things and snarking about politics -- was going to change everything.
left: http://www.theage.com.au/ffximage/2007/04/06/svBLOG_narrowweb__300x506,0.jpg
right: http://robiospeaks.files.wordpress.com/2010/06/peter-merholz.png
and we were right.
photo: stevan little
except for the comments. i apologize for the whole commenting thing, in retrospect it was a really bad idea.
image: https://img0.etsystatic.com/011/0/7887463/il_fullxfull.438911204_gfot.jpg
so enough "good old days" nonsense. i pointed out some people that were trying to do something about this -- what am _i_ trying to do?
image: no idea. i am a bad person and i feel bad.
there are a number of things i have on my todo list for 2015: moving away from google, replacing "free" services with services i pay for, or even better, write myself.
image: https://i.imgflip.com/bjr2p.jpg
but for this talk, i want to focus on twitter.
image:http://edudemic.com/wp-content/uploads/2013/04/twitter1.gif
I ❤️ Twitter.
i really like twitter-the-service. i'm on twitter a _lot_. twitter has helped me hire people, it's been essential in making friends after i moved across the country a couple years ago, and it's how i keep up with the vast majority of my friends.
I ❤️ Twitter.⃠i'm not quite as big a fan of twitter-the-company. they don't seem to have a great idea of what direction they're going in, and their attempts at monetization and attracting new users have me increasingly concerned for the future of twitter-the-service.
Thinking about solutions. Or even just mitigations.
Options. Escape hatches.
so i'm thinking about ways to solve those problems, or even just reduce them. thinking about where i could go, if it came down to that. thinking about what would be in my "go bag".
Inspiration.
one of the best benefits of my job is getting to hang out with people that make me want to do better.
http://micro.sartak.org/
• Archive
• Search
• Potential Escape Hatch
great, because it does the stuff that shawn wanted it to do.
doesn't do everything i want though.
So I started writing Klatsch.
• Archive
• Search
• Potential Escape Hatch
• Feed reading / management
• Posting (micro- and macro-blogging)
• RSS reader
• Hub for online social activity in general
• Archive
• Search
• Potential Escape Hatch
• Whole Feed
• Posting (micro- and macro-blogging)
• RSS reader
• Hub for online social activity in general
Note: almost all
currently aspirational...
Most importantly: Easy deployment.
I want other people to be able to run their own copies of this software too. Centralization of this sort of thing provides an incentive towards silo-a-zation, and that's the beginning of the bad times.
Which, yes, means:
Not Perl
Perl deployments are horrible.
#sorry
#sorrynotsorry
Best deployment story around, currently:
Go.
Go (aka golang)
• Statically typed (w/inference)
• Compiled (cross-platform)
• C-like syntax & design
• Garbage collected
• Excellent concurrency support
• Interesting approach to OO
But, most importantly:
Statically-linked. Binaries.
Deployment == trivial.
package main
import "fmt"
func main() { fmt.Print("Hello world") }
this is hello world in go.
% ls -‐sh hello 1.8M hello*
static linking == big binaries
but it doesn't matter.
image: http://www.quickmeme.com/img/3b/3b0241c9f06118600eaa2271ac5a0e11c619bc72a2a547d6883c8f62a2dc7a58.jpg
So... Klatsch.
package main
import ( "fmt" "github.com/spf13/cobra" )
func main() { var cmdFetch = &cobra.Command{ Use: "fetch", Short: "fetch", Long: "long fetch", Run: fetch, } var Force bool cmdFetch.PersistentFlags().BoolVarP(&Force, "force", "F", false, "build HTML page even if nothing has changed")
var cmdImportTweets = &cobra.Command{ Use: "import_tweets", Short: "import", Long: "long import", Run: func(cmd *cobra.Command, args []string) { fmt.Println("import_tweets not implemented yet.") }, }
...
var rootCmd = &cobra.Command{Use: "klatsch"} rootCmd.AddCommand(cmdFetch, cmdImportTweets, cmdInit, cmdSearch, cmdServer) rootCmd.Execute() }
import ( ...
"github.com/ChimeraCoder/anaconda" "github.com/spf13/cobra" )
func fetch(cmd *cobra.Command, args []string) { var force bool = false if cmd.Flag("force").Value.String() == "true" { force = true }
exitUnlessDatabaseExists()
db := getDatabaseHandle() defer db.Close()
twitter := getTwitterApiHandle(db)
v := url.Values{"count": {"200"}} timeline, err := twitter.GetUserTimeline(v) if err != nil { log.Fatal(err) }
inserted, err := saveTimeline(db, timeline) if err != nil { log.Fatal(err) }
if force || inserted > 0 { if err = writeOutTimeline(db); err != nil { log.Fatal(err) } } }
import ( ...
"github.com/ChimeraCoder/anaconda" "github.com/spf13/cobra" )
func fetch(cmd *cobra.Command, args []string) { var force bool = false if cmd.Flag("force").Value.String() == "true" { force = true }
exitUnlessDatabaseExists()
db := getDatabaseHandle() defer db.Close()
twitter := getTwitterApiHandle(db)
v := url.Values{"count": {"200"}} timeline, err := twitter.GetUserTimeline(v) if err != nil { log.Fatal(err) }
inserted, err := saveTimeline(db, timeline) if err != nil { log.Fatal(err) }
if force || inserted > 0 { if err = writeOutTimeline(db); err != nil { log.Fatal(err) } } }
You can take the boy out of Perl...
import ( ...
"github.com/ChimeraCoder/anaconda" "github.com/spf13/cobra" )
func fetch(cmd *cobra.Command, args []string) { var force bool = false if cmd.Flag("force").Value.String() == "true" { force = true }
exitUnlessDatabaseExists()
db := getDatabaseHandle() defer db.Close()
twitter := getTwitterApiHandle(db)
v := url.Values{"count": {"200"}} timeline, err := twitter.GetUserTimeline(v) if err != nil { log.Fatal(err) }
inserted, err := saveTimeline(db, timeline) if err != nil { log.Fatal(err) }
if force || inserted > 0 { if err = writeOutTimeline(db); err != nil { log.Fatal(err) } } }
Live demo!
Live demo! (safest live demo evar.)
<!DOCTYPE html> <html lang="en" data-‐ng-‐app="klatsch"> <head> <meta charset="utf-‐8"> <title>Klatsch!</title>
<link href="css/bootstrap.min.css" rel="stylesheet"> <link href="css/klatsch.css" rel="stylesheet"> </head> <body> <div class="container"> <div class="col-‐md-‐3"></div> <div class="col-‐md-‐6"> <h1>Postin'</h1>
<twitter-‐input></twitter-‐input>
</div> <div class="col-‐md-‐3"></div> </div>
<div class="footer"> <div class="container"> <p class="text-‐muted">Powered by Klatsch!</p> </div> </div>
<script src="http://code.angularjs.org/1.2.26/angular.min.js"></script> <script src="js/directives.js"></script> </body> </html>
<!DOCTYPE html> <html lang="en" data-‐ng-‐app="klatsch"> <head> <meta charset="utf-‐8"> <title>Klatsch!</title>
<link href="css/bootstrap.min.css" rel="stylesheet"> <link href="css/klatsch.css" rel="stylesheet"> </head> <body> <div class="container"> <div class="col-‐md-‐3"></div> <div class="col-‐md-‐6"> <h1>Postin'</h1>
<twitter-‐input></twitter-‐input>
</div> <div class="col-‐md-‐3"></div> </div>
<div class="footer"> <div class="container"> <p class="text-‐muted">Powered by Klatsch!</p> </div> </div>
<script src="http://code.angularjs.org/1.2.26/angular.min.js"></script> <script src="js/directives.js"></script> </body> </html>
directive("twitterInput", function () { return { restrict: "E" , replace: true , templateUrl: "./twitter_input.html" , controller: function($scope,$timeout) { $scope.error = function(name) { var form = $scope.form[name]; return form.$invalid && form.$dirty ? "has-‐error" : ""; }; }, scope: {} }; })
<form name="form" role="form"> <div class="form-‐group" data-‐ng-‐class="error('postfield')"> <div class="controls"> <input type="text" name="postfield" class="form-‐control" data-‐ng-‐trim=false counted-‐max="140" data-‐ng-‐model="post.content" placeholder="Compose new tweet" /> </div>
<div class="pull-‐right" style="margin:5px 0;"> <span class="help-‐block inline-‐display" data-‐ng-‐show="form.postfield.$error.unique"> Post is too long! </span> <span class="count" style="margin-‐right:5px" data-‐ng-‐class="error('postfield')"> {{140 -‐ post.content.length}} </span> <button class="btn btn-‐primary" data-‐ng-‐click="postToTwitter(account)" data-‐ng-‐disabled="!form.$valid"> Post to Twitter </button> </div> </div> </form>
.directive("countedMax", function() { return { require: "ngModel" , restrict: "A" , link: function(scope,element,attrs,ngModelCtrl) { var maxlength = Number(attrs.countedMax); function fromUser(text) { ngModelCtrl.$setValidity( 'unique', text.length <= maxlength ); return text; } ngModelCtrl.$parsers.unshift(fromUser); } }; })
Live demo 2: search
So that's what I'm trying to do about it.
what can _you_ do about it?
image: http://memestorage.com/_nw/21/04359364.jpg
Just use the app and give me feedback.once it's ready, I mean.
image: http://memestorage.com/_nw/21/04359364.jpg
http://www.poststat.us/wp-content/uploads/2013/12/patches-welcome-752x361.jpg
Or write your own tool!
(and then we can figure out how to make them work
together!)
http://treasure.diylol.com/uploads/post/image/399053/resized_jesus-says-meme-generator-jesus-says-do-it-yourself-ffe55f.jpg
Reminder.
http://lesquestionscomposent.fr/wp-content/uploads/2013/03/23353915.jpg
https://github.com/genehack/klatsch