Найлегша співбесіда

Я побував на, мабуть, півсотні співбесід за десять років роботи програмістом. Я провів майже стільки ж співбесід.
І найлегша й найпростіша співбесіда в мене була в компанії, де я працюю зараз.
Просто один день роботи разом. Один день у парі з розробниками над реальними завданнями.
Не потрібні тестові завдання – можна побачити, як думає людина. Нащо суперскладні чи-то суперлегкі питання, які можна проґуґлити. Краще перевірити, чи може кандидат ґуґлити, чи може завдати питання, чи може працювати, чи може якимось чином допомогти.
Це й набагато легше кандидату – можна відразу побачити, чи можна працювати в цій компанії, які люди тут працюють, які умови праці.
Якщо все так легко – то чи проходять усі кандидати? Ні, більшість не проходять. Не проходить більшість поганих програмістів. Не проходять деякі добрі програмісти, які не вміють спілкуватися. І що найголовніше – не проходять програмісти, які знають розумні слова, але не вміють програмувати.

Про поновлення chef-client

Вже більше року ми запускаємо  нові віртуальні машини з chef’ом на борту. За цей рік було починено декілька багів клієнта. Найбільший на мою думку – баг з перезаписуванням run-list (списку ролей та рецептів) при запуску з заданим вручну run-list при помилці в рецепті. Здається він був починений в версії 11.8 Тож поновити версії потрібно (та й взагалі потрібно намагатися тримати свіжі версії)

Більш ніж сто машин важко поновити вручну, та й навіщо – chef. Та для початку потрібно було знайти версії клієнтів на машинах, аби поновити застарілі. Ми знайшли статтю, та код там страшний: з глобального Ruby запускається Ruby код Knife, що генерує JSON, а потім глобальний код парсить цей JSON.

Ось трохи більше коду, але кращого.

require 'chef/knife'
Chef::Knife.new.configure_chef
result = Chef::Search::Query.new.search('node', 'name:*')[0]
versions = result.each_with_object(Hash.new(0)) {|node, hash| hash[node['chef_packages']['chef']['version']] += 1 rescue nil}

Чому є rescue? Бо деякі node не були правильно створені, а потім не були правильно видалені.

Ще трохи коду аби почистити ці ужасні записи-зомбі.

result.select do |node|
node['chef_packages'].nil?
end.each do |node|
Chef::ApiClient.load(node.name).destroy if Chef::ApiClient.list.keys.include?(node.name)
node.destroy
end

Далі можна поновючати. Є два варіанти – один за допомогою omnibus_updater. Версія для Windows є у форках.

Інший менш правильний – інсталювати gem chef. Для мінорних поновлень – нормально, але потрібно розуміти, що Ruby залишиться старим.

Далі пишемо простий запрос

knife ssh "chef_packages_chef_version:11.6.2 AND platform:ubuntu" "sudo chef-client -o recipe[omnibus_updater]"

Знайти всі ноди з Убунтою та версією клієнта – 11.6.2 та поновити версію, можна було використати:

/opt/chef/embedded/gem install chef -v version

 

Winbind та Ubuntu 14.04

Нещодавно ми вирішили перевести наші машини на Убунту 14.04. Все пройшло декілька місяців, настрашніші баги вже зловлені. Тестові побудови за допомогою спрацювали нормально. Тож ми вирішили спробувати в AWS.
Раптово побудова зламалася з помилкою.
Я

net ads join dnscreate@AWS.DOMAIN.COM

failed with

kerberos_kinit_password dnscreate@AWS.DOMAIN.COM failed: Cannot contact any KDC for requested realm

Same recipe worked with test kitchen. I spent couple days trying to find the reason. It appeared that winbind started to use UDP 88 instead of TCP 88. I didn’t found that in changelog, so beware.

Відмінності у вибірці по сторінках даних в SQL Server Denali

Я додав підтримку запитів до нового SQL Server у ActiveRecord адаптер.
Єдине,що змінилось вибірка даних по сторінках. (Limit & Offset – детальніше http://msdn.microsoft.com/en-us/library/ms188385(v=sql.110).aspx)

Ось декілька відмінностей, які я побачив.

Перша – потрібно явно вказувати порядок у виборці.

Друга. Потрібно обов’язково вказувати offset, тоді як limit необов’язковий.
Тому при наявності обмеження тільки кількості, краще користуватися top.

Також це тому, що є різниця в обробці обмеження в 0.
select top(0) * from some_table
поверне список колонок.

Тоді як
select * from some_table order by id OFFSET 0 ROWS FETCH FIRST 0 ROWS ONLY
не виконається через помилку.

Четверта відмінність у сортуванні з группуванням.
Це простіше пояснити з прикладом. Є дві таблиці: posts та comments.
Потрібно вибрати 5 постів, після останнього у яких були залишені останні коментарі.

select top(5) distinct id
from (
select posts.id, ROW_NUMBER() OVER (ORDER BY comments.posted_at) as rn_id
from posts left join comments on comments.post_id=posts.id) help_query
where help_query.rn_id > 1

В “Denali” не потрібний внутрішній запит. Отож:
select distinct posts.id
from posts left join comments on comments.post_id=posts.id
order by comments.posted_at

Але отримуємо помилку. Error: ORDER BY items must appear in the select list if SELECT DISTINCT is specified.

Добре. Стандартний трюк з групуванням:

select posts.id
from posts left join comments on comments.post_id=posts.id
group by posts.id
order by max(comments.posted_at)

Працює. Але не зовсім вірно, null значення на першому місці.

Отож остаточний варіант такий:
select posts.id
from posts left join comments on comments.post_id=posts.id
group by posts.id
order by CASE WHEN (max(comments.posted_at) is null) then 1 else 0 end DESC, max(comments.posted_at)

На цьому поки що все.
Цей пост переклад: http://wp.me/p1EcKH-c

SQL чи NoSQL ?

Я робив маленьку доповідь на тему SQL і мене спитали, як вирішити, що використовувати SQL чи NoSQL?

Так от дуже просте правило.

LOLCAT правило

Якщо, в базу будуть записані ті самі смішні котики (не важливо у якому вигляді, фотографії, коментарі, програмки про котиків, відео), то можна(і можливо навіть потрібно) використовувати NoSQL.

Інакше, потрібно також подумати про інші причини.
Чи потрібна узгодженість даних? Яка статистика буде використана? (в режимі реального часу – NoSQL, пошук складних тенденцій та інший видобуток даних – SQL)
Чи велика зв’язність даних?

теж саме англійською

Ruby/Go/.NET/SQL та всяка всячина