with great nerdery comes great responsibility

Post on 07-Jul-2015

375 Views

Category:

Internet

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Delivered at Pittsburgh Perl Workshop 2014.

TRANSCRIPT

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

https://github.com/genehack/klatsch

questions?

top related