Skip to content

Про отладку и внимательность (новичкам)

Rakhim Davletkaliyev edited this page Sep 26, 2015 · 1 revision

jack [18:02] Что же не так, кто подскажет?

$myFactorial = function($acc, $num) use (&$myFactorial) {

   if ($num == 1 || $num == 0) {
       return $acc;
   };
   
   return $myFactorial($acc * $num, $num - 1);

};

$myFactorial(1, $num);

kirill.mokevnin [18:03] а ошибка в чем?

kirill.mokevnin [18:03] покажите вывод запуска

jack [18:06] Ого, как оперативно)

jack [18:06] PHPUnit 4.7.7 by Sebastian Bergmann and contributors.

FFFFFFF

Time: 204 ms, Memory: 4.75Mb

There were 7 failures:

  1. App\Test::testFactorial with data set #0 (1, 0) Failed asserting that null matches expected 1.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #1 (1, 1) Failed asserting that null matches expected 1.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #2 (2, 2) Failed asserting that null matches expected 2.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #3 (6, 3) Failed asserting that null matches expected 6.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #4 (24, 4) Failed asserting that null matches expected 24.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #5 (120, 5) Failed asserting that null matches expected 120.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #6 (3628800, 10) Failed asserting that null matches expected 3628800.

/usr/src/app/test.php:14

FAILURES! Tests: 7, Assertions: 7, Failures: 7. make: *** [test] Error 1 Run failed! Check and fix errors above!

jack [18:06] а в чате нет что-то типо спойлера?

kirill.mokevnin [18:08] нет

kirill.mokevnin [18:08] теперь будем учиться читать тесты), откройте файл который тут указан в выводе

kirill.mokevnin [18:09] и посмотрите как там запускается та функция которую вы должны определить

jack [18:31] по тесту два значения возвращается? или я вообще ничего не понимаю? (edited)

jack [18:41] а нет, дело в 14 строчке. сейчас разберусь!

kirill.mokevnin [18:49] 7) App\Test::testFactorial with data set #6 (3628800, 10) Failed asserting that null matches expected 3628800.

/usr/src/app/test.php:14

kirill.mokevnin [18:49] в тестах важно учиться читать вывод

kirill.mokevnin [18:50] как вы думаете, что означает этот текст?

kirill.mokevnin [18:50] failed asserting ...

jack [19:15] failed asserting? что-то сродни неверному утверждению, когда нечто ожидается. или как?

kirill.mokevnin [19:16] так и что конкретно тут нам говорит тест?

kirill.mokevnin [19:16] что ожидал что получил

jack [19:16] вообще я вижу, что явное несовпадение на линии 14 а файле тест.

jack [19:17] ну да, неравенство в том что должно было выйти и то что вышло.

jack [19:17] но это как-то слишком абстрактно для меня.

kirill.mokevnin [19:17] почему?

kirill.mokevnin [19:17] тест ожидал что ваша функция вернет 3628800

kirill.mokevnin [19:17] но в итоге получил null

jack [19:18] $this->assertEquals($expected, factorial($number));

что-то не следует из индекса этой строке в тесте.

kirill.mokevnin [19:18] куда уж конкретнее

kirill.mokevnin [19:18] exptected это то что ожидал

kirill.mokevnin [19:18] actual это то что получил

jack [19:18] а число в десятичном?

kirill.mokevnin [19:18] конкретнее некуда я бы сказал

kirill.mokevnin [19:18] ну да

kirill.mokevnin [19:18] а какая разница какое число?)

kirill.mokevnin [19:18] для вас главное что в том вызове где ваша функция

kirill.mokevnin [19:18] получился тull

kirill.mokevnin [19:18] null

jack [19:18] я думал это что-то..ээм.. шифр или что

kirill.mokevnin [19:18] вот что для вас главное в этом сообщение

jack [19:19] хм.

jack [19:19] да, логично

kirill.mokevnin [19:19] вы смотрели наш вебинар про тесты/

kirill.mokevnin [19:19] ?

kirill.mokevnin [19:19] тесты это ваш лучший и главный друг

jack [19:19] нет, не смотрел. не знал даже о них :с

kirill.mokevnin [19:19] о, вы много пропустили)

kirill.mokevnin [19:19] сверху ссылка есть

kirill.mokevnin [19:19] на сайте

kirill.mokevnin [19:19] https://github.com/Hexlet/webinars/wiki

GitHub Hexlet/webinars Hexlet webinars

kirill.mokevnin [19:19] посмотрите обязательно

jack [19:20] спасибо большое)

kirill.mokevnin [19:20] так вот теперь вам надо выяснить почему null

kirill.mokevnin [19:20] кстати, а вы поняли с каким аргументом была вызвана функция?

kirill.mokevnin [19:20] 7) App\Test::testFactorial with data set #6 (3628800, 10) Failed asserting that null matches expected 3628800.

/usr/src/app/test.php:14

kirill.mokevnin [19:20] еще раз смотрим сюда внимательно)

kirill.mokevnin [19:21] тут всего три числа 😄

kirill.mokevnin [19:21] одно из них мы знаем что означает (3628800 это exptected)

jack [19:21] там функция идет аргументом

kirill.mokevnin [19:21] data set #6 здесь видно что 6 это порядковый номер датасета

kirill.mokevnin [19:21] не функция а переменная

kirill.mokevnin [19:22] вы читали задание для задачи которую делаете?

kirill.mokevnin [19:22] там сказано что факториал принимает на вход

kirill.mokevnin [19:22] но даже без чтения задания довольно очевидно что функция факториала принимает на вход число

jack [19:22] Реализуйте рекурсивную функцию factorial используя линейно-итеративный процесс. и все(

kirill.mokevnin [19:22] таково ее математическое определение

jack [19:22] ну и на выход должно выдавать одно число

kirill.mokevnin [19:23] а да, я это не указал потому что в предыдущем упражнении где был рекурсивный процесс

kirill.mokevnin [19:23] та же функция

kirill.mokevnin [19:23] снаружи

kirill.mokevnin [19:23] тот же интерфейс

kirill.mokevnin [19:23] давайте еще раз вернемся к моему вопросу

kirill.mokevnin [19:23] так вот теперь вам надо выяснить почему null

kirill.mokevnin [12:20 PM] кстати, а вы поняли с каким аргументом была вызвана функция?

kirill.mokevnin [12:20 PM] 7) App\Test::testFactorial with data set #6 (3628800, 10) Failed asserting that null matches expected 3628800.

/usr/src/app/test.php:14

kirill.mokevnin [12:20 PM] еще раз смотрим сюда внимательно)

kirill.mokevnin [12:21 PM] тут всего три числа 😄

kirill.mokevnin [12:21 PM] одно из них мы знаем что означает (3628800 это exptected)

kirill.mokevnin [19:23] так какое же число было передано на вход функции факториала так что оно вернула null?

kirill.mokevnin [19:24] мы сейчас пытаемся эвристически думать, без точного знания что там на самом деле и как работает

kirill.mokevnin [19:24] мы знаем что был вызван факториал с каким то числом, получился null, ожидался 3628800

jack [19:24] ноль же и вернуло ноль

kirill.mokevnin [19:24] еще раз копирую

kirill.mokevnin [19:24] 7) App\Test::testFactorial with data set #6 (3628800, 10) Failed asserting that null matches expected 3628800.

/usr/src/app/test.php:14

kirill.mokevnin [19:24] учитесь читать вывод тестов

jack [19:24] 10!

kirill.mokevnin [19:25] наконец-то

jack [19:25] хахаха

jack [19:25] простите)

kirill.mokevnin [19:25] вы понимаете что сами себе сложности создаете тем что игнорируете вывод тестов?)

kirill.mokevnin [19:25] теперь давайте опять же эвристически попробуем понять что внутри файла тестов

jack [19:25] я не игнорирую, просто смотрю на нее и понимаю только полностью про файл и линию

kirill.mokevnin [19:26] на самом деле непонимание приводит к игнорированию, в смысле мозг не пытается даже зацепиться

jack [19:26] это да, согласен

kirill.mokevnin [19:26] называется “смотрю в книгу вижу фигу"

kirill.mokevnin [19:26] вот это важный навык, учиться понимать когда мозг так делает

jack [19:26] в самом файле, как я понимаю, каька

jack [19:26] калька

kirill.mokevnin [19:27] понятно теперь внутри самого файла что означают наборы чисел?

jack [19:27] которой должны соответствовать результаты работы основного файла?

kirill.mokevnin [19:27] одно из них ожидаемый ввывод

kirill.mokevnin [19:27] второе это то что идет на вход функции

kirill.mokevnin [19:27] теперь еще раз внимательно смотрим вывод тестов

kirill.mokevnin [19:27] весь

kirill.mokevnin [19:27] PHPUnit 4.7.7 by Sebastian Bergmann and contributors.

FFFFFFF

Time: 204 ms, Memory: 4.75Mb

There were 7 failures:

  1. App\Test::testFactorial with data set #0 (1, 0) Failed asserting that null matches expected 1.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #1 (1, 1) Failed asserting that null matches expected 1.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #2 (2, 2) Failed asserting that null matches expected 2.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #3 (6, 3) Failed asserting that null matches expected 6.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #4 (24, 4) Failed asserting that null matches expected 24.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #5 (120, 5) Failed asserting that null matches expected 120.

/usr/src/app/test.php:14

  1. App\Test::testFactorial with data set #6 (3628800, 10) Failed asserting that null matches expected 3628800.

/usr/src/app/test.php:14

kirill.mokevnin [19:28] теперь еще раз внимательно смотрим вывод тестов

kirill.mokevnin [19:28] и уже начинаем понимать, что тест запускается для каждого набора индивидуально

jack [19:28] ага, все 7 значений вывели неверный ответ!

kirill.mokevnin [19:28] более того, вход функции не важен (судя по результатам тестов)

kirill.mokevnin [19:28] ваша функция всегда возвращает null!

jack [19:28] и все они упираются в 14 линию

kirill.mokevnin [19:28] ну так очевидно там и происходит проерка

kirill.mokevnin [19:28] это не важно что она 14

kirill.mokevnin [19:29] там вызов вашей функции

kirill.mokevnin [19:29] она возвращает null

kirill.mokevnin [19:29] теперь тест на внимательность

kirill.mokevnin [19:29] как называется функция которую вы определили?

jack [19:30] testFactorial?

kirill.mokevnin [19:30] функция которую вы опредлели

kirill.mokevnin [19:30] это ваш факториал

kirill.mokevnin [19:30] вы не определяли других функций

kirill.mokevnin [19:31] ок, давайте тогда другой важный навык прокачаем

kirill.mokevnin [19:31] я о нем говорил в самом первом уроке

kirill.mokevnin [19:31] вот у вас есть функция

kirill.mokevnin [19:31] и работает она не правильно

kirill.mokevnin [19:31] как по быстрому ее повызывать с разными аргументами посмотреть что она возвращает?

kirill.mokevnin [19:31] этакое ручное тестирование

jack [19:31] в шеле

jack [19:31] идле или как еще

kirill.mokevnin [19:31] давайте этосделаем

kirill.mokevnin [19:31] в иде внизу терминал

kirill.mokevnin [19:31] наберите там php -a

kirill.mokevnin [19:32] и дальше require ‘имя файла где определан функция факториал’;

kirill.mokevnin [19:32] после этого вызывайте echo factorial(10);

jack [19:32] ага. а то я никак не знал как терминалом вызывать

kirill.mokevnin [19:33] как набирать php -a ?

kirill.mokevnin [19:33] или require ?

jack [19:33] вызов

kirill.mokevnin [19:33] так же как и в файлах вы пишите

kirill.mokevnin [19:34] function(args);

kirill.mokevnin [19:34] echo нужен для того чтобы вывод на экран напечатать

kirill.mokevnin [19:34] это не вызов вашей функции (edited)

kirill.mokevnin [19:34] внутри шела вы как будто построчно пишите файл

jack [19:35] но ничего не происходит

kirill.mokevnin [19:35] происходит

kirill.mokevnin [19:35] вам возвращается null

jack [19:35] root@be01d31d368b:/usr/src/app# php -a
Interactive mode enabled

require 'index.php';
echo factorial(10);
echo factorial(10);

kirill.mokevnin [19:36] наберите echo null;

kirill.mokevnin [19:36] что вам на экран будет напечатано?

kirill.mokevnin [19:36] вы не думайте что есть какая то магия

kirill.mokevnin [19:36] вы вызваете функцию (edited)

kirill.mokevnin [19:36] она вызывается (вы же не видите ошибок)

kirill.mokevnin [19:37] нет такого “ничего не происходит"

kirill.mokevnin [19:37] вопрос в том что вернула функция

kirill.mokevnin [19:37] раз ничего не печатается на экран

jack [19:37] ну я понимаю, что магии никакой нет, что все происходит "под ковром"

kirill.mokevnin [19:37] давайте еще один маленький эксперимент после которого я думаю вы многое поймете

jack [19:37] я-то не вижу отдачи

kirill.mokevnin [19:37] напишите внутри вашей функции первой строчкой вот такое

kirill.mokevnin [19:38] return “hello world”;

kirill.mokevnin [19:38] потом перезайдите в шел

kirill.mokevnin [19:38] и заново проделайте то что делали

kirill.mokevnin [19:41] что теперь показывает echo factorial(<тут любое число>); ?

jack [19:42] function factorial($num) { return “hello world”; ....

Interactive mode enabled

require 'index.php';
echo factorial(10);
^C

jack [19:42] ничего и я вышел

kirill.mokevnin [19:43] вам сначала надо было выйти

jack [19:43] да, это не пайтоновские исключения

jack [19:43] я перезагружал

kirill.mokevnin [19:44] сделайте cat index.php

kirill.mokevnin [19:44] в терминале

kirill.mokevnin [19:44] что там внутри?

kirill.mokevnin [19:44] то вы сейчас описали выше это невозможно, значит где то ошибка

kirill.mokevnin [19:44] либо файл не сохранился

kirill.mokevnin [19:44] либо не загрузилось оно в терминал

kirill.mokevnin [19:45] cat - это команда баша а не php

jack [19:46] cat отображает файл как есть в терминале

kirill.mokevnin [19:47] да

kirill.mokevnin [19:47] там есть строка ‘return ‘hello world’' ?

jack [19:47] };

$testFactorial(1, $num);

};

?>root@be01d31d368b:/usr/src/app# php -a
Interactive mode enabled

require 'index.php';
echo factorial(10);

jack [19:48] да, там порядок

jack [19:48] все как есть

kirill.mokevnin [19:48] можете скрин показать?

kirill.mokevnin [19:53] так да, у вас же там неймспейс app

kirill.mokevnin [19:54] вызывать функцию надо echo \App\factorial(10);

jack [19:54] а что это и зачем оно нужно?

kirill.mokevnin [19:54] пространства имен, чтобы не было конфликтов

kirill.mokevnin [19:54] каждый может определить свой факториал

jack [19:54] с кем?

kirill.mokevnin [19:54] они будут проходиться в более поздних уроках

jack [19:54] ааа

kirill.mokevnin [19:54] ну вдруг вы используете в программе два разных пакета и там одинаковые функции?

kirill.mokevnin [19:54] атата будет

jack [19:54] понял понял

kirill.mokevnin [19:55] папка это пространство имен

jack [19:56] require 'index.php';
echo \App\factorial(10);

jack [19:56] вот так нужно?

kirill.mokevnin [19:56] https://www.dropbox.com/s/1lpojpkwqyxkdtm/Screenshot%202015-09-26%2012.55.55.png?dl=0

kirill.mokevnin [20:01] да беда, на самом деле почему то шел не работает

kirill.mokevnin [20:01] видите на моем скрине как он должен выглядеть?

jack [20:01] вижу конечно, но что это мне дает

jack [20:01] если он не работает)

kirill.mokevnin [20:01] это дает вам понимание

kirill.mokevnin [20:02] что вывод на самом деле есть просто проблема с отображением

jack [20:02] ну проблемы и нет, буду оффлайн средствами работать

jack [20:03] но что же не так было в функции? или лучше я посмотрю вебинар и сам разберу?

kirill.mokevnin [20:03] а не то что “в языке какая то магия"

kirill.mokevnin [20:04] блин, у меня проблемы с интернетом

jack [20:04] да я понимаю, что нет никакой магии)

kirill.mokevnin [20:04] в общем я вас подводил к очень простой вещи

kirill.mokevnin [20:04] вам просто надо построить логическую цепочку

kirill.mokevnin [20:04] ваша фукнция при любом входе возвращает null (edited)

kirill.mokevnin [20:05] такое может происходит в двух случаях

kirill.mokevnin [20:05] либо вы реально возвращаете null (и значит у вас ошибка в логике программы)

jack [20:05] неправильное тело или аргументы

kirill.mokevnin [20:05] либо вы забыли написать return

kirill.mokevnin [20:05] есть такая штука, называется “отладка"

jack [20:05] работал с ней на js

jack [20:06] php тоже имеет нечто подобное?

kirill.mokevnin [20:06] когда вы отлаживаете вашу функцию и постепенно убеждаетесь в работоспособности ее частей и в конце концов находите где ошибка

kirill.mokevnin [20:06] )

kirill.mokevnin [20:06] вы под отладкой понимаете какой то инструмент

kirill.mokevnin [20:06] а я говорю про процесс нахождения ошибок в программах

jack [20:07] ну, на пайтоне я отлаживал просто вставляя print в интересующие меня куски кода

kirill.mokevnin [20:07] это то чем занимаются программисты 90 процентов времени

kirill.mokevnin [20:07] ну так вот жеж !

kirill.mokevnin [20:07] делайте это и смотрите вывод

kirill.mokevnin [20:07] но я же вам все написал

kirill.mokevnin [20:07] либо вы реально возвращаете null (и значит у вас ошибка в логике программы)

jack [1:05 PM] неправильное тело или аргументы

kirill.mokevnin [1:05 PM] либо вы забыли написать return

kirill.mokevnin [20:07] у вас там тривиальная ошибка по невнимательности

kirill.mokevnin [20:07] первое что надо проверять когда null это “не забыл ли я сделать return"

kirill.mokevnin [20:07] посмотрите на последнюю строчку в вашей фукнции

kirill.mokevnin [20:08] и в js и в python тоже самое

kirill.mokevnin [20:08] по дефолту функция возвращает null

kirill.mokevnin [20:08] если забыть return

jack [20:08] забыл return -_\

kirill.mokevnin [20:08] в ruby не так, оно возвращает последнее вычисленное выражение

jack [20:09] с ruby не сталкивался(

kirill.mokevnin [20:09] уровень программиста определяется тем наколько быстро и качественно он отлаживает

kirill.mokevnin [20:09] по этому сразу видно

kirill.mokevnin [20:09] как он приступает к задаче

kirill.mokevnin [20:09] вот сейчас можно сказать было собеседование (оно у нас так же проходит примерно)

kirill.mokevnin [20:09] но пока вы сами даже не пытаетесь двигаться и рассуждать о коде

kirill.mokevnin [20:10] этого недостаточно даже для junior позиции

kirill.mokevnin [20:10] но зато вы увидели как это можно делать

kirill.mokevnin [20:10] надеюсь поможет

jack [20:11] спасибо большое, буду разбираться.

kirill.mokevnin [20:11] а вебинары обязательно посмотрите)

kirill.mokevnin [20:11] ну и еще, вы слышали про TDD?

jack [20:11] неа

kirill.mokevnin [20:11] вот по сути вы по нему и работаете сейчас

kirill.mokevnin [20:11] разработка через тестирование

kirill.mokevnin [20:11] сначала написаны тесты, потом пишется код который их удовлетворяет

kirill.mokevnin [20:12] многие (в том числе мы) так разрабатывают софт

kirill.mokevnin [20:12] что дает огромные возможности по быстрому и безболезненному рефакторингу

jack [20:12] а, сталкивался с chai mocha

jack [20:12] на js опять же

kirill.mokevnin [20:13] вы сейчас о другом

kirill.mokevnin [20:13] инструмент для тестирования и процесс разработки это вещи из разных категорий

kirill.mokevnin [20:13] вы можете писать тесты и не используя TDD

kirill.mokevnin [20:14] а TDD это именно разработка управляемая тестами

kirill.mokevnin [20:14] то есть вы сначала пишете тесты

kirill.mokevnin [20:14] а потом код

jack [20:14] нужно почитать про тдд

kirill.mokevnin [20:14] и не важно какой тестовый фреймворк используется и используется ли вообще

kirill.mokevnin [20:14] и заодно про экстремальное программирование

kirill.mokevnin [20:14] кстати следующий вебинар будет о нем

jack [20:14] это два вебинара?

jack [20:15] отлично

kirill.mokevnin [20:15] но там уже разговор будет идти с учетом что все смотрели вебинар про tdd

jack [20:15] https://github.com/Hexlet/webinars/wiki/5-%E2%80%94-%D0%A2%D0%B5%D1%81%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B8-TDD

GitHub Hexlet/webinars Hexlet webinars

jack [20:16] он?

kirill.mokevnin [20:16] ага

jack [20:17] спасибо большое!) буду разбирать

kirill.mokevnin [20:17] на здоровье)

Clone this wiki locally