«На самом деле хакинг — это просто способ сделать что-то быстро или проверить границы того, что может быть сделано. Как и многое другое, его можно использовать во благо и во вред, но подавляющее большинство хакеров, которых я встречал, — идеалисты, желающие оставить положительный след в мире.»
— Марк Цукерберг, «Путь Хакера»

imageСегодня день рождения Марка Цукерберга (14 мая 1984). Каким он был программистом?

  • В 11 лет написал «домашний мессенджер» ZuckNet, чтоб не бегать по дому, а посылать сообщения родным через компьютер.
  • В старших классах написал Synapse Media Player — прообраз Last.fm. Алгоритм понимал музыкальные предпочтения пользователей Winamp. Microsoft and AOL предложили выкупить программу и устроиться к ним на работу. Но Марк выложил ее в свободный доступ.
  • CourseMatch помогал студентам Гарварда выбрать курсы. Он отображал сколько студентов уже записались на курсы, а так же показывал, на какие курсы записался конкретный студент.
  • FaceMash — «пузырьковая сортировка» людей по привлекательности. Он показывал 2 фотки и предлагал выбрать более симпатичную. Хабраэффект от этого сервиса обрушил сетку Гарварда. Марку выкатили выговор за то, что он использовал фотки людей без их согласия.


«Если ты ничего не разрушаешь, ты, вероятно, растешь не слишком быстро.»
— Марк Цукерберг

Под катом — «исходный код» раннего Фейсбука, письмо Марка инвесторам «Путь хакера», парочка скриншотов и видосы его лекций в Росссии.


image
В школьные годы занимался компьютерным программированием, разработал сетевую версию игры «Риск».

image
Synapse Media Player

image
«Вовочка, встань и выйди»

image
THEfacebook

Was this written by Mark Z.?
#!/usr/bin/perl



use Mysql;
use strict;
use vars qw($school_name);
use vars qw($pass);

require "./cgi-lib.pl";
#do "./school_name.pl";
do "../password.pl";

my (%input, $text, $field);
&ReadParse(\%input);

my @rawCookies = split (/; /,$ENV{'HTTP_COOKIE'});
my %cookies;

foreach(@rawCookies){
    my ($key, $val) = split (/=/,$_);
    $cookies{$key} = $val;
} 

my $id = $input{id};
my $user = $input{user};
my $code = $input{code};
my $course = 0;#$input{course};
my @node;
my @edge;
#my $db_data = Mysql->connect("69.28.179.12", "login", "mark", $pass);
my $db_data = Mysql->connect("$cookies{host}", "$cookies{db}", "mark", $pass);
my $map;
if ($ENV{'HTTP_HOST'} =~ m/^(.*)\.thefacebook\.com/) {
    $map = $1;
}
my $cookie_host = $cookies{host};
my $cookie_db = $cookies{db};
my $sql = "SELECT * FROM school_data where map='$map'";
my $retval = $db_data->query($sql);
my %rs = $retval->fetchhash();
my $host = $rs{ip};
my $dbname = $rs{db};
#my $sql = "INSERT INTO viz (user,map,host,db) VALUES ('$user', '$map','$host', '$dbname')";
#$db_data->query($sql);
my $db = Mysql->connect($host, $dbname, "mark", $pass);
#my $db = Mysql->connect("69.28.179.11", "facebook", "mark", $pass);
my $retval; my $sql;
my %privacy;
my $num_degrees = 1;
my @already_expanded;
my %cs;
     
sub morph {
  my ($number) = @_;
  return ((((($number % 7) * 13) % 17) * 19) % 23);
}

sub share_course {
  my ($user1, $user2) = @_;
  $sql = "SELECT count(*) as count FROM course as course1, course as course2 WHERE " .
    "course1.id = '$user1' AND course2.id = '$user2' AND course1.course_id = course2.course_id";
  $retval = $db->query($sql);
  my %rs = $retval->fetchhash();
  return $rs{count};
}

sub is_one_degree {
  my ($user1, $user2) = @_;
  $sql = "SELECT count(*) as count FROM friend WHERE user1 = '$user1' AND user2 = '$user2'";
  $retval = $db->query($sql);
  my %rs = $retval->fetchhash();
  return $rs{count};
}

sub is_two_degrees {
  #my ($user1, $user2) = @_;
  #$sql = "SELECT count(*) as count FROM friend as f1, friend as f2 " .
  #  "WHERE f1.user1 = '$user1' AND f1.user2 = f2.user1 AND f2.user2 = '$user2'";
  #my %rs = $retval->fetchhash();
  #return $rs{count};
  return 0;
}

sub is_three_degrees {
  #my ($user1, $user2) = @_;
  return 0;
}

sub can_see {
  my ($user, $id, $type) = @_;
  if ($user eq $id) { return 1; }
  $sql = "SELECT house, year, " . $type . "_domain, " . $type . "_type, " .
         $type . "_allow FROM info WHERE info.id = '$id'";
  $retval = $db->query($sql);
  my %control = $retval->fetchhash();
  my $allow = $control{$type . '_allow'};
  my $domain = $control{$type . '_domain'};
  my $privacy_type = $privacy{$type};
  if (($domain eq "" or ($privacy{email} =~ m/$domain$/)) and
      ($control{$type . '_type'} =~ m/-$privacy_type/)) {
    if ($allow =~ m/-1/) {
      $cs{$id} = 1;
      return 1;
    } elsif (($allow =~ m/-2/) and $privacy{year} eq $control{year}) {
      $cs{$id} = 1;
      return 1;
    } elsif (($allow =~ m/-3/) and $privacy{house} eq $control{house}) {
      $cs{$id} = 1;
      return 1;
    } elsif (($allow =~ m/-4/) and share_course($user, $id)) {
      $cs{$id} = 1;
      return 1;
    } elsif (($allow =~ m/-5/) and is_one_degree($user, $id)) {
      $cs{$id} = 1;
      return 1;
    } elsif (($allow =~ m/-6/) and is_two_degrees($user, $id)) {
      $cs{$id} = 1;
      return 1;
    } elsif (($allow =~ m/-7/) and is_three_degrees($user, $id)) {
      $cs{$id} = 1;
      return 1;
    }
  }
  return 0;
}

sub find_node {
  my ($id, $type) = @_;
  for (my $i = 0; $i < @node; $i++) {
    if ($node[$i]{id} eq $id and $node[$i]{type} eq $type) {
      return $i;
    }
  }
  return -1;
}
      
sub find_connections {
  my ($this, $degree, $is_course) = @_;
  my ($type, $type_id);
  if (!$is_course) {
    $already_expanded[@already_expanded] = $this;
    $sql = "SELECT * FROM friend WHERE user1 = '$this' LIMIT 0, 200";
    $type = "friend";
    $type_id = 1;
  } else {
    $sql = "SELECT * FROM course WHERE course_id = '$this'";
    $type = "course";
    $type_id = 0;
  }
  my $return = $db->query($sql);
  while (my %row = $return->fetchhash()) {
    my $new_id;
    if (!$is_course) {
      # get the new id from the friend pair
      #if ($row{user1} eq $this) {
      #  $new_id = $row{user2};
      #} else {
      #  $new_id = $row{user1};
      #}
      $new_id = $row{user2};
    } else {
      $new_id = $row{id};
    }
    if ($degree > $num_degrees or $cs{$new_id} or can_see($user, $new_id, $type)) {
      # see if the id is already a node; if not, add it
      my $node_exists = 0;
      for (my $i = 0; $i < @node and !$node_exists; $i++) {
        if ($node[$i]{id} eq $new_id and $node[$i]{type} eq 1) {
          $node_exists = 1;
        }
      }
      if (!$node_exists and $degree <= $num_degrees) {
        my $next_node = @node;
        $node[$next_node]{id} = $new_id;
        $node[$next_node]{type} = 1;
      }
      # see if there's an edge between the two already; if not, add it
      if ($node_exists or $degree <= $num_degrees) {
        my $edge_exists = 0;
        my $this_index = find_node ($this, $type_id);
        my $new_index = find_node ($new_id, 1);
        for (my $i = 0; $i < @edge and !$edge_exists; $i++) {
          if (($edge[$i][0] eq $this_index and $edge[$i][1] eq $new_index) or
              ($edge[$i][0] eq $new_index and $edge[$i][1] eq $this_index)) {
            $edge_exists = 1;
          }
        }
        if (!$edge_exists) {
          my $next_edge = @edge;
          $edge[$next_edge][0] = $this_index;
          $edge[$next_edge][1] = $new_index;
        }
      }
      # if we want to consider friends farther out, do so now
      if ($degree < $num_degrees + 1) {
        my $expansion_exists = 0;
        for (my $i = 0; $i < @already_expanded and !$expansion_exists; $i++) {
          if ($already_expanded[$i] eq $new_id) {
            $expansion_exists = 1;
          }
        }
        if (!$expansion_exists) {
          if (!$is_course or can_see ($user, $new_id, "friend")) {
            find_connections ($new_id, $degree + 1, 0);
          }
        }
      }
    }
  }
}

sub identify_nodes {
  for (my $i = 0; $i < @node; $i++) {
    if ($node[$i]{type}) {
      $sql = "SELECT name FROM info WHERE id = '" . $node[$i]{id} . "'";
    } else {
      $sql = "SELECT name FROM course_list WHERE id = '" . $node[$i]{id} . "'";
    }
    $retval = $db->query($sql);
    my %row = $retval->fetchhash();
    $node[$i]{name} = $row{name};
  }
}

if ($code == &morph($user) and &can_see($user, $id, "friend")) {  
  # figure out what's going into the graph
  $sql = "SELECT email, house, year FROM info WHERE info.id = '$user'";
  $retval = $db->query($sql);
  %privacy = $retval->fetchhash();
  $node[0]{id} = $id;
  if ($course) {
    $node[0]{type} = 0;
  } else {
    $node[0]{type} = 1;
  }
  find_connections ($id, 1, $course);
  identify_nodes ();
  # generate the graph file
  my $o;
  my $outfile = "/tmp/thefacebook-$id-graph-" . time();
  open  $o, "> $outfile";
  # headers
  print $o "graph g {\n";
  print $o "start=\"yes\"\n";
  print $o "size=\"20,20\"\n";
  print $o "page=\"20,20\"\n";
  print $o "maxiter=1000\n";
  print $o "resolution=100\n";
  print $o "center=true\n";
  print $o "bgcolor=white\n";
  print $o "title=\"A Graph\"\n";
  # nodes                           
  print $o "node [shape=box,fontname=\"Tahoma\",style=filled]\n";
  for (my $i = 0; $i < @node; $i++) {
    my $name = $node[$i]{name};
    $name =~ s/[^A-Z0-9'. ]//gi;
    my ($red, $green, $blue);
    do {
      $red = int(rand() * 201);
      $green = int(rand() * 201);
      $blue = int(rand() * 56) + 200;
    } while ($red + $green + $blue < 400);
    my $extra = "";
    if ($i eq 0) {
      $extra = ",fontsize=32,label=\"$name\"";
    } else {
      $extra = ",fontsize=24,label=\"$name\"";
    }
    printf $o "n$i [color=\"#%02x%02x%02x\"$extra]\n", $red, $green, $blue;
  }
  # edges
  print $o "edge [len=8,color=\"#555555\"]\n";
  for (my $i = 0; $i < @edge; $i++) {
    my $name1 = $node[$edge[$i][0]]{name};
    my $name2 = $node[$edge[$i][1]]{name};
    print $o "n$edge[$i][0] -- n$edge[$i][1] [dir=both,weight=1]\n";
    #print $o "$name1 -- $name2 [dir=both,weight=1]\n";
  }
  # footer
  print $o "}\n\n";
  # compile the graph and output
  my $cmd = "nice neato -Tsvgz $outfile|";
  print "Content-Encoding: gzip\n";
  print "Content-Type: image/svg+xml\n\n";
  #print "Content-Type: text/html\n\n";
  my $file;
  my $pid = open ($file, $cmd);
  while (my $line = <$file>) {
    print $line;
  }
  close $o;
  unlink $outfile;
  #print "what is up..\n";
} else {
  print &PrintHeader;
  print "Authentication failed.  Return <a href='http://";
  print $school_name;
  print ".thefacebook.com/home.php'>home</a>.\n";
}

#print "end...\n";



Источник


Путь хакера
Взято отсюда.

Из письма Марка Цукерберга будущим акционерам Facebook



Facebook не создавался для того, чтобы быть компанией. Facebook создавался для того, чтобы выполнять социальную миссию: сделать мир более связанным и открытым. Нам кажется важным, чтобы каждый, кто инвестирует в Facebook, понимал, что эта миссия для нас означает, как мы принимаем решения и почему мы делаем то, что делаем. Я попытаюсь описать наш подход в этом письме.

Мы вдохновляемся технологиями, которые изменили потребление и распространение людьми информации. Мы часто говорим об изобретениях вроде печатного станка и телевидения: просто облегчив коммуникацию, они привели к полной трансформации важных частей общества. Они дали многим людям голос. Они вдохновляли прогресс. Они изменили принципы организации человеческого сообщества. Они сделали нас ближе друг к другу.

Сегодня общество достигло новой переломной точки. Большинство людей в мире имеют доступ к интернету или мобильным телефонам — новым инструментам, позволяющим делиться своими мыслями, чувствами и действиями с кем только захочется. Facebook надеется построить сервисы, которые дадут людям возможность делиться [друг с другом] и помогут им снова трансформировать многие ключевые отрасли и общественные институты.

Существует огромная потребность и удивительная возможность связать всех в мире между собой, дать каждому голос и трансформировать общество для будущего. Масштаб технологий и инфраструктуры, которые для этого понадобится создать, не имеет прецедентов, и мы верим, что это самая важная проблема, на которой мы должны сфокусироваться.

Наша миссия и наш бизнес



Как я уже говорил, Facebook создавался не для того, чтобы быть компанией. Мы всегда заботились в первую очередь о своей общественной миссии, о своих сервисах и людях, которые ими пользуются. Это не самый обычный подход для публичной компании, так что я хочу объяснить, почему, с моей точки зрения, он оправдан.

Когда я писал первую версию Facebook, я делал это сам, потому что мне хотелось, чтобы он был. С тех пор большая часть идей — и программного кода — были созданы лучшими людьми, которых мы привлекли в свою команду.

Лучшие люди беспокоятся в первую очередь о том, чтобы делать большие проекты и хотят быть частью больших проектов, но они также хотят зарабатывать деньги. В процессе создания команды — а также сообщества разработчиков, рекламодателей и инвесторов — я осознал, что строительство сильной компании с сильной экономикой и быстрым ростом может быть самым удачным способом объединения многих людей для решения важных проблем.

Попросту говоря, мы не создаем сервисы, чтобы зарабатывать деньги, мы зарабатываем деньги для того, чтобы создавать лучшие сервисы.
С нашей точки зрения это хороший способ что-нибудь сделать. Сейчас я думаю, что все больше людей хотят пользоваться услугами компаний, верящих во что-то большее, чем максимизация прибылей.

Мы считаем, что, фокусируясь на своей миссии и создавая отличные сервисы, мы создадим для наших инвесторов больше стоимости в длительной перспективе. А это, в свою очередь, позволит нам и дальше привлекать лучших людей и создавать отличные сервисы. Мы не просыпаемся по утрам, думая о том, где бы добыть деньжат, но понимаем, что лучший способ выполнить свою миссию — это построить сильную и дорогую компанию.

Вот так же мы думаем и про наше IPO. Мы становимся публичной компанией ради наших сотрудников и наших инвесторов. Давая им долю в компании, мы обещали, что она будет дорого стоить и станет ликвидной, и наше IPO — подтверждение этого обещания. Становясь публичной компанией, мы обещаем то же и нашим новым инвесторам и будем работать изо всех сил, чтобы снова выполнить это обещание.

Путь хакера



Создавая сильную компанию, мы много работаем над тем, чтобы сделать Facebook лучшим местом, где лучшие люди могли бы менять мир и учиться у лучших. Мы создали уникальную культуру и систему управления, которую мы называем «путь хакера».

Слово «хакер» имеет — несправедливо — негативные коннотации. Хакеров изображают в медиа людьми, которые взламывают компьютеры. На самом деле хакинг — это просто способ сделать что-то быстро или проверить границы того, что может быть сделано. Как и многое другое, его можно использовать во благо и во вред, но подавляющее большинство хакеров, которых я встречал, — идеалисты, желающие оставить положительный след в мире.

«Путь хакера» — это подход к созиданию, который включает постоянные улучшения и повторы. Хакеры верят, что все можно улучшить и ничто не может быть совершенным. Надо всего лишь исправить — часто вопреки воле людей, которые говорят, что это невозможно, и довольны статус-кво.
Хакеры стараются строить лучшие сервисы, выпуская частые релизы и обучаясь на небольших итерациях, вместо того чтобы постараться сделать все правильно с первого раза. Чтобы поддержать этот подход, мы построили тестовую среду, способную в каждый момент времени испытывать тысячи версий Facebook. На стенах нашего офиса написаны слова, призванные постоянно подгонять нас: Done is better than perfect.

Хакинг по своей природе активная и практическая работа. Вместо того чтобы днями спорить о возможностях или способах реализации новой идеи, хакеры просто сделают прототип и посмотрят, что работает, а что нет. В стенах Facebook вы часто можете услышать мантру хакера: [программный] код выигрывает споры.

Хакерская культура исключительно открыта и меритократична. Хакеры верят, что выигрывать должна лучшая идея и ее лучшее исполнение, а не люди, которые лучше болтают или имеют больше подчиненных.

Поощряя этот подход, каждые несколько месяцев мы проводим «хакатлон», во время которого каждый строит прототипы своих новых проектов. В конце вся команда собирается вместе и смотрит, что получилось. Многие наши успешные продукты появились таким образом, включая Timeline, чат, видео, среду мобильной разработки и некоторые важнейшие инфраструктурные разработки.

Чтобы увериться, что все наши программисты разделяют наш подход, мы заставляем всех новичков — даже менеджеров, которые не будут программировать, — пройти через программу Bootcamp, где они изучают нашу программную среду, наши инструменты и наш взгляд на мир. В индустрии есть много людей, которые хотят управлять программистами, но не хотят писать код, но те люди, которых мы ищем, хотят и могут пройти через Bootcamp.

Приведенные выше примеры адресованы программистам, но из этих принципов мы выделили пять ценностей, ключевых для развития Facebook:

Фокусироваться на результате. Если мы хотим добиться высокого результата, то всегда должны быть уверены, что концентрируемся на решении самых важных проблем. Звучит просто, но многие компании, как нам кажется, плохо с этим справляются и теряют кучу времени. Мы надеемся, что каждый сотрудник Facebook умеет находить самые важные проблемы и решать их.

Быстро развиваться. Быстрый рост позволяет нам делать больше и учиться быстрее. Большинство компаний замедляются по мере роста, потому что они больше боятся сделать ошибку, чем упустить хорошую возможность из-за своей медлительности. У нас есть присказка: «Двигайся быстро и разрушай». Идея в том, что если ты ничего не разрушаешь, ты, вероятно, растешь не слишком быстро.

Быть смелым. Нельзя сделать больших проектов, не рискуя. Страх перед риском мешает большинству компаний совершить смелые поступки, которые следовало бы совершить. Но в мире, который меняется с такой скоростью, отказ от риска просто гарантирует неудачу. У нас есть присказка и на эту тему: «Самый большой риск — не идти на риск». Мы поощряем принятие смелых решений, даже если иногда это значит, что приходится ошибаться.

Быть открытым. Мы верим, что открытый мир лучше, потому что хорошо информированные люди принимают лучшие решения и успевают сделать больше. Это относится и к управлению нашей компанией. Мы много работаем над тем, чтобы каждый в Facebook имел доступ ко всей возможной информации, чтобы принять наиболее правильные решения и достичь высокого результата.

Создавать социальный капитал. Еще раз: Facebook существует для того, чтобы сделать мир более связанным и открытым, а не просто как компания для зарабатывания денег. Мы ожидаем, что каждый сотрудник Facebook сфокусирован на том, как принести больше реальной пользы для мира каждым своим действием.

Оригинал письма на английском языке


Комментарии (0)