Выпускник ли, начинающий карьеру разработчика, или человек, переходящий к программированию из другой сферы, остановись и прочти эти семь советов для начинающих программистов от тех, кто занимается этим уже много лет.
Загляните под капот
Знание языка программирования — основа разработки программного обеспечения. Но не менее важно понимать, что скрывается у языка под капотом.
Пит Балл, инженер поддержки в Acquia, сказал: «Многие языки абстрагированы от того, что происходит на уровне системы, и эта абстракция полезна, поскольку позволяет разработчикам быстрее разрабатывать. Но когда вы натыкаетесь на грабли, действительно неприятный баг, нужно понять, что же происходит внутри. Совершенно необходимо тогда уметь заглянуть внутрь процесса, посмотреть системные вызовы и понять, как кусок кода взаимодействует с остальной системой».
Точно так же говорит Роберт Дуглас, вице-президент отдела удовлетворенности клиентов Platform.sh: «Когда я начинал программировать, были вещи, которые я действительно не понимал. Три примера таких вещей — файловые системы, сеть и то, как данные хранятся в памяти. Это значит, что я не обязательно понимал цели некоторых программ, с которыми сталкивался».
Знайте инструменты командной строки
Есть шанс, что как разработчик, вы большую часть времени будете писать код в красивом редакторе или IDE. Однако знание разных утилит командной строки может облегчить вам жизнь.
Ветеран с двадцатилетним опытом, пожелавший остаться анонимным, сказал: «Иногда вы оказываетесь перед машиной с ограниченным набором инструментов и задачей, которую надо сделать прямо сейчас. Знайте командную строку, как пять пальцев; инструменты, такие как find, comm, diff, vi/vim, sed, awk; умейте писать небольшие скрипты прямо в командной строке, чтобы найти файл, который надо подправить прямо сейчас, потому что продакшн сломан, а Джо, который полез своими ручонками не туда, — в отпуске на Фиджи».
Балл, использовавший инструменты Microsoft, а теперь перебирающийся на Linux, соглашается: «Я узнал о командной строке и утилитах *nix все, что возможно. Я могу вспомнить код, который писал год назад, и как я проводил дни или недели, работая над тем, что решается однострочником на grep+awk».
Дебаггер — ваш друг
Как разработчик, вы проведете кучу времени, отлавливая баги. Дейв Вэйрон, биотехнолог-программист в Novartis, выделяет преимущества дебаггера, несмотря на затраты времени на его освоение.
«Учитесь пользоваться дебаггером!», — говорит он. «Потратьте день-два на его настройку. Если вы не видите ожидаемого результата, просто отладьте его: установите точки останова и аккуратно продвигайтесь по коду, особенно по коду сторонних библиотек. Это лишит вас дней разочарования, более того: вы научитесь новому, просто читая чей-то код».
Научитесь писать тесты
Некоторые разработчики уверены в критической важности модульного тестирования, которое подразумевает написание небольших тестов, проверяющих, делает ли код то, что задумал разработчик. Среди этих людей — Ричард Хэндлофф, разработчик баз данных в Strategic Power Systems. Он пишет: «Думаю, что лучший совет, который я могу дать начинающему разработчику — научиться писать хорошие тесты как можно раньше».
Планируйте самообучение
С быстрым изменением технологий меняются системы, языки и инструменты, используемые программистами.
Адам Вульф, мобильный разработчик и основатель Milestone Made, предполагает, что новые разработчики должны быть готовы к изменениям и быть на гребне волны. «Прямо сейчас я хочу сказать, что вы должны быть готовы осваивать новый стек технологий примерно каждые четыре года. Хорошие базовые знания всегда будут актуальны, но инструменты и технологии, которые вы будете использовать каждый день, будут меняться не реже, чем с названной частотой».
«Проекты больше не пишутся на одном языке и стеке технологий», сказал анонимный разработчик. «Вы никогда не ограничитесь работой только с одной технологией в одном проекте. Привыкайте к переходу из проекта в проект и от одних языков и технологий к другим».
Кооперируйтесь
Несмотря на то, что обычно разработчики работают обособленно, им приходится взаимодействовать с другими людьми. Бен Миллер, CTO Sinclair Digital Ventures, подчеркнул важность готовности к командной работе для вашей карьеры: «Большие проекты — это куча движущихся деталей, собранных вместе, и то, как они соединяются и разделяют проблемы, создаст невероятные инженерные сложности, если вы не будете осторожны», пишет он.
«Прежде чем браться за улучшение одного алгоритма, соберитесь с командой и убедитесь, что нет способа разделить проблему на всех, сделав ее проще. Разработка — командная игра!».
Подтверждая важность командных навыков, Вейрон говорит: «Если вы не можете понять самостоятельно, как работает этот интерфейс, попросите помощи. То, что вы считаете свою работу шедевром, не делает ее шедевром. Как в колледже, у других людей в комнате те же вопросы или вопросы, на которые только вы можете ответить. Разрабатывайте отношения с коллегами. Часто просто озвучивание проблемы вызывает озарение».
Анонимный источник, разделяющий мнение о важности командной игры, говорит: «Соберитесь и делайте что говорят, даже если это вас утомляет. Но осторожно: вы рискуете застрять так надолго».
Разрабатывайте для себя вне работы
Миллер дает достаточно интересный совет, который не кажется очевидным на первый взгляд. «Разработка для себя — путь к повышению», — говорит он. «Найдите простое решение проблемы, сделайте код понятным и легко модифицируемым, и вам подкинут еще больше работы. Со временем у вас даже будут просить совета» — объясняет он. «Короче говоря, стремление к спокойной безопасной работе затормозит карьеру».
Перевел: Андрей Никифоров
___
Полезные материалы для начинающих разработчиков от образовательного IT-портала GeekBrains:
Запись вебинара "Все, что вы хотели знать о профессии программиста"
Бесплатный онлайн-курс для начинающих "Основы программирования"
Комментарии (97)
Shultc
07.04.2016 17:41+10Семь вещей, которые нужно знать начинающему программисту:
- Двоичная система счисления
- Типы переменных
- Логические операции
- Блок-схемы
- Циклы
- Функции
- Рекурсия
EminH
07.04.2016 17:49Двоичная система счисления
а можно узнать почему?
не программист, но со всем остальным согласенZibx
07.04.2016 17:54-4Не обязательно двоичная, но ту, которую использует процессор под который разрабатываешь — знать обязательно. От этого зависит длина слова, от неё зависит определение сложности алгоритма.
EminH
07.04.2016 18:09+8если вы про Low-level типа ассемблера, то да.
а как работает интегральная схема процессора или трансформатор в блоке питания надо знать?
п.с. я не спорю, просто интересно знать более конкретное обоснованиеOgi
08.04.2016 09:27А ещё знание двоичной системы нужно, чтобы понимать, почему 0.1 * 10 не равно единице.
Zibx
08.04.2016 16:45-1Я про тот low level, который доходит до самого верха. Предположим что у нас есть алгоритм сортировки. Хороший алгоритм, все знают что у него логарифмическая сложность. Но есть один нюанс — эта сложность будет только если у нас переменная меньше либо равна разрядности процессора. Если же мы возьмём и воспользуемся в алгоритме 128 битными переменными, то в лучшем случае всё ухудшится в 4 раза, а скорее всего выползет квадрат. А теперь вопрос — как программист без знаний низкого уровня будет оптимизировать приложение когда упрётся в боттлнэк? Он может поставить больше серверов, но там вылезают эта же двоичная система, но приминительно к сетям. Ровно в тот момент когда для программиста заканчивается вся магия низкого уровня — приходит понимание. Что оптимизации, что хайлоада. Я бы не сказал что это ненужные знания, я соглашусь что они могут не пригождаться очень долго, возможно даже — никогда, но вот ровно до того момента пока есть запас производительности.
VolCh
08.04.2016 17:48+1Если же мы возьмём и воспользуемся в алгоритме 128 битными переменными, то в лучшем случае всё ухудшится в 4 раза
То есть сложность не изменится :)Zibx
08.04.2016 19:51Так «в лучшем» же :)
Константа резко поплывёт. Обычно одна инструкция за такт (+\-, иногда могут несколько уместиться), а тут резко все действия становятся медленнее. И нам ещё повезло что современный процессор похож на многоленточную машину тьюринга, во времена одноленточной задавшему вопрос рассмеялись бы в лицо!
Shultc
07.04.2016 17:57+2Это азы работы компютера и, как по мне, их стоит знать как и историю своей страны (не из-за пользы). Так же, знание бинарки сильно позволяет экономить ресурсы. Ибо обычный человек думает, что в 3-х bool переменных можно хранить 3 единицы информации, а программист должен знать, что это 8 единиц информации.
Ну, и плюс, моё, личное — я не люблю поверхностную информацию. Она очень часто ведёт к неправильным выводам. Поэтому знание бинарки, как и базового устройства железа считаю обязательными.EminH
07.04.2016 18:07+1в 3-х bool переменных можно хранить 3 единицы информации, а программист должен знать, что это 8 единиц информации.
это конкретно bool, про что уже говорит пункт №2Shultc
07.04.2016 18:09+1Пункт №2 заставит понимать, что это за тип. А не концепцию хранения и сортировки массивов из него.
Также мне кажется что нельзя до конца понять логические операции не зная бинарки… Поэтому и написал на первом месте — она мать всего (утрирую)
alexkunin
07.04.2016 18:50+2А можете пояснить, пожалуйста, про 3 и 8 единиц информации? На сколько я знаю, в 3-х bool можно хранить 3 бита, бит — это минимальная единица информации. И если в этих трех битах хранить число в двоичном виде (т.е. каждый бит — разряд двоичного числа), то это число может принимать значения от 0 до 7 (после перевода в десятичную систему исчисления).
Можно сказать, что в трех битах можно хранить указание на одно из 8 значений, т.к. 3 bool могут представлять 8 уникальных комбинаций, каждой из которых можно сопоставить что-либо (число, цвет, имя, объект). Но по этой логике в одном bool можно хранить две единицы информации, а это не так — ведь бит уже одна, минимальная единица информации. А то ведь можно было бы сделать прикольный архиватор, который сжимает любые данные до 1-го бита. ;)Blumfontein
08.04.2016 07:19>> А то ведь можно было бы сделать прикольный архиватор, который сжимает любые данные до 1-го бита
Так сразу в /dev/null, чего мелочиться :)
Pazzik
08.04.2016 10:08-1Но по факту, все равно один bool занимает 8 бит в памяти. И три bool можно уместить в 8 бит минимум, и то через битовые маски. Так что в некотором роде комментатор прав.
Urvin
08.04.2016 10:17Но по факту, все равно один bool занимает 8 бит в памяти.
Не факт. Зависит от компилятора.
Alexeyslav
08.04.2016 10:22+3Фиг там, в современных языках логическая переменная занимает одно машинное слово — используется тип INTEGER. С чем это связано? А банально с производительностью… современному процессору сложнее оперировать байтами — для этого ему нужно из кеша/памяти извлечь слово и отсечь всё лишнее — а это дополнительные операции и соответственно замедление работы. Ещё хуже — использовать для этого отдельные биты.
Но для ХРАНЕНИЯ данных на внешних носителях экономичней всего хранить логические переменные именно в БИТАХ, но этим как правило брезгуют — лишняя морока ради экономии 128 байт на логических переменных из сотен килобайт сопутствующих данных. Шевелится начинают когда выигрыш более 50% или объём данных находится на грани, чтобы уложится в размер определённого слота и т.д.
alexkunin
08.04.2016 10:26Вы о каком языке говорите? И — для некоторых языков — о какой реализации? Ну, и, в любом случае, есть C, в нем есть битовые поля.
На счет умещения 3 булей в 8 бит я не понял, простите. До этого вы сказали, что один буль занимает 8 бит. Как же 3 буля в 8 бит влезут?
Чтобы избежать лишних дискуссий:
есть логический тип — bool, принимает всего два значения, теоретически должен поместиться в 1 бит, потому как и представляет собой ровно 1 бит (кстати, и от этого могут быть отступления — посмотрите optionals в Swift);
в разных языках он называется и реализован по-разному, и может занимать физической памяти больше, чем 1 бит, тут я с вами согласен — может и байт занимать, может и машинное слово (которое может быть и 4 бита, кстати — разные есть процессоры);
есть языки, где один boolean может занимать один физический бит памяти;
и еще есть выравнивание, например буль может быть представлен как байт (например), но механизм распределения памяти выделяет куски с адресами, кратными 16 байт (или 4096, или 4 — разные есть ситуации), и в итоге однобайтный буль для хранения потребует больше места.
Alexeyslav
08.04.2016 10:28Несколько не так, переменная типа BOOL это на самом деле INTEGER, который равен машинному слову используемой системы. т.е. нынче это 32/64 бита. Мало кто работает с BOOL как с отдельными битами т.к. из-за этого сильно страдает производительность и имеет смысл только для долговременного хранения состояния и в случае массовой обработки бинарных состояний(маски прозрачности изображений?). В целом, работать с битами процессору очень накладно, он умеет эффективно работать только группами бит по 32-64 за раз. А некоторые системы работают большими порциями — например по 1024 бита за раз(привет видеокартам и аналогичным числовым ускорителям) и им крайне накладно работать с одиночными битами.
skjame
08.04.2016 11:57+1Как-то я вас не понимаю. Операция по установке бита занимает от силы 3-4 такта процессора, для снятия 4-5. Слишком накладно для процессора это с fload/double работать, вместо fractional
И потом, следуя Вашей логике выходит, что и в степень двойку возводить лучше умножением чем сдвигом?
У Вас в профиле указано, что работа связана с МК и ассемблером… но почему-то мне страшно представить код после Вашей оптимизации.
Sorry за оффтопик. Если по теме, то я считаю, что обязательно нужно знать операции с фиксированной точкой.Alexeyslav
08.04.2016 12:46Вы не учитываете что при этом если переменная не находится в кеше L1 нужно подтянуть её из оперативки, а это может занять уже до сотни тактов и очень неочевидно. И при этом процессор хоть из кеша хоть из оперативки вынужден читать словами, т.е. если надо где-то изменить один бит он читает 64/128 бит меняет их и ложит обратно. При этом операции с кешем могут затрагивать блоки гораздо большего размера — например страницу кеша в 64 байта… т.к. процессор/чипсет не умеет извлекать одиночные байты/слова и вынужден при операциях с данными оперировать объёмами кратными размеру страницы кэша, что в итоге выливается в очень много тактов простоя из-за таких простых операций, зато в отличие от бит он УЖЕ способен работать с числами с плавающей запятой гораздо быстрее — результат вычисления над числами с плавающей запятой появляется уже через 2..10 тактов. А в некоторых системах умножение матриц чисел 8x8 занимает 2..3 такта. По сравнению с этим, операции с битами выглядят крайне неэффективными.
В любом случае, работать с битами проще всего только в регистрах что и практикуется, но одиночное использование логической переменной очень не оптимально.
SidMeier
07.04.2016 18:45Основная форма представления данных в самых распространенных, на сегодняшний день, ВС. Сильно поможет «заглянуть под капот».
Alexeyslav
08.04.2016 10:13+1Она тесно связана с элементарными логическими операциями.
К тому же, понимание двоичной системы счисления даёт обьяснение таким странным магическим числам как 1024, 32768, 65535 и многим другим непонятным ограничениям(ограничение размера файла в 4Гб на FAT32, 32Гб на размер винчестера в старых системах...).
Так же, приноси понимание почему математическая операция 10.0/10.0 = 1.0 не имеет смысла и очень часто даёт ложный результат, почему к примеру не всегда получится прибавить 1 к числу вроде 1E+37. Всё это завязано на двоичную систему счисления чуть более чем полностью.
noGeek
07.04.2016 20:47Можешь посоветовать книгу начинающему?
Что прочесть в первую очередь?Fedcomp
07.04.2016 21:33-3Вам для начала стоит определиться каким программированием вы хотите заняться. На вскидку могу определить три области, железячники, которые начинают с ардуино и продолжают на микроконтроллерах, системные программисты, которые пишут прикладные программы и веб разработчики, которые строят сайт. Это все очень грубые упрощения.
noGeek
07.04.2016 22:18Вы описали очень интересные области. Если судить так, то вот вопрос: Что можете посоветовать для начинающего в области программирования, ну т.е. написание системных программ?
BlackRaven86
08.04.2016 17:12Могу порекомендовать классику: Брайан Керниган, Деннис Ритчи. Язык программирования C.
Особенно полезно будет, если программировать под *nix.
MacIn
08.04.2016 00:53+3системные программисты, которые пишут прикладные программы
Это уж слишком грубое упрощение.
VolCh
08.04.2016 06:48+2Системы программисты пишут, как ни странно, системные программы, а прикладные программы, включая веб, пишут прикладные программисты.
ZaEzzz
08.04.2016 10:08Я не знаю в какой сфере вы хотите писать (может вы и сам еще не определились), но вкупе с литературой вашего направления рекомендую Стива Макконнелла — Совершенный код.
Сразу учитесь структурировать и оформлять свои мысли, а параллельно сразу учитесь писать тесты.noGeek
08.04.2016 18:55Для начала советуют изучить PHP. Но как я понял не мало важны и знания аппаратного обеспечения. Я хочу стать хорошим специалистом. Буду читать книги. Большое спасибо.
Yak52
08.04.2016 06:17+3Причем рекурсию надо знать, что бы потом бежать от нее подальше. Она хороша при обучении, алгоритмы с рекурсией красивы и как правило занимают немного строк кода. Но когда выясняется, что например алгоритм обхода графа падает при обходе реального графа с десятками тысяч параметров, приходит понимание, что алгоритмы из учебника в реальном мире спотыкаются о такие ограничения операционной системы, как размер стека.
AlexeiZavjalov
08.04.2016 08:22К сожалению, об этом часто не задумываются даже очень опытные программисты. Как пример — недавняя проблема в компиляторе андроид, использовавшемся в миллионах телефонов по всему миру:
https://android.googlesource.com/platform/art/+/e5f01223ae03b89767dc7881d75dca061121ee36%5E!/
Обход графа был реализован рекурсивным алгоритмом и вызвал то самое переполненение стека.
bonv
08.04.2016 10:08Не всегда это так.
В функциональных языках многие вычисления естественно выражать в виде рекурсивных функций.
Т.к. транслятор может заменять хвостовую рекурсию на итерацию.JIghtuse
08.04.2016 13:00+1Никто и не говорит, что всегда. Но многие алгоритмы проще выражаются не хвостовой рекурсией, и здесь компилятор уже беспомощен. К примеру, такой "красивый", прямо математичный, факториал:
pure ulong factorial(uint n) { return n <= 1 ? 1 : n * factorial(n - 1); }
Чтобы рекурсию сделать хвостовой, надо уже городить вложенную функцию или нечто иное.
vadoo
09.04.2016 12:06А если ничего не городить и написать вот так
factorial(x, fac) {
if (x == 1)
return fac;
else
return factorial(x-1, x*fac);
}alexkunin
09.04.2016 13:24Так вы уже и «нагородили»: факториал по определению функция с одним параметром, а у вас два, и конечному пользователю нужно давать осмысленное значение fac. Вы можете это спрятать во внешнюю функцию с одним параметром, которая будет давать начальное значение fac внетренней функции, но вот и получится «городить вложенную функцию».
Стало бы чуть-чуть лучше, если переформулировать так:
function factorial(x, fac) {
if (x <= 1)
return fac || 1;
else
return factorial(x — 1, x * (fac || 1));
}
Т.е. не нужно давать начальное значение fac, но все равно вы оставляете на публику детали реализации: «второй параметр должен быть равен 1 или опущен, для служебного пользования». Ну, и опять же, это уже не чистый алгоримт факториала, а его смесь с деталями реализации. Это и есть «городить».
Кстати, обратите внимание на изменение условия перед первым return — так можо избежать бесконечно рекурсии (если враг народа даст на вход дробный, нулевой или отрицательный x).vadoo
09.04.2016 16:36«Огласите весь список, пжлста»(ц)
Вам нужна функция с одним параметром? Нет проблем:
tail_fac(N) -> tail_fac(N,1).
tail_fac(0,Acc) -> Acc;
tail_fac(N,Acc) when N > 0 -> tail_fac(N-1,N*Acc).
Теперь не подойдёт из-за наличия 2-х функций?
Тогда возьмите язык, в котором есть возможность задавать значения по-умолчанию для аргументов функции.alexkunin
09.04.2016 16:46Я что-то не пойму, о чем вы. Ваша реплика: «А если ничего не городить и написать вот так...». Это был ответ на «надо уже городить вложенную функцию». И вы сами пришли к тому же, но под лозунгом «ничего не городить». То, что у вас совпадает имя, не значит, что вы решили задачу одной функцией, т.к. функция — это имя + сигнатура (или хотя бы арность), и у вас фактически две разные функции — как и было в изначальном посыле в комментарии JIghtuse.
vadoo
09.04.2016 19:54Мы с Вами едины в непонимании))
«Чтобы рекурсию сделать хвостовой, надо уже городить вложенную функцию...» — показал, как можно обойтись без вложенной функции
"… факториал по определению функция с одним параметром, а у вас два..." — привел пример с одним параметром и без вложенной функции
И всё равно мимо кассы.
Поэтому и попросил огласить весь список требований, а то создается впечатление(мозгами понимаю, что скорее всего ложное), что требования выдумываются на ходу.alexkunin
09.04.2016 20:12+1Не совсем понял, где тут были требования. Было утверждение «Чтобы рекурсию сделать хвостовой, надо уже городить вложенную функцию или нечто иное.»
Ваши оба примера как раз подходят под «нечто иное» (первый пример, добавляем «технический» второй параметр) и под «вложенную функцию» (второй пример, у вас там две функции, и вторая не нужна пользователю — ее бы спрятать (вложить), но язык не позволяет).
Представьте себе, что вам нужна функция sin(x), вы направляете в отдел тригонометрии запрос, и вам возвращают решение: вот super_smart_sin(x, k), и вы такой «что за k? что туда передать?», а они вам «не обращайте внимания, всегда передавайте 1». Как-то не очень, правда?
Ну, а второй пример — как я уже сказал, это две разные функции, причем вторая — tail_fac(N, Acc) — эквивалентна первому примеру. Т.е. вы к первому примеру добавили еще одну функцию, которая избавляет пользователя от проблемы, описанной в предыдущем абзаце.
Итого, вы все правильно сделали: переписали исходный «неудобный» код для вычисления факториала в хвостовую рекурсию, при этом как раз прибегнули к «городить вложенную функцию или нечто иное». Все в рамках исходной задачи.
Единственный момент, с которым я не могу согласиться — «Тогда возьмите язык, в котором». Это хорошо в общем случае некой абстрактной академической задачи. Но если это прикладная задача, например эта функция понадобилась в проекте на PHP, или это пример на лабораторной по C++, то выбрать язык никак не получится. А так — можно было бы выбрать язык, в котором факториал — функция из стандартной библиотеки. Ну, тоже решение, да.vadoo
09.04.2016 22:46> Не совсем понял, где тут были требования.
Если один, другой варианты не подходят это означает, что существуют требования из-за которых варианты не подходят. Верно?
> Ваши оба примера как раз подходят под «нечто иное»
Согласен. Оба примера подходят под «нечто иное». Но, если последовать такому подходу, то нерекурсивное решение попадает тоже в категорию «нечто иное».
> Представьте себе, что вам нужна функция sin(x)…
Введите в область видимости функцию-обертку с нужным количеством аргументов.
> Единственный момент, с которым я не могу согласиться — «Тогда возьмите язык, в котором»
Подумайте, зачем придумали такое количество языков? И может ли это быть связано с тем, что некоторые языки не предназначены для решения некоторых задач?))
P.S. кстати, требований по поводу языка никто не предъявлялalexkunin
09.04.2016 23:33> Если один, другой варианты не подходят
Верно. Они не подходят под ваше утверждение «А если ничего не городить». Определение «городить» было дано выше.
> Но, если последовать такому подходу, то нерекурсивное решение попадает тоже в категорию «нечто иное».
«Чтобы рекурсию сделать хвостовой» означает, что нерекурсивное решение не подходит вообще. Т.е. задача стояла сделать из общей рекурсии хвостовую. Избавление от рекурсии не решает задачу переделки ее в хвостовую. Но решает задачу «посчитать факториал». Которая уже была решена.
> Введите в область видимости функцию-обертку
Я всего лишь хотел сказать, что заставлять пользователя давать функции непонятные константые аргументы несколько странно.
> не предназначены для решения некоторых задач?))
А если ваша задача включат в себя множество подзадач, каждая их которых решается лучше всего на своем, отдельном языке? Или даже так, вам дали проект, вы выбрали язык исходя из описания, работаете, пишете, и тут вдруг приходит дополнение, и там посчитать факториал нужно, а ваш язык даже хвостовую рекурсию не поддерживает (PHP какой-нибудь). Если идеальный язык для задачи, есть подходящий, есть неподходящий подходящий. Главное выбрать такой, который подходит для большинства задач, составляющих проект.
> P.S. кстати, требований по поводу языка никто не предъявлял
И никто не говорил, что у вас неудачный выбор языка.vadoo
10.04.2016 01:08> Верно. Они не подходят под ваше утверждение «А если ничего не городить».
> Определение «городить» было дано выше.
Подходят, по причине того, что дополнительные условия появлялись уже после приводимых решений.
Кстати, могли бы Вы процитировать определение «городить» во избежании путаницы?
> «Чтобы рекурсию сделать хвостовой» означает, что нерекурсивное решение не
> подходит вообще. Т.е. задача стояла сделать из общей рекурсии хвостовую.
> Избавление от рекурсии не решает задачу переделки ее в хвостовую. Но решает
> задачу «посчитать факториал». Которая уже была решена.
Простите, позднее время суток и самочувствие не дают понять «кто на ком стоял». Вы уж не серчайте))
> Я всего лишь хотел сказать, что заставлять пользователя давать функции
> непонятные константые аргументы несколько странно.
Замечательно)) Не хотите заставлять — не надо заставлять. Мы ведь совсем не об этом говорим, не так ли?
> А если ваша задача включат в себя множество подзадач, каждая их которых
> решается лучше всего на своем, отдельном языке?
Посмотрите на игрушки, в которых используется не один язык и каждый для своих задач. Без конкретных примеров задач, которые нужно решать говорить можно долго.
> Или даже так, вам дали проект, вы выбрали язык исходя из описания, работаете,
> пишете, и тут вдруг приходит дополнение, и там посчитать факториал нужно, а ваш
> язык даже хвостовую рекурсию не поддерживает (PHP какой-нибудь).
А давайте немного не так? Представим, что надо посчитать не факториал, а что-то «иное», что составляет львиную долю всего проекта. И тут оказывается, что при рекурсии экономятся ресурсы, а язык уже выбран.
> И никто не говорил, что у вас неудачный выбор языка.
Я снова обращаю внимание, что изначально не было требований к языку, но появились потом и уже с учетом новых требований оценивался предложенный мной вариант.alexkunin
10.04.2016 01:29+1> Подходят, по причине того, что дополнительные условия появлялись уже после приводимых решений.
В комменте, на который вы отвечали, последняя строка: «Чтобы рекурсию сделать хвостовой, надо уже городить вложенную функцию или нечто иное.» Автор коммента указал, что для выполнения задачи — переделка рекурсии в хвостовую для облегчения жизни компилятору — потребуется что-то «городить», а именно: «вложенную функцию» или «что-то еще». Вы и сделали вложенную функцию (вторая попытка) или что-то еще (первая попытка). Кроме мелочей типа проверки на равенство нулю, оба решения работают. У обоих есть недостатки. Но все-таки они работают.
Сыр-бор в том, что вы — как мне показалось по вашей фразе «А если ничего не городить и написать вот так» — утверждали, что ваше решение не «городит вложенную функцию». Я же указал, что вы, отбросив вложенность, сделали другое — добавили «магический» константный аргумент. А потом вы же этот недостаток устранили — с помощью реализации со вложенной функцией: у вас есть обертка, которая вызывает спец-функцию с рекурсией.
> Простите, позднее время суток и самочувствие не дают понять «кто на ком стоял». Вы уж не серчайте))
Так зачем же вы отвечаете в заведомо неподходящем состоянии? Утро вечера мудренее — завтра и ответили бы. Может и лишней иронии поубавилось бы.
> Без конкретных примеров задач, которые нужно решать говорить можно долго.
Я всего лишь указал, что сменить язык — спорное решение. В таком случае можно ведь решить задачу «накормить гостей» методом «поубивать их, а раз мертвые на голод не жалуются — значит, не голодные». А еще это похоже на то, как на вопрос вроде «как же в Си ассоциативные массивы сделать?» приходит ответ «возьмите PHP». Ну, да, выход, в некотором роде.
> Представим, что надо посчитать не факториал, а что-то «иное», что составляет львиную долю всего проекта.
Как вы сами заметили, без конкретного примера говорить можно долго.
> Я снова обращаю внимание, что изначально не было требований к языку
Покажите мне то место, где эти требования появились. Цитатой, если не затруднит.
s4gear
08.04.2016 10:08-11Я дико извиняюсь, но:
1. Что за двоичная система «счисления»? Если вы про булевую математику, но вроде как используется только в вентильной системе, до которой вас не допустят. И на секунду, процессор оперирует командами вроде как.
2. Может быть типы данных? А еще лучше разобрать разницу между статичной типизацией и динамической?
3. Логические операции… Это вообще что значит? Паттерны?
4. Другими словами UML.
5. Почему циклы? а почему не массивы?)
6. Какие функции? или вы имели ввиду методы? ну тогда это ведь зависит от фреймворка и парадигмы программирования.
KvanTTT
08.04.2016 11:47+2Семь вещей, которые нужно знать начинающему программисту:
- Двоичная система счисления
- Типы переменных
- Логические операции
- Блок-схемы
- Циклы
- Функции
- Семь вещей, которые нужно знать начинающему программисту
Zealint
07.04.2016 17:49+22Честно говоря, я очень плохо отношусь к статьям подобного рода: «21 способ похудеть, лёжа на диване» или «35 мест, где должен побывать турист». То же касается программирования. Тут один совет: у человека должна быть голова на отведённом ею эволюцией месте, а конкретный способ организации своей деятельности он сам определит, исходя из конкретных условий работы и задач, которые нужно решать.
Вот смотрите сами: «научитесь писать тесты». Что это за совет вообще? Давайте я попробую давать подобные советы: «научитесь программировать без ошибок», «научитесь решать задачи», «научитесь писать код», «научитесь читать код». Ну вот! Теперь Вы на 100500 шагов впереди тех, кто этих советов не знает…Zealint
07.04.2016 17:55+10Я всё-таки попробую улучшить статью. Восьмой совет.
Научитесь решать задачи
Некоторые разработчики уверены в критической важности умения решать задачи, которое подразумевают написание кода, делающего то, что задумал разработчик. Среди этих людей — Васька Фёдоров, мой сосед, разработчик баз данных в Seventh April Systems. Он пишет: «Думаю, что лучший совет, который я могу дать начинающему разработчику — научиться решать задачи как можно раньше».alexkunin
07.04.2016 18:55+2Разрешите дополнить: «Научитесь ставить задачи». Себе, другим — уже не важно. Четко поставленная задача содержит в себе половину решения.
troyanskiy
07.04.2016 18:46+4Как-то преподаватель в университете озвучил мне 2 закона.
1. Написанный код с первого раза запустится с ошибкой.
2. Если он запустился без ошибки, значит он работает не правильно.
i360u
08.04.2016 06:13+2Научитесь думать абстрактно.
Учитесь проектировать Системы.
Учитесь управлять зависимостями.
Учитесь декомпозировать.
Учитесь писать читаемый код.
Изучите основные алгоритмы.
Учитесь упрощать все и везде, насколько это возможно.
Учитесь писать гибкий расширяемый код.
Познайте среду исполнения с ее возможностями и ограничениями.
Ну и авторитетная цитата: "Учиться, учиться и еще раз учиться!" В. И. Ленин.
Aleco
08.04.2016 08:54У вас последний абзац переведен неправильно. Там смысл такой — что пишИте хороший код, который можно отдать другим на поддержку. И люди к вам потянутся. И работа будет. А если держаться за свое место и подминать под себя неподдерживаемый другими код — то перестанешь расти как профессионал.
Kolyuchkin
08.04.2016 09:37Как-то уже давно, лет 8-10 назад, ко мне на работу устроился студент-отличник (в зачетке все пятерки). Он успорял, что много знает и что умеет программировать. На первый же вопрос, который я обычно задаю всем новичкам, он ответил (со знаком «минус»). Вопрос был таков: «Как наиболее просто узнать значение заданного бита в 16-разрядном слове?» Он написал функцию на ассемблере в >100 строчек кода, применив, наверное, весь знакомый математический аппарат — и это только для выделения заданного бита. На слово мне он не хотел верить, что я все это могу уместить в «одну строчку» кода на том же ассемблере)))))))))) Пришлось доказать))))) Работал он не долго — сами догадаетесь почему))) Потом он устроился в банк, в кредитный отдел… вскорости банк «лопнул» (и тут я закончил линию логических умозаключений))))))
Все это я к чему повествую? А к тому, что не менее важно уметь пользоваться знаниями! Навыки анализа задачи, поиска и сопоставления знаний нужно вывести на уровень условных рефлексов. А без алгоритмического мышления (способности строить алгоритмы) стать программистом (хорошим) очень сложно… Даже имея обширные знания в различных сопутствующих областях…
З.Ы.
Сейчас у меня работает девушка наподобие описанного студента… Зачатки навыка алгоритмизации у нее появились, когда я ей стал давать задачи на GO))) (комплимент этому ЯП)
vlreshet
08.04.2016 09:46Чтобы «заглянуть под капот», и понять как работают ЯП — нужно не только посмотреть исходники какого-нибудь языка, но и попробовать написать свой. Не обязательно на ассемблере и по хардкору, не обязательно супер производительный, не обязательно какой-то инновационный и с уникальными фичами — а просто Тьюринг-полный язык. Да хоть компилятор к брейнфаку. И во время разработки откроется и осознается очень много интересных и сложных вещей.
Arastas
Правило, которое выучил я (навеяло заглавной картинкой):
Никогда не ставьте кофе так близко от рабочего ноутбука, любая чашка однажды опрокинется. Минимум на расстоянии вытянутой руки. Лучше, на другом столе.
Krypt
И желательно, чтобы он был без сахара — когда вы его таки разольёте — будет проще отмывать.
i360u
Ваш совет реально полезнее всего, что написано в посте.
RealFLYNN
Вы когда-нибудь пили кофе по 20 000 рублей за чашку? И я пил. Ваш совет крайне полезен.
bonv
Буквально пару дней назад как менял клавиатуру на ноутбуке по этой причине.
radiolok
Это был худший розыгрыш себя самого на первое апреля.
BlackRaven86
И перед собой тоже не стоит ставить — очень легко задеть рукой. Когда-то я у меня была такая привычка, но после нескольких инцидентов я научился ставить чашку далеко в стороне :)
Abbath
Если уж очень хочется кофе или чая, то можно взять большую чашку с широким основанием. Я использую чашку объемом 800 миллилитров. Даже при поперечном ударе в верхнюю кромку она не переворачивется, в отличие от обычных чашек.