среда, 18 декабря 2013 г.

Mendeley - must have для любого научного сотрудника

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

Думала, что с моими проблемами Mendeley не справится, но потом включила разум и нашла такую статью и  вот такую, и управилась со всем минут за 10! (а если бы оформляла вручную, то полдня бы потратила). Спасибо доброму человеку из второй ссылки, который сделал стиль оформления источников по русскому ГОСТу да еще с упорядочением по фамилиям авторов (именно такой замороченный стиль требуют в журнале УБС).

среда, 11 декабря 2013 г.

Mathtype: эта версия Word не поддерживается

Эта информация мне сегодня помогла вовремя отправить правки статьи в журнал :) Взято отсюда.

Официально MathType 6.6a не поддерживает Microsoft Word 2010 и при установке не распознает данное приложение. Но существует ручной способ для подключения надстройки MathType 6.6a, для этого необходимо скопировать два файла в папку автозагрузки Microsoft Word 2010:
 КОПИРУЕМ
C:\Program Files\MathType\MathPage\MathPage.wll
C:\Program Files\MathType\Office Support\MathType Commands 6 For Word.dotm
В каталог установки офиса (по умолчанию c:\Program Files)
C:\Program Files\Microsoft Office\Office14\STARTUP\
 1. Нажимаем на "Запуск макросов отключен"
2. Нажимаем на кнопку "Включить содержимое"

воскресенье, 8 декабря 2013 г.

О научных журналах

Цитата с Хабра:

Отвлекаясь от темы, не могу не заметить, что почти все научные статьи, печатаемые в компетентных журналах, а) труднодоступны и б) довольно бесполезны. Те сайты, где они хранятся, и на которые выдает первые ссылки поисковик, всегда платные и весьма кусачи — обычно чуть ли не десять долларов за публикацию. Впрочем, пошарившись получше, можно, как правило, отыскать ту же самую статью и в открытом доступе. Если не удалось и это, можно попробовать написать автору, который, как правило, не отказывает в любезности выслать копию (из чего я делаю вывод, что от сложившейся системы сами авторы мало что получают, а доходы идут кому-то другому). 

Впрочем, от каждой конкретной статьи практической пользы обычно немного. В них, за редким исключением, нет информации, по которой можно сесть и тут же набросать алгоритм. Там бывают или абстрактные идеи без всяких указаний, как же их реализовать; или куча математических формул, пробившись через которые понимаешь, что то же самое можно было написать в двух строчках и человеческим языком; или результаты экспериментов, проведенных авторами, с неизменным комментарием: «ясно далеко не все, нужно продолжать дальше». Не знаю, то ли эти статьи пишутся для галочки или, вернее, для каких-то внутринаучных ритуалов, то ли жаба давит делиться реальными наработками, которые вполне успешно можно использовать в собственном стартапе. В любом случае, эрозия науки налицо.


Да-да, абсолютно согласна!! Вот доразбираюсь со статьями в труднодоступных журналах, чтобы прокачать ПРНД, и попробую запилить еще один постик на Хабр в популярном стиле.

Эти все формулы или идеи, вкратце описываемые другими, начинаю понимать только после того, как сама понаделаю велосипедов на заданную тему, т.е. в некоторой степени повторю путь авторов. 

понедельник, 2 декабря 2013 г.

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

Пример 1.
"Все планеты круглые. Земля - планета. Значит, Земля круглая".
Это дедукция, нормальное такое логическое утверждение (от общего - к частному).

Пример 2.
"Все планеты круглые. Маша круглая. Значит, Маша-планета".
Это абдукция, в данном случае полный бред, но иногда абдукция совпадает с правдой.

А вот еще:


  • Абдукцией называют правдоподобный вывод от частного к частному. Этот вывод обычно связывают с объяснением. 
  • Индукция – метод  перехода от частных наблюдений к общей закономерности, которой удовлетворяют все частные наблюдения. Индукцию называют эмпирической, если найденные при ее помощи закономерности, вообще говоря, могут опровергаться последующими наблюдениями. 
  • Дедукция – умозаключение от общего к частному, от общих суждений к частным выводам. 


понедельник, 21 октября 2013 г.

Как писать комментарии

Опять я почитала книгу С. Мартина "Чистый код. Создание, анализ, рефакторинг". Ниже привожу понравившиеся советы из книги по поводу написания комментариев.

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

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

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

3. Юридические комментарии - например, заявление об авторских правах. Такие комментарии не должны представлять собой трактаты. Вместо того, чтобы перечислять в комментарии все условия, по возможности ограничьтесь ссылкой на стандартную лицензию или другой внешний документ.

4. Предупреждения о последствиях - это весьма полезные комментарии. Например:


5. Иногда бывает полезно оставить заметки на будущее в форме комментариев TODO. Регулярно просматривайте такие комментарии и удаляйте те, которые потеряли актуальность.

6. Комментарий может подчеркивать важность обстоятельства, которое на первый взгляд кажется несущественным:


7. Избыточные комментарии. Читаются не проще, чем сам код. Например:

А вот еще избыточные комментарии:
8.  Использовать штуки типа Javadoc - это хорошо. Но правила, говорящие, что каждая функция должна иметь комментарий Javadoc или что каждая переменная должна быть помечена комментарием - обычная глупость. Такие комментарии только загромождают код, распространяют недостоверную информацию и вызывают общую путаницу и дезориентацию. Например, вот тут комментарий совершенно избыточен:

При всей полезности комментариев Javadoc для API общего пользования не применяйте их в коде, не предназначенном для общего потребления. 

9. Позиционные маркеры. Это строки типа:

//Действия///////////////

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

10. В программировании редко встречаются привычки более отвратительные, чем закрытие комментариями неиспользуемого кода. Никогда не делайте этого! У других программистов, видящих закомментированный код, не хватает храбрости удалить его. Они полагают, что код оставлен не зря и слишком важен для удаления. В итоге закомментированный код скапливается, словно осадок на дне бутылки плохого вина. Системы контроля исходного кода запоминают изменения в коде за нас.

11. Не излагайте информацию системного уровня в контексте локального комментария. Примером служит следующий комментарий. Не считая того, что он избыточен, в него также включена информация о порте по умолчанию, при том, что функция никоим образом не может управлять этим значением. И конечно, ничто не гарантирует, что комментарий будет изменен при изменении кода, в котором это значение определяется. 


12. Плохо, когда сам комментарий нуждается в объяснениях. Например, (см. ниже) - что такое байты фильтра? Они как-то связаны с +1 или *3? Один пиксел соответствует одному байту? 


пятница, 18 октября 2013 г.

Монада и моноид: что это такое

Монада

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

В частности, к монадам относятся:

  • IO (монада строго последовательных вычислений): стратегия связывания — «сначала первое вычисление, затем второе»;
  • Maybe (монада вычислений с отсутствующими значениями): стратегия связывания — «если первое вычисление дало результат, то второе; иначе — отсутствие результата»;
  • List (монада вычислений с несколькими результатами): стратегия связывания — «все возможные результаты второго вычисления, примененного к каждому из вычисленных первым значений параметра»;
  • State (монада вычислений с переменной состояния): стратегия связывания — «начать второе вычисление с состоянием, измененным в результате первого»;
Вот тут описан хороший пример создания и использования монады Maybe.

Моноид

Моноид - это множество с заданной на нем ассоциативной бинарной операцией и нейтральным элементом. Примерами моноидов могут служить:

  • String с операцией конкатенации и значением "пустая строка";
  • Boolean с операцией && и значением true;
  • Boolean с операцией || и значением false;
  • Integer с операцией (+) и значением 0;
  • -Integer с операцией (*) и значением 1;

и т.д.

Определения, которые помогают глубже постигнуть суть моноида

Свойство ассоциативности


Операция \(\circ\) ассоциативна, когда \(\forall x,y,z  (x\circ{y})\circ{z}=x\circ(y\circ{z})\).

Операция сложения целых чисел - ассоциативна.
Например, вычисление выражения 1 + (2 + 3) даст такой же результат, как и вычисление выражения (1 + 2) + 3  число 6.

Операция деления на множестве вещественных чисел - не ассоциативна.
Например, вычисление выражения 4/(2/2) даст число 4, а (4/2)/2 - число 1.

Бинарная операция


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

Нейтральный элемент

Нейтральный элемент бинарной операции - это элемент, который оставляет любой другой элемент неизменным при применении к ним этой бинарной операции. Говоря более формально, пусть \((M, \circ)\) - множество \(M\) с определенной на нем бинарной операцией \(\circ\). Элемент \(e \in M\) называется нейтральным относительно \(\circ\), если \(x\circ{e}=e\circ{x}=x\) \( \forall x \in M\).

1. Определение монады (wiki)
2. Туториал по системе переписывания термов TermWare
3. Про моноиды с примерами на F#
4. Определение ассоциативности (wiki)
5. Определение ассоциативности (ru.math.wikia)
6. Бинарная операция (wiki)
7. Определение нейтрального элемента (ru.math.wikia)


понедельник, 14 октября 2013 г.

Как сделать презентацию для конференции: клевая ссылка

Готовлю тут презентацию к конференции, а они в разделе для докладчиков выложили ссылку на такую вот замечательную памятку докладчикам:

http://wiki.4intra.net/Conference-for-speakers

http://www.powerlexis.ru/klub_powerpoint/tekstozavr/ - этот инструмент заценяет адекватность презентации, надо будет попробовать :)

А вот кстати и интутитивно понятный онлайн инструмент для построения графиков и диаграмм (полезно, когда никак навскидку не можешь вспомнить, как строить их в MS Excel):

http://www.chartgo.com/en/chartbar.jsp


суббота, 5 октября 2013 г.

Как подчистить историю коммитов (личный опыт)

В общем, мне нужно было сделать свою текущую историю коммитов на github "красивой", чтобы в ветке develop была последняя работа, а в ветке master - только стабильный, нормально работающий код. Имелась только ветка master с кучей лишних коммитов, а стабильный код был где-то пару-тройку коммитов назад.

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

Вопрос.

What I'd like to do is remove ALL the version history from the local Git repository, so the current contents of the repository appear as the only commit (and therefore older versions of files within the repository are not stored).

Ответ.

The only solution that works for me (and keeps submodules working) is
git checkout --orphan newBranch
git add -A  # Add all files and commit them
git commit
git branch -D master  # Deletes the master branch
git branch -m master  # Rename the current branch to master
Вопрос.

How to force push a reset to remote repository
(когда откатываешь master на пару коммитов назад, этот зараза отказывается пушить изменения)

Ответ.

git push origin master -f

Вопрос.

Как посмотреть, какие ветки есть и к какому коммиту прикреплена каждая ветка?

Ответ.

git show-branch --all

P.S. http://www.syntevo.com/smartgithg/documentation?page=git-flow

Информационные источники: stackoverflowеще stackoverflowдокументация Git

понедельник, 30 сентября 2013 г.

Как писать функции

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

1. Функции должны быть компактными. Желательно, чтобы длина функции не превышала 20 строк.

2. Максимальный уровень отступов в функции не должен превышать одного-двух (отступы создаются командами if, else, while и т.д.)

3. Функция должна выполнять только одну операцию. Она должна выполнять ее хорошо и ничего другого она делать не должна. Чтобы убедиться в том, что функция "выполняет только одну операцию", необходимо проверить, что все команды функции находятся на одном уровне абстракции. Например, посмотрим на вот такой кусочек кода:


В этом куске кода данное правило нарушается. Некоторые из концепций - например, getHtml() - находятся на очень высоком уровне абстракции, другие (например, String pagePathName = PathParser.render(pagePath) - на среднем уровне). Наконец, третьи - такие, как .append("\n") - относятся к чрезвычайно низкому уровню абстракции.

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

4. Код должен читаться как рассказ - сверху вниз. За каждой функцией должны следовать функции следующего уровня абстракции. Это позволяет читать код, последовательно спускаясь по уровням абстракции в ходе чтения списка функций.

5. В идеальном случае количество аргументов функции равно нулю. Функций с тремя аргументами следует по возможности избегать. Аргументы не только ухудшают читаемость кода, но и создают больше проблем с точки зрения тестирования. Только представьте, как трудно составить все тестовые сценарии, проверяющие правильность работы кода со всеми комбинациями аргументов.

6. Если функция должна получать более двух или трех аргументов, весьма вероятно, что некоторые из этих аргументов  стоит упаковать в отдельном классе. Рассмотрим следующие два объявления:

Circle makeCircle(double x, double y, double radius);
Circle makeCircle(Point center, double radius)

Сокращение количества аргументов посредством создания объектов может показаться жульничеством, но это не так. Если переменные передаются совместно как единое целое (как переменные x и y в этом примере), то, скорее всего, вместе они образуют концепцию, заслуживающую собственного имени.

7. Выбор хорошего имени для функции  способен в значительной мере объяснить смысл функции, а также порядок и смысл ее аргументов. В унарных функциях сама функция и ее аргумент должны образовывать естественную пару "глагол/существительное". Например, вызов вида write(name) смотрится весьма информативно. Читатель понимает, что чем бы ни было "имя", оно куда-то "записывается". Еще лучше запись writeField(name), которая сообщает, что "имя" записывается в "поле" какой-то структуры.

8. Избавьтесь от побочных эффектов. Ваша функция обещает сделать что-то одно, но делает что-то другое, скрытое от пользователя. Иногда она вносит неожиданные изменения в переменные своего класса - скажем, присваивает им значения параметров, переданных функции или глобальных переменных системы. в любом случае такая функция является коварной и вредоносной. Для примера рассмотрим следующую функцию:

Функция использует стандартный алгоритм для проверки пары "имя пользователя/пароль". Она возвращает true или false. Побочным эффектом этой функции является вызов Session.initialize(). Имя checkPassword сообщает, что функция проверяет пароль. Оно ничего не говорит о том, что функция инициализирует сеанс. Таким образом, тот, кто поверит имени функции, рискует потерять текущие сеансовые данные, когда он решит проверить данные пользователя. 

Побочный эффект создает временную привязку. А именно, функция checkPassword может вызываться только в определенные моменты времени (когда инициализация сеанса может быть выполнена безопасно). Несвоевременный вызов может привести к непреднамеренной потере сеансовых данных. Временные привязки создают массу проблем, особенно когда они прячутся в побочных эффектах. Если без временной привязки не обойтись, этот факт должен быть четко оговорен в имени функции. В нашем примере функцию можно было бы переименовать в checkPasswordAndInitializeSession, хотя это безусловно нарушает правило одной операции.

9. Почти все наверняка сталкивались с необходимостью дополнительной проверки аргументов, которые на самом деле оказывались выходными, а не входными. Пример: appendFooter(s). Присоединяет ли эта функция s в качестве завершающего блока к чему-то другому? Или она присоединяет какой-то завершающий блок к s? Является ли s входным или выходным аргументом? Конечно, можно посмотреть на сигнатуру функции и получить ответ. Но это нарушает естественный ритм чтения кода. На самом деле функцию appendFooter лучше вызывать в виде: 
report.appendFooter()
В общем случае выходных аргументов стоит избегать. Если ваша функция должна изменять чье-то состояние, пусть она изменяет состояние своего объекта-владельца.

10. Функция должна что-то делать или отвечать на какой-то вопрос, но не одновременно. Либо функция изменяет состояние объекта, либо возвращает информацию об этом объекте. Совмещение двух операций часто вызывает путаницу. Для примера рассмотрим следующую функцию:

public boolean set(String attribute, String value);

Функция присваивает значение атрибуту с указанным именем  и возвращает true, если присваивание прошло успешно, или false, если такой атрибут не существует. Это приводит к появлению странных конструкций вида 

if (set ("username", "UncleBob"))...

Представьте происходящее с точки зрения читателя кода. Что проверяет это условие? Что атрибут "username" содержит ранее присвоенное значение "UncleBob"? Или что атрибуту "username" успешно присвоено значение "UncleBob"? Смысл невозможно вывести из самого вызова, потому что мы не знаем,  чем в данном случае является слово set - глаголом или прилагательным. 

Полноценное решение заключается в отделении команды от запроса, чтобы в принципе исключить любую неоднозначность:

if (attributeExists("username")){
    setAttribute("username", "UncleBob")
...
}

11. Изолируйте блоки try/catch. Блоки try/catch выглядят весьма уродливо. Они запутывают структуру кода и смешивают обработку ошибок с нормальной обработкой. По этой причине тела блоков try и catch рекомендуется выделять в отдельные функции:

12. Используйте исключения, а не коды ошибок!

13. Если ваши функции остаются очень компактными, редкие вкрапления множественных return, команд break и continue не принесут вреда, а иногда даже могут повысить выразительность по сравнению с классической реализацией с одной точкой входа и одной точкой выхода. 




понедельник, 16 сентября 2013 г.

Как пользоваться Sublime 2

Ниже будут представлены не все тонкости работы с Sublime, а только те, которыми буду пользоваться в ближайшее время. Все проверялось на ОС Ubuntu.

Ctrl + + -  увеличить шрифт
Ctrl + /  -  закомментировать/раскомментировать выделенный текст

Если нажать на Shift и правую кнопку мыши, то можно сделать вертикальное выделение текста:



Если нажать на Ctrl, то можно выделить сразу несколько блоков текста (множественное выделение), когда начнем писать, текст будет вводиться одновременно во всех выделенных местах:


По нажатию Ctrl+P вызывается панель перехода и поиска. Если мы в ней введем @func, то перейдем к функции с именем func, если введем :10 - то перейдем к 10 строке.

Ctrl+Home, Ctrl+End - переход к началу или концу файла соответственно.

Ctrl + <-, Ctrl + -> - переход по словам

Сtrl + l - добавляем к выделенному еще одну строку

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

Ctrl + Shift + M - 
выделить текст внутри скобки, квадратной или фигурной. Повторяя нажатие этих клавиш, выделим и сами скобки, потом выделится текст внутри охватывающих эти скобки других скобок и т.д.:


Ctrl + F2 -поставить/убрать закладку. 
F2 -перейти к закладке

Sublime Package Control

Позволяет с легкостью устанавливать новые плагины. Устанавливается так. Нажимаем Ctrl + ` . Затем в открывшуюся консоль пишем


Перезапускаем Sublime. Идем в Preferences->Package Settings. Там должен появиться Package Control.
Плагин Alignment

Этот плагин помогает красиво выравнивать знаки равенства:


Для установки этого плагина нажимаем Ctrl + Shift + P. В строке набираем install и ищем Alignment.
Для того, чтобы сделать автоматическое выравнивание, набираем Ctrl + Alt + A. 

Плагин Emmet

Хорошо про этот плагин написано вот тут. Вкратце, этот плагин помогает сильно экономить время при создании макетов страниц. Например, можно написать 

ul>li*4>a[href=#]{текст}

нажать Tab, или Ctrl+E и получится вот что:


Плагин CSS Comb

Применение этого плагина позволяет сделать код CSS более читаемым и красивым, т.е. улучшает стиль кода. Используется он следующим образом. Встаем курсором на блок CSS и нажимаем Shift + Ctrl + C.

До и после:



Информационные источники: ПервыйВторойТретий и еще какие-то...

воскресенье, 15 сентября 2013 г.

Как пользоваться git: тонкости

Прошла часть туториалов, находящихся вот тут. Разъяснилось несколько вещей (см. ниже).

Во-первых, ветки (бранчи) в Git не занимают много места, т.к. по сути это просто ссылки на конкретный commit и больше ничего. Во-вторых, ...

Merge vs Rebase

Команда merge создает специальный commit, у которого есть два уникальных родителя. Этот commit как бы говорит нам "я хочу включить в себя всю ту работу, которая была проделана при разработке обоих моих родителей и их родителей". Рассмотрим следующий пример.

Введем команду 
git merge bugFix
Получится вот что:



Теперь в master'е содержится вся выполненная работа. Теперь выполним такие команды:

git checkout bugFix
git merge master


Т.к. ветка bugFix находилась в дереве выше (то есть, менее актуальна), чем master, то ссылка bugFix просто передвинулась на тот же commit, на который указывает ветка master.

Команда rebase берет несколько commit'ов, копирует их, и помещает копии вниз под тем commit'ом, который мы укажем. Преимущество rebase в том, что он приводит историю commit'ов к линейному виду. Commit log/history будет выглядеть гораздо более красивым, чем до применения rebase. Рассмотрим следующий пример.


Допустим, мы хотим перенести то, что сделано в bugFix, чтобы в истории commit'ов все выглядело так, как будто мы не параллельно разрабатывали две фичи, а последовательно. Введем команду 

git rebase master

Получится вот что:
Создался новый commit с фичей из ветки bugFix, являющийся продолжением commit'а C2. Теперь у нас красивая линейная история commit'ов. Заметим, что commit C3 до сих пор где-то болтается (где именно, не написано было), а commit C3' как бы является его копией.

Теперь введем команды 

git checkout master
git rebase bugFix

Получится вот что:
Т.к. ветка master находилась в дереве выше, чем bugFix, т.е. была менее актуальна, то она просто передвинулась.

Reset vs Revert

Reset отменяет изменения путем переноса ссылки на предыдущий commit. Это как бы переписывание истории commit'ов. Пусть у нас вот такая история commit'ов:


Наберем команду

git reset HEAD~1

(HEAD это относительная ссылка на commit, на котором мы сейчас находимся. Оператор ~ позволяет прыгать по дереву commit'ов вверх или вниз на указанное количество шагов, в данном случае на 1)

Получится вот что:


Эта команда отлично подходит для локальных репозиториев на вашем компьютере, но совершенно не подходит для случая удаленных репозиториев, когда над проектом работают несколько программистов (в этом случае до других просто не дойдут ваши изменения). В этих других случаях выручает команда revert.

Пусть у нас опять такая же ситуация, и мы хотим отменить последний commit:


Введем команду

git revert HEAD
И получится вот что:


Т.е. создался новый commit, аналогичный commit'у C1, не содержащий изменений, которые были в commit'е C2.

Cherry-pick

Эта команда позволяет более гибко перемещать commit'ы. Имеет следующий формат: cherry-pick <Commit i1><Commit i2>...<Commit ik>. Рассмотрим пример. Пусть у нас имеется вот такой репозиторий

 И мы хотим перенести в master все фичи, которые есть в commit'ах C3, C4, C7. Наберем команду

git cherry-pick C3 C4 C7

И получим желаемый результат:

И вот еще, про гигиену commit'ов:
  • Коммитить нужно часто, но атомарно (т.е. только законченные функции), также нужно подробно описывать, что в commit'е (иначе будет трудно поймать состояние проекта, будет трудно понять, куда нужно откатиться, если текущая версия не работает).
  • Не использовать git как систему бэкапа!

пятница, 13 сентября 2013 г.

Как называть переменные и функции: rules of thumb

Меня давно уже волнует вопрос, как нужно называть переменные и функции, чтобы код был понятнее. Понравились следующие мысли по этому вопросу (ниже конспект из книги Р. Мартина "Чистый код. Создание, анализ и рефакторинг"). Выписала оттуда не все советы, а только те, что могут пригодиться в ближайшее время.

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

Плохо:
int d: //Прошедшее время
Хорошо:
int elapsedTimeInDays;
int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;

Плохо:
Хорошо:

2. Избегайте дезинформации.

2.1. Переменным не стоит присваивать имена типа hp, aix и sco, потому что они ассоциируются с платформами и разновидностями Unix. Даже если в переменной хранится длина гипотенузы и имя hp кажется хорошим сокращением, оно может ввести в заблуждение читателя кода.

2.2. Не обозначайте группу учетных записей именем accountList,  если только она действительно не хранится в списке. Лучше подойдут такие имена, как accountGroup, bunchOfAccounts или даже просто accounts. 

2.3. Остерегайтесь малозаметных различий в именах. Сколько времени потребуется, чтобы заметить незначительное различие в XYZControllerForEfficientHandlingOfStrings и XYZControllerForEfficientStorageOfStrings?

2.4. Не используйте комбинации из "l" и "O" в именах переменных, потому что они похожи на 0 и 1.

Плохо:
int a = l;
if ( O == l )
    a = ol;
else
    l = ol;

3. Используйте осмысленные различия

Плохо:
Хорошо:
Вместо a1 и a2 лучше использовать source и destination.

Плохо:
-Классы Product, ProductInfo, ProductData  - разные имена, которые по сути обозначают одно и тоже. 
-Методы getActiveAccount(), getActiveAccounts(),  getActiveAccountInfo(). Как понять, какую из этих функций вызывать в конкретном случае?

4. Используйте удобопроизносимые имена.
Если имя невозможно нормально произнести, то при любом его упоминании в обсуждении вы выглядите полным идиотом. "Итак, за этим би-си-эр-три-си-эн-тэ у нас идет пи-эс-зэт-кью, видите?"

5. Однобуквенные имена могут использоваться только для локальных переменных в коротких методах. Длина имени должна соответствовать размеру его области видимости. Однобуквенные переменные хорошо использовать в счетчиках цикла.

6. Имена классов и объектов должны представлять собой существительные и их комбинации: Customer, WikiPage, Account, AddressParser. Старайтесь не использовать в именах классов такие слова, как Manager,  Processor, Data, Info. Имя класса не должно быть глаголом. 

7. Имена методов представляют собой глаголы или глагольные сочетания: postPayment, deletePage, save и т.д. Методы чтения/записи и предикаты образуются из значения и префикса get, set, is.
Хорошо:
string name = employee.getName();
customer.setName("mike");
if (paycheck.isPosted())

8. Выберите одно слово для каждой концепции. Например, существование в разных классах эквивалентных методов с именами fetch, retrieve и get неизбежно создаст путаницу. Аналогичным образом, использование терминов controller, manager и driver в одной кодовой базе тоже вызывает путаницу. Чем DeviceManager принципиально отличается от ProtocolController?

9. Старайтесь не использовать одно слово в двух смыслах. Допустим, программа содержит много классов с методами add, которые создают новое значение сложением или конкатенацией двух существующих значений. Вы пишете новый класс с методом, помещающим свой единственный параметр в коллекцию. Стоит ли присвоить этому методу имя add? Т.к. новый метод имеет другую семантику, то ему лучше присвоить имя insert или append.

10. Не стесняйтесь использовать термины из области информатики, названия алгоритмов и паттернов, математические термины и т.д. Имя AccountVisitor сообщит много полезной информации программисту, знакомому с паттерном "Посетитель". Если для того, что вы делаете, не существует подходящего программизма, используйте имя из пространства задачи. По крайней мере программист, занимающийся сопровождением кода, сможет узнать у специалиста в предметной области, что означает это имя. 

пятница, 30 августа 2013 г.

Шаблон логин-формы

Сверстала вот такую центрированную форму входа на сайт, вдруг кому еще пригодится, ну и мне как шпаргалка. Выглядит вот так:



А вот код:

вторник, 27 августа 2013 г.

Предобработка картинок в административной панели (фреймворк Yii).

Сразу же оговорюсь, что ниженаписанное тестировалось только для Yii версии 1.1.2, поскольку сайт я делаю в процессе изучения этой книги (на момент ее публикации эта версия была последней).

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



Решение.

1. Подключение необходимых библиотек
Нам помогут три библиотеки: imgAreaSelectWideImagejquery.form. Первая библиотека требует более нового jQuery, который поставляется с Yii, поэтому также пришлось отключать "старый" jQuery и  подключать "новый". Для этого в /protected/config/main.php под 'components' напишем следующее:
Далее, в /protected/views/layouts/main.php напишем следующее:
Вот мы и подключили нужную версию jQuery и заодно imgAreaSelect. WideImage будем подключать "на лету" прямо в контроллере. 
2. Изменение модели
Объявляем переменные (photo - ссылка на файл-картинку, остальные переменные - координаты обрезания картинки). У меня модель находится в файле /protected/models/News.php):
В этом же файле изменяем функцию rules (в ней прописываются правила, которым должны удовлетворять данные, вносимые в форму):
3. Изменение формы
В форме редактирования страницы (у меня это файл /protected/views/news/_form.php)  убираем текстовое поле Picture, где хранится путь к файлу и добавляем кнопку выбора файла:
Также добавляем место, куда будем подгружать картинку для предпросмотра и переменные, где будем хранить сведения о координатах для обрезки картинки и о пути к загруженному файлу:
В самый верх файла добавляем скрипты. Они делают следующее.
После выбора пользователем файла, он отправляется на сервер, где файл сохраняется в папке tmp, обратно приходит ссылка на него. Далее в область предпросмотра подгружается картинка из присланной ссылки. Подключается к работе плагин imgAreaSelect. При изменении параметров обрезки картинки  в скрытых данных формы сохраняются координаты обрезки. Эти скрытые данные будут также переданы при нажатии на кнопку "Отправить". Кстати, за возможность отправки файла без перезагрузки страницы стоит поблагодарить плагин jquery.form, у него есть полезнейший метод ajaxSubmit. Оказалось, что просто так без перезагрузки страницы файл на сервер не отправить (из соображений безопасности). Вот этот плагин и выручил.
4. Изменение контроллера
В контроллере (у меня это файл /protected/controllers/NewsController.php) изменяем функцию accessRules - для того, чтобы разрешить пользователям сайта запускать функцию preview (функция preview сохраняет выбранный файл в папку tmp и передает на клиент ссылку на него):
А вот и сама функция preview:
Она такая большая, потому что выполняет кучу проверок - на формат файла, на размер, и т.д. Генерирует уникальное имя файла, зависящее от времени загрузки, ужимает до макс. 600 px по ширине и высоте, сохраняет файл в папку tmp и сообщает клиенту его адрес.

А вот функция создания новости (вызывается, когда на клиенте нажимается кнопка "Отправить"). Как видим, перед сохранением новости производится обрезка изображения по координатам, выбранным пользователем. Кстати, функция обновления новости видоизменяется аналогично.

четверг, 8 августа 2013 г.

Фреймворк Yii: продолжение

Продолжаю изучать Yii по этой книге. Удивило то, что надо "ручками" создавать таблицы БД, а затем автоматом генерировать ORM-модели (например в Django все наоборот, в models пишешь модели, а потом запускаешь syncdb и таблицы генерируются сами). Для создания таблиц скачала phpmyadmin, его можно очень просто поставить (распаковать в папку откуда запускаются веб-приложения, переименовать, переименовать пример файла настроек config.sample.inc.php просто в config.inc.php). Таблицы в нем тоже очень просто создаются, а вот с настройкой связей между ними сложнее. В книге , например, приводится вот такой код для настройки связей между двумя таблицами:

ALTER TABLE 'tbl_issue' ADD CONSTRAINT 'FK_issue_project' FOREIGN KEY
('project_id') REFERENCES 'tbl_project' ('id') ON DELETE CASCADE ON
UPDATE RESTRICT;

такой запрос никак не хотел выполняться из-за ошибок в синтаксисе. В итоге выполнился вот такой запрос (спасибо stackoverflow):

ALTER TABLE `tbl_issue`
  ADD CONSTRAINT `FK_issue_project` FOREIGN KEY (`project_id`) REFERENCES `tbl_project` (`id`);

Ну а запрос INSERT INTO ... принял такой вид:

INSERT INTO `tbl_user`
  (`email`, `username`, `password`)
VALUES
  ('test1@notanaddress.com','Test_User_One', MD5('test1')),
  ('test2@notanaddress.com','Test_User_Two', MD5('test2'));

Для набора этих кривых кавычек, оказывается, есть отдельная кнопка на клавиатуре :)

вторник, 30 июля 2013 г.

Фреймворк Yii: первые шаги

Решила поизучать Yii с помощью этой книги. Для начала пришлось установить PHP & Apache. Оказалось, что тут описан "путь Воина", при выборе которого исходники Apache компилируются на компьютере пользователя. Это полезно, когда нужно настроить всякие тонкости. Мне же пока тонкости не нужны, поэтому можно воспользоваться LAMP и написать:

sudo apt-get install lamp-server^

Далее в книге предлагалось скачать yii, скопировать ее в web-accessible folder и проверить, удовлетворяются ли в системе минимальные требования для ее работы. Насколько я поняла, такой папкой является /var/www. Но в эту папку оказалось не так-то просто скопировать файлы. Поэтому пришлось копировать через терминал:

sudo cp -r /home/natalia/yii-1.1.2.r2086/* /var/www

Далее, проверила выполнение минимальных требований, набрав в строке браузера

127.0.0.1/requirements/index.php

(то, что localhost по адресу 127.0.0.1 увидела в сообщениях при установке LAMP)

Минимальные требования были выполнены. Далее в книге предлагалось воспользоваться инструментом yiic, который автоматически создает demo-приложение. Но если писать так, как указано в книге, никак не получалось. Ответ нашелся в документации по этой версии, скачанной с сайта yii framework. Воспользовалась одним из альтернативных предложенных в документации способов. Перешла в папку /var/www/framework и набрала

php yiic.php webapp /home/natalia/demo.

Потом попыталась открыть http://localhost/demo/index.php и увидела ошибку 404.

Оказалось, что нужно было настроить еще несколько вещей (спасибо Дмитрию).

1. Для удобства и пущей безопасности было решено хранить веб-проекты в папке /home/natalia/projects, а yii framework поместить в папку /home/natalia/projects/lib/yii. Настроить права к папке projects: sudo chmod -R 777 /home/natalia/projects.

2. Изменить права к папке apache, чтобы без проблем можно было сохранять внесенные изменения: sudo chmod -R 777 /etc/apache2

3. Настроить DocumentRoot в файле /etc/apache2/sites-available/default.txt DocumentRoot - указывает apache на то, откуда брать файлы для сайтов. В файле default вместо папки /var/www в паре мест написать /home/natalia/projects.

3. В demo-приложении в файле index.php поправить строку (путь к yii)
$yii = dirname(_FILE_).'../lib/yii/framework/yii.php';

4. Перезапустить apache

sudo service apache2 stop
sudo service apache2 start

После этого демо-приложение заработало :)



Архив блога