За исключением нескольких аномалий, когда вы начинаете обучение игре на музыкальном инструменте, никто не начинает с виртуоза. Изучение такого навыка требует терпения и внимания к практике и применению, что, если быть честным, является работой, которая никогда не бывает «завершенной» на протяжении всей карьеры музыканта. Никто не исполняет концерт после недели занятий. Сначала они должны вникнуть не только в физический аспект игры на инструменте, но и попытаться расшифровать лабиринт теории, окружающей «музыку», какой мы ее знаем сегодня (или, по крайней мере, «гармонический стиль европейских музыкантов 18-го века», но это тема для другого дня). Музыканты обычно получают знания о конкретном инструменте наряду с более фундаментальными концепциями музыки, которые впоследствии позволяют гораздо легче исследовать различные инструменты или музыкальные стили.

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

1) Ошибки — ваши друзья

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

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

2) Циклы и итерация

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

Глубокое понимание того, как использовать циклы, перейдет на любой язык кодирования и позволит разработчику быстро писать сложную логику, просто изучив синтаксис языка. Один из наиболее распространенных типов циклов обычно называется циклом for, который берет список элементов и применяет фрагмент кода к каждому элементу в этом списке. Это можно рассматривать как «итерацию» по списку. Хотя способ написания цикла for будет варьироваться от языка к языку, эта концепция является фундаментальной для кодирования в целом. Вот пример одного и того же цикла for на 4 разных языках кодирования. Я хочу, чтобы мой код брал список чисел от 1 до 5 и выводил каждое число по одному на консоль:

Рубин:

array = [1, 2, 3, 4, 5]
array.each do |num|
    puts num
end

Питон:

array = [1, 2, 3, 4, 5]
for x in fruits:
  print(x)

JavaScript:

const array = [1, 2, 3, 4, 5] 
for (num of array) {
    console.log(num)
}

C#:

int[] array = {1, 2, 3, 4, 5};
foreach (int i in array) 
{
    Console.WriteLine(i);
}

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

3) If/else if/else Условные выражения (ветвление)

По данным Wired, типичный современный автомобиль содержит более 100 миллионов строк кода! Теперь многое из этого не обязательно связано с эксплуатацией автомобиля. Он содержится в GPS, развлекательной системе или других второстепенных системах, однако большинство людей не осознают, что между вашей ногой на педали тормоза и физическими тормозами, которые на самом деле останавливают ваш автомобиль, существуют условия «если/иначе».

Утверждение «если» является необходимым компонентом наших основ кодирования, и его концепция довольно проста. Они позволяют нам сравнивать фрагменты информации и запускать определенный код на основе этого сравнения. Слово «если» заставляет код читаться как английский, и это ключевое слово довольно стандартно для большинства языков программирования. Обычно это сопровождается некоторой формой «иначе, если» и «иначе». Мы можем задать вопрос, и если вопрос «если» верен, код «если» будет запущен. Если это ложно, но вопрос «иначе, если» верен, тогда этот последующий код будет запущен. Наконец, если ни один из этих вопросов не верен, будет запущен код «else». Например, мы можем закодировать такое утверждение, как «Если солнечно, напишите «Я люблю солнечный свет!», а если идет дождь, напишите «Я ненавижу дождь!». Если не солнечно и не идет дождь, напишите «Интересно, будет ли дождь?»

Вот наш оператор if на нескольких языках:

Рубин:

if weather == "sunny"
  puts "I love the sunshine!"
elsif weather == "raining"
  puts "I hate the rain!"
else
  puts "I wonder if it will rain?"
end

Питон:

if weather == "sunny":
  print("I love the sunshine!")
elif weather == "raining":
  print("I hate the rain!")
else:
  print("I wonder if it will rain?")

JavaScript:

if (weather === "sunny") {
  console.log("I love the sunshine!")
} else if (weather === "raining") {
  console.log("I hate the rain!")
} else {
  console.log("I wonder if it will rain?")
}

C#:

if (weather == "sunny")
{
  Console.WriteLine("I love the sunshine!")
} 
else if (weather == "raining") 
{
  Console.WriteLine("I hate the rain!")
} 
else
{
  Console.WriteLine("I wonder if it will rain?")
}

Операторы if/else if/else составляют основу большинства современных логик программирования. При изучении нового языка программирования это ваша гамма до мажор. Узнай это первым!

4) Переменные

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

Причина, по которой эта важная фундаментальная концепция является столь важной для ознакомления, заключается в том, что разные языки имеют немного разные методы работы с переменными. В современных языках программирования есть 2 типа переменных, Python и JavaScript, например, используют только ссылочные типы, в то время как другие (например, C#) используют оба:

а) Тип значения:

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

б) Тип ссылки:

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

Переменные являются неотъемлемой частью каждого языка программирования, и важно иметь общее представление о том, как разные переменные ссылаются на свои данные, так как это играет большую роль в том, чтобы назначения переменных в вашем коде работали должным образом. Некоторые языки также трудно определить в этих конкретных терминах, но важно, чтобы вы четко понимали, как язык, который вы используете, обрабатывает переменные. Являются ли переменные, подобные физическим объектам, хранящими значение, или они указывают на объект где-то еще? См. ссылку в справочниках для списка типов переменных на разных языках. Ruby может использовать тест, чтобы убедиться в этом:

a = 10
 => 10
a.object_id
 => 21
b = a
 => 10
b.object_id
 => 21
a = 15
 => 15

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

Сначала мы присвоили переменной a значение 10. Она ссылается на числовой объект с идентификатором 21.

Затем мы присвоили переменной b значение a. b теперь также ссылается на тот же числовой объект с идентификатором 21.

Наконец, мы повторно присвоили a значение 15. Каково теперь значение b? Как вы думаете, каким будет идентификатор объекта этих двух переменных?

a
 => 15
a.object_id
 => 31
b
 => 10
b.object_id
 => 21

Переменная b остается равной 10. Это означает, что переменные не связаны глубоко друг с другом и ссылаются на отдельные объекты в памяти. Итак, эти переменные являются ссылочными типами.

Подобные тесты могут выявить природу переменных, которые мы используем в конкретном языке.

5) Функции и абстракция

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

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

Почти все языки программирования имеют систему написания блоков кода, которые можно повторно использовать и вызывать при необходимости. Некоторые языки также используют «объектно-ориентированное программирование», позволяющее разработчику определять «классы» и создавать объекты, которые имеют свои собственные функции. Эти классы и функции определены и хранятся в памяти. Давайте определим наше пианино. Я буду использовать Ruby для этого примера:

class Piano
  def press_key(note_id, velocity)
    puts "Playing note #{note_id} at volume #{velocity}"
    hammer = Hammer.find_by_note(note_id)
    hammer.strike(velocity)
  end
end 
class Hammer 
  attr_accessor :note
  @@all = []
  def self.all
    @@all
  end
  def initialize(note)
    @note = note
    self.class.all << self
  end
  def strike(velocity)
    puts "hammer striking the string at strength #{velocity}"
  end
  def self.find_by_note(note_id)
    self.all.find{|hammer| hammer.note == note_id}
  end
end
piano = Piano.new
Hammer.new(1)
Hammer.new(2)
Hammer.new(3)
piano.press_key(1, 100)

Это может показаться большим количеством кода, но в этом суть. Пользователь хочет передать только определенную информацию для использования функцией. В этом случае единственная информация, которая нам нужна от проигрывателя, это «Какая нота была нажата?» и «Как сильно вы нажали на нее?». Мы можем передать эту информацию, используя «аргументы» в функции. Аргументы следуют за вызовом функции и обычно заключаются в круглые скобки и разделяются запятыми. В нашем классе фортепиано мы сначала определяем нашу функцию «press_key». Когда эта функция вызывается (когда эта клавиша нажата), она принимает информацию через свои аргументы. Последняя строка — это то, с чего начинается весь эффект домино, а все, что было до нее, только его настраивает. С помощью piano.press_key(1, 100) мы говорим пианино найти молоточек для ноты 1, что, в свою очередь, говорит молоточку ударить по струне со скоростью 100. Мы «абстрагируем» игрока, которому нужно знать о струне или молоточке. или любой из их функций. Им нужно только нажать клавишу, а об остальном позаботится код.

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

Рубин:

def my_function(argument)
  puts "Hello from a #{argument} function!"
end
my_function("Ruby")
=> "Hello from a Ruby function!"

Питон:

def my_function(argument):
  print(f'Hello from a {argument} function!')
my_function('Python')
=> "Hello from a Python function!"

JavaScript:

function myFunction(argument) {
  console.log(`Hello from a ${argument} function`);
}
myFunction("JavaScript")
=> "Hello from a Javascript function!"

6) Объекты и базы данных

Почти каждое приложение должно хранить данные, хотя разные языки и платформы имеют свой уникальный подход к выполнению этой задачи. Сегодня популярны два типа баз данных: SQL и не SQL. Понимание основ взаимодействия с базами данных необходимо любому разработчику.

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

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

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

ИСТОЧНИКИ:





Базы данных NoSQL и SQL
TLDR: базы данных NoSQL («не SQL
или не только SQL) были разработаны в конце 2000-х с акцентом на масштабируемость, быстроту…www.mongodb.com»