понедельник, января 05, 2015

Как повысить эффективность разработки — советы программистам. Мои дополнения



К недавней статье "Как повысить эффективность разработки — советы программистам" на siliconrus я бы добавил свои подходы, хотя статья и так хороша.
Часто бывает не сложно сосредоточится, а сложно начать что-то делать, поэтому я использую следующее:

  1. Начать что-то писать в текстовый редактор:
    неважно что вы пишите, главное начать, это может быть todo список дел на сегодня или просто пост в блог, как правило к моменту когда вы закончите вы уже будет полны запала что-то сделать;
  2. Выполнить задание:
    это может быть просто разминка для мозга, вспомнить алгоритм сортировки пузырьком, реализовать свою версию hashmap и т.д. Также попробуйте выполнить одно из заданий на codecademy, или пройдите тесты здесь;
  3. просто посидеть 5-10 минут:
    не поверите, но это работает, это сродни медитации и заставляет упорядочить все в голове
Удачи! Напишите, что помогает вам.

среда, декабря 24, 2014

Полезные заметки javascript разработчика - 1

Работа в большой команде с git требует усложнения процесса, есть отличная статья об Удачной модели ветвления в git
Я уже ранее писал об основах работы в git
Не давно потребовалось перименовать текст последнего коммита, вот решение:
git commit --amend [-m 'new text'] - откроется редактор и вы сможете исправить текст.
git push [origin master]
Здесь подробнее.

В последнее время приходится много работать с mongo, и при миграции данных, когда не понятно, что творится в бд (как вы знаете mongo это документо-ориентированная бд, в которой можно хранить документы с разной структурой в одной коллекции/таблице). Потребовалось понять какие существуют поля в документах, и конечно нашлась статья в stackoverflow
Для это в консоли mongo создадим дополнительные коллекции
mr = db.runCommand({
  "mapreduce" : "my_collection",
  "map" : function() {
    for (var key in this) { emit(key, null); }
  },
  "reduce" : function(key, stuff) { return null; }, 
  "out": "my_collection" + "_keys"
})
Получить результат:
db[mr.result].distinct("_id")


Функция Array.some будет очень полезна для поиска в массиве элементов соответствующих условию
Пример использования:
function isBigEnough(element, index, array) {
  return element >= 10;
}
var passed = [2, 5, 8, 1, 4].some(isBigEnough);
// passed равен false
passed = [12, 5, 8, 1, 4].some(isBigEnough);
// passed равен true
Самое приятное, что функция пробегает не по всему массиву, а до первого совпадения, это можно проверить добавив счетчик в isBigEnough. Это работает на последней node (0.10) и в вашем любимом современном браузере.

среда, августа 01, 2012

Нет сети в эмуляторе Android

Бывает странный глюк в эмуляторе android. Допустим в моей домашней сети в эмуляторе нет интернета ни в приложении ни в браузере. Для решения этой проблемы попробуйте явно указать dns сервер.
./emulator.exe -avd android-emulator-name -dns-server 192.168.0.1
Все же если у вас есть интернет в браузере эмулятора, но нет в приложении. То проверьте permission в AndroidManifest.xml.
Еще более полная статья (на англ.) 

Изменения в политике Google Play для разработчиков

Все мы знаем насколько лояльно Google относится к приложениям в своём магазине. Идеальный алгоритм модерации, который устраивал и пользователей и разработчиков, ещё не придумал никто. Но Google движется в этом направлении.
Сегодня (01.08.2012) прислал письмо разработчикам о новой политике, вот краткий список нововведений:

  • введены четкие детали политики платежей и правил того как будут обрабатываться отмены в новой функции подписки биллинга (детали надо искать в личном кабинете разработчика)
  • ограничение на  использование названий или иконок похожих на системные приложения в целях снижения запутанности пользователей
  • новые правила о  видах опасных продуктов, которые не допускаются на Play Google, например, приложения, которые раскрывают личную информацию без разрешения не допускается  (детали необходимо поискать)
  • даны больше примеров нарушений политики спама (детали необходимо поискать)
  • новые правила рекламы,  реклама должна следовать тем же правилам , что и само приложение, реклама не должна обманывать, вести себя агрессивно или блокировать другую рекламу (детали необходимо поискать)
  • новые приложения или обновления старых сразу подвергнуться действию новой политики, если в существующем приложении будут найдены нарушения то в течени 30 дней их необходимо устранить иначе оно может быть удалено из каталога
Как мне кажется это должно благотворно сказать на всей экосистеме Android.

Ссылка на полный текст новой политики (на англ.).

вторник, февраля 07, 2012

Ошибки Eclipse и Android SDK

Я разрабатываю под ubuntu (на момент публикации 11.04).
Eclipse SDK Version: 3.7.1 Build id: M20110909-1335
$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) Server VM (build 20.1-b02, mixed mode)

При очередном старте проекта наткнулся на ошибку
parsesdkcontent failed android

проекты собирались, т.к. sdk не был загружен. Я попытался переустановить все с начала - не помогло. Попробовал обновить sdk через файл ./sdk/tools/android (Android SDK Manager), стали появляться следующие ошибки:
Failed to fetch URL http://dl-ssl.google.com/android/repository/addons_list-1.xml, reason: Failure initializing default SSL context
но файл по адресу открывается. Покопавшись в интернетах обнаружил вот это обсуждение.
Там сказано, что следует удалить gcj, позже я вспомнил, что недавно устанавливал этот пакет.
sudo apt-get remove gcj-*
Далее при попытке сборки в консоли эклипса появляется следующее
Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead. Please use Android Tools > Fix Project Properties.
Должно лечиться этими инструкциями, а именно Project properties -> Android Tools -> Fix Project Properties
Мне не помогло. Я попробовал перейти на openjdk.

sudo apt-get remove sun-java6-*
ubuntu сразу предложил поставить пакеты на замену

ca-certificates-java default-jre default-jre-headless icedtea-6-jre-cacao icedtea-6-jre-jamvm icedtea-netx libaccess-bridge-java libaccess-bridge-java-jni openjdk-6-jre openjdk-6-jre-headless openjdk-6-jre-lib tzdata-java

добавил путь /usr/lib/jvm/java-6-openjdk/jre/bin/ в bash_profile чтобы запускался eclipse

$ vim ~/.bash_profile
PATH=$PATH:/usr/lib/jvm/java-6-openjdk/jre/bin
export PATH

После этого все заработало, ура.

среда, января 25, 2012

Простой алгоритм случайной выборки с учетом веса

Часто необходимо обращаться к одной и той же задаче:
"случайная выборка с учетом веса".

Чтобы не забыть вот кратное описание взятое отсюда:

Простой алгоритм случайной выборки с учетом веса


В общем виде этот алгоритм можно описать так:

  1. Выбрать случайное число между еденицей и суммой “весов” всех элементов
  2. Спускаться по списку элементов добавляя к счетчику вес текущего элемента
  3. Проверить, если счетчик (шаг №2) больше или равен случайному числу (шаг №1), то закончить
  4. цикл и вернуть текущий элемент. В противном случае перейдите к шагу №2.
/**
 * Выборка случайного элемента с учетом веса
 *
 * @param array $values индексный массив элементов
 * @param array $weights индексный массив соответствующих весов
 * @return mixed выбранный элемент
 */
function weighted_random_simple ( $values, $weights )
{
    $total = array_sum( $weights );
    $n = 0;
 
    $num = mt_rand( 1, $total );
 
    foreach ( $values as $i => $value )
    {
        $n += $weights[$i];
 
        if ( $n >= $num )
        {
            return $values[$i];
        }
    }
}

$values = array('A', 'B', 'C');
$weights = array(3, 7, 10);
echo weighted_random_simple($values, $weights);

Алгоритм случайной выборки из тысяч элементов

Алгоритм может быть расширен, чтобы сделать его значительно быстрее. Вместо вычисления общего веса (шаг №1) и счетчика (шаг №2) каждый раз, можно сделать это один раз и сохранить значения счетчиков в массиве. Тогда мы сможем использовать бинарный поиск, чтобы быстро выбрать правильный элемент. Ниже приведен модифицированный вариант скрипта:
/**
 * Случайно выбирает один из элементов на основе их веса. 
 * Оптимизирован для большого числа элементов.
 *
 * @param array $values индексный массив элементов
 * @param array $weights индексный массив соответствующих весов
 * @param array $lookup отсортированный массив для поиска
 * @param int $total_weight сумма всех весов
 * @return mixed выбранный элемент
 */
function weighted_random($values, $weights, $lookup = null, $total_weight = null)
{
    if ($lookup == null OR $total_weight == null) 
    {
        list($lookup, $total_weight) = calc_lookups($values, $weights);
    }
 
    $r = mt_rand(1, $total_weight);
         
    return $values[binary_search($r, $lookup)];
}
 
/**
 * Создание массива используемого в бинарном поиске
 *
 * @param array $values 
 * @param array $weights
 * @return array
 */
function calc_lookups($values, $weights)
{
    $lookup = array();
    $total_weight = 0;
         
    for ($i=0; $i < count($weights); $i++)
    {
        $total_weight += $weights[$i];
        $lookup[$i] = $total_weight;
    }
     
    return array($lookup, $total_weight);
}
 
/**
 * Ищет в массиве элемент по номеру и возвращает элемент если он найден.
 * В противном случае возвращает позицию, где он должен быть вставлен, 
 * или count($haystack)-1, если $needle больше чем любой элемент в массиве.
 *
 * @param int $needle
 * @param array $haystack
 * @return int
 */
function binary_search($needle, $haystack)
{
    $high = count($haystack) - 1;
    $low = 0;
 
    while ( $low < $high )
    {
        $probe = (int)(($high + $low) / 2);
 
        if ($haystack[$probe] < $needle)
        {
            $low = $probe + 1;
        } 
        elseif ($haystack[$probe] > $needle) 
        {
            $high = $probe - 1;
        } 
        else
        {
            return $probe;
        }
    }
 
    if ( $low != $high )
    {
        return $probe;
    } 
    else
    {
        return ($haystack[$low] >= $needle) ? $low : $low + 1;
    }
}

// Рассчет массивов (1 раз)
list($lookup, $total_weight) = calc_lookups($values, $weights);
//....
// Каждый раз когда вам необходимо выбрать случайный элемент:
$val = weighted_random($values, $weights, $lookup, $total_weight);

понедельник, октября 31, 2011

Основы работы с git

Основной и полноценный документ http://githowto.com/

забрать код
git clone git@github.com:companyname/projectname.git

если
Cloning into mambaandroid...
Permission denied (publickey).
fatal: The remote end hung up unexpectedly
то
ssh-keygen -t rsa -C "your_email@youremail.com"
cat ~/.ssh/id_rsa.pub
и скопировать его в настройки своего аккаунта на гитхабе

тест коннекта
ssh -T git@github.com

иногда надо добавить идентит
ssh-add ~/.ssh/id_rsa

список бранчей
git branch -a

переключиться в бранч
git checkout version-0.8

если вставить этот код в конец своего .bashrc
PS1="\[\033[38m\]\u@\h\[\033[01;34m\] \w \[\033[31m\]\`ruby -e \"print (%x{git branch 2> /dev/null}.grep(/^\*/).first || '').gsub(/^\* (.+)$/, '(\1) ')\"\`\[\033[35m\]$\[\033[00m\] "

то будет подсвечиваться текущий бранч прямо в консоли

забрать все новое с удаленного репа и попытаться авто-смерджить с текущим состоянием
git pull origin version-0.8

добавить все данные в локальной копии и зафиксировать
git add .
git commit -m 'desc'
или
git commit -a -m 'desc'

пушнуть в удаленный реп
git push origin version-0.8

отменить локальные изменения (svn revert)
сбросить все
git reset --hard HEAD

только определенный файл
git checkout -- hello.rb
git checkout HEAD hello.rb

ревертнуть последний коммит
git revert HEAD

еще примеры здесь

смерджить код из обного бранча в другой
git checkout version-0.9
git pull origin version-0.9
git merge version-0.8
git log
git push origin version-0.9

смерджить код в мастер и навесить таг
git checkout master
git merge version-0.8
git tag -a version-0.8.1-release -m "0.8.1 фикс-версия"
git push --tags origin master

четверг, февраля 10, 2011

Как на самом деле работает присваивание и передача по ссылке объектов в php5

Как-то давно, когда только появился php5, я думал, что разобрался с ООП, а именно с присвоением объектов. Но из-за того, что много времени проводил с java стал под забывать как это работает в php5.
В штатном режиме, если всегда помнить о том, что в php5 присваивание происходит по ссылке, то нет никаких проблем, пока не используешь знак &.
http://www.php.net/manual/en/language.oop5.basic.php
<?php
class SimpleClass{}
class SimpleClass
{
    // property declaration
    public $var = 'a default value';

    // method declaration
    public function displayVar() {
        echo $this->var;
    }
}
?>

Но подлинный смысл раскрывается этим комментарием:
http://www.php.net/manual/en/language.oop5.basic.php#79856
Я позволил себе его вольно перевести:
В php необходимо думать о переменных как о ячейках памяти. У каждой переменной если имя, которое ссылается на ячейку памяти(переменную), где хранится значение простого типа: число, строка, массив, и т.д. Когда вы создаете ссылку(&), вы создаете второе имя, которое ссылается на ту же саму ячейку памяти. Когда вы присваиваете одну переменную другой, вы копируете содержимое ячейки памяти в другую ячейку памяти.
Но присваивание экземпляров классов(далее объект) происходит не так как присваивание простых типов. Объекты не хранятся в ячейках памяти, которые программист "видит" на прямую. Вместо этого в ячейке памяти хранится указатель на объект. Таким образом указатель ведет себя как примитивный тип.
Когда вы присваиваете значение ссылки объекта одной переменной другой, обе переменные могут менять состояние одного и того же объекта. Но переменные не являются ссылками на объект, т.к. если присвоить одной из переменных новое значение, то это не отразится на другой переменной.
<?php
// Assignment of an object
Class Object{
   public $foo="bar";
};

$objectVar = new Object();
$reference =& $objectVar;
$assignment = $objectVar

//
// $objectVar --->+-----------+
//                |(указатель1)----+
// $reference --->+-----------+    |
//                                 |
//                +-----------+    |
// $assignment -->|(указатель2)----+
//                +-----------+    |
//                                 |
//                                 v
//                  Object(1):foo="bar"
//
?>
Значение переменной $assignment отличается от $objectVar, но эти значение ссылаются на один и тот же объект. Это поведение делает похожим на механизм передачи по ссылке. Если вы используете переменную $objectVar, чтобы поменять состояние объекта, то эти же изменения появятся и в переменной $assignment, т.к. они указывают на один и тот же объект.


<?php
$objectVar->foo = "qux";
print_r( $objectVar );
print_r( $reference );
print_r( $assignment );

//
// $objectVar --->+-----------+
//                |(указатель1)----+
// $reference --->+-----------+    |
//                                 |
//                +-----------+    |
// $assignment -->|(указатель2)----+
//                +-----------+    |
//                                 |
//                                 v
//                  Object(1):foo="qux"
//
?>

Но с передачей значения по ссылке (&) дело обстоит совсем иначе. Если вы обнулите $objectVar, вы замените значение указателя в ячейке памяти на NULL. Это означает, что $reference, которая ссылается на туже ячейку памяти, также будет NULL. Но $assignment, которая ссылается на другую ячейку памяти, будет так же хранить копию указателя на объект, и она не будет равна NULL.

<?php
$objectVar = null;
print_r($objectVar);
print_r($reference);
print_r($assignment);

//
// $objectVar --->+-----------+
//                |  NULL     | 
// $reference --->+-----------+
//                           
//                +-----------+
// $assignment -->|(указатель2)----+
//                +-----------+    |
//                                 |
//                                 v
//                  Object(1):foo="qux"
?>


К примеру, если взять java, где все переменные если ссылки на объекты, тот же пример выполняется так как и в php5 без символа &:

import java.util.*;

class ObjectReference {
    public static void main(String[] args) {
        class Obj {
            int var = 1;
        }
        
        Obj objectVar = new Obj();
        Obj reference = objectVar;
        objectVar.var = 2;
        System.out.println("objectVar.var="+objectVar.var);
        System.out.println("reference.var="+reference.var);
        
        objectVar = null;
        
        if (reference == null) {
            System.out.println("reference is null");
        } else {
            System.out.println("reference is not null");
        }
    }
}
ответ:
objectVar.var=2
reference.var=2
reference is not null