Нужен совет.

Есть примерный план интерактивного учебника по программированию. Учебник собирается выпускаться бесплатно (если на Бумстартере средства соберу, то еще и быстро).


Накидал сейчас план, нужны комментарии - какие темы стоит рассматривать, какой порядок тем лучше и какие темы включать в п. 7.1, 8.1, 9.1, 10.1, 11.1.


Примерный план учебника:


1 Введение в информатику

1.1 Системы счисления

1.2 Логические операции

1.3 Графические представления

1.4 Алгоритмы

1.5 Аппаратное обеспечение ЭВМ

1.6 Типы данных

2 Подготовка к началу работы

2.1 Системы контроля версий

2.2 Требования к рабочему месту

2.3 Выбор программного обеспечения

3 Введение в программирование

3.1 Графические схемы при проектировании приложения

3.2 Алгоритмизация

3.2.1 Построения алгоритма решения задачи

3.2.2 Принцип дробления алгоритма

3.2.3 Принцип атомарной операции

3.2.4 Повторное использование кода

3.3 Оформление кода

3.4 Безопасность приложения

3.5 Определение целей и задач

3.6 Структура программы

3.6.1 Библиотеки

3.6.2 Функции

3.6.3 Строки

3.6.4 API

3.7 Программный интерфейс

3.7.1 Нативные приложения

3.7.2 Веб-приложения

3.7.3 Консольные приложения

3.7.4 Универсальные (полиинтерфейсные) приложения

3.8 Парадигмы программирования

3.9 Объекты и их применимость

4 Базы данных

4.1 SQL и реляционная модель данных

4.2 SQLite3

4.3 MySQL

4.4 PostgreSQL

4.5. NoSQL базы данных

5 Язык программирования Python

5.1 Типы данных

5.1.1 Числа

5.1.2 Строки

5.1.3 Списки

5.1.4 Словари

5.1.5 Кортежи

5.2 Условный оператор

5.3 Циклы

5.3.1 Счетный цикл for

5.3.2 Условный цикл while. Бесконечный цикл.

5.4 Функции.

5.4.1 Функции

5.4.2 Параметры функции и значения по умолчанию

5.4.3 Лямбда функции

5.4.4 Модификаторы функций

5.5 Классы и объекты

5.5.1 Классы

5.5.2 Наследование классов

5.5.3 Объекты

5.6 Графический интерфейс. Библиотека PySide

5.7 Работа с веб-интерфейсом

5.8 Работа с базами данных

5.9 Исключения

5.10 Многопоточность

6 Язык программирования С

6.1 Типизация. Типы данных

6.2 Условный оператор

6.3 Циклы

6.4 Функции.

6.5 Графический интерфейс. Библиотека GTK

6.6 Работа с базами данных

7 Язык программирования С++

7.1 Предлагайте

8 Язык программирования JavaScript

8.1 Предлагайте

9 Язык программирования PHP

9.1 Предлагайте

10 Язык программирования PERL

10.1 Предлагайте

11 Язык программирования Prolog

11.1 Предлагайте

Вы смотрите срез комментариев. Показать все
1
Автор поста оценил этот комментарий

Тесты. Если этого до сих пор нет в содержании, лучше ничему не учить других.

раскрыть ветку (16)
3
Автор поста оценил этот комментарий

Тесты являются распиаренной, но не нужной (а иногда и опасной) системой. Наглядно:

1. Пишем код

2. Пишем тесты кода

3. Натравливаем 2 на 1

4. Смотрим результат.

Если все хорошо, то в релиз. Круто? Да... Но только выглядит. Потому что если тест написан с косяком или баг трудно воспроизвести, то в релиз уходит уязвимость.


Теперь смотрим на такую схему:

1. Прописываем архитектуру вызовов

2. При написании кода определяем граничные значения переменных

3. При передачи параметров функциям проверяем переменные на граничные условия

4. Проверяем функцию на набор условий.


То есть во-первых тестирование не является отдельным пунктом разработки (включено в Безопасность), во-вторых проводится непосредственно при разработке. Шанс ошибиться гораздо ниже (правда и скорость разработки несколько падает).

раскрыть ветку (15)
2
Автор поста оценил этот комментарий

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

раскрыть ветку (1)
1
Автор поста оценил этот комментарий
Спасибо за комментарий
Автор поста оценил этот комментарий

Я не совсем понял описываемую схему. Т.е. есть предложение написать кусок документации  и каждый раз вручную все проверять, чтобы не накосячить в тестах?

раскрыть ветку (6)
1
Автор поста оценил этот комментарий

Нет. Допустим мы пишем программу которая содержит функцию возведения в степень. Она принимает 2 числовых значения и возвращает результат. В блокноте (или по вкусу) пишем:


pow(число дробное 1 (0-1000), число дробное 2 (0-100)) - число (возвращаемое значение)


вообще там сложнее, но для примера сгодиться. Далее в самом начале функции прописываем:

если (число аргументов != 2 или аргумент 1 > 1000 или аргумент 1 < 0 или аргумент 2 > 100 или аргумент 2 < 0) {запрос повторного ввода или исключение } иначе {тело функции}.


Вызываем функцию и видим, чего она ждет и чего возвращает.


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


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


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

раскрыть ветку (5)
Автор поста оценил этот комментарий

А если в код пишут 2 программиста. И функция возведения в степень использует функцию, вывода, обработчик ошибок, и функцию умножения. А функцию pow использует функция факториала.

То как одному программисту гарантировать, что изменения в одном участке кода не приведут к появлению ошибок в другом участке кода?

раскрыть ветку (4)
1
Автор поста оценил этот комментарий
А для этого и существует контроль версий и документация.


Когда я участвовал в коллективной разработке у нас было "правило кодов" (обратили внимание на QT, который все "свои" данные метит Q). Для того, чтобы случайно не переназначить системные переменные или не создать случайно две переменные/функции с одним именем использовались коды:

[буква проекта][1-2 буквы из ФИО сотрудника]. То есть если код проекта Z, а сотрудник получил код II то его функции и переменные начинаются с ZII. При выполнение работы сперва ставилась задача (если проблему видел сотрудник, то он выставлял задачу себе), шла итерация (добавление/изменение функций и переменных), проверялось исполнение, затем следующая итерация.


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

раскрыть ветку (3)
Автор поста оценил этот комментарий

Проверка функции pow с любыми значениями на входе и выходе. Никак не покажет ошибку в функции факториала.

Ну и это по сути и есть ручное тестирование?

Ну и зачем мы тогда программируем, чтобы все делать вручную?

Что такое эмуляция? Интеграционное тестирование?

раскрыть ветку (2)
1
Автор поста оценил этот комментарий
Про проверку "на выходе" не прочитал?


Эмуляция - когда архитектура программы имеет выделенную функцию приема данных от пользователя (вызываемую обычно в main/основном коде в зависимости от ЯП) и функцию вывода данных. В dev-версии вызов функции приема заменяется другой, которая содержит подобранный и "решенный" массив данных. Данная функция подает "на вход" программы значения, а функция-вывод заменяется анализатором, который сравнивает полученные в итоге значения с контрольными.


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


Отличие от тестов - проверяется работа программы. Не код. Код может меняться сотни раз, но программа при этом должна работать, причем правильно работать.

раскрыть ветку (1)
Автор поста оценил этот комментарий
И как только в коде оказывается пара конечных автоматов вся эта методика летит к чертям.
Уж если не писать тесты так не писать, а не ограничиваться парой интеграционных и думать что все оттестировано. А как насчет проверки обработки ошибок?
Автор поста оценил этот комментарий

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


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

раскрыть ветку (3)
Автор поста оценил этот комментарий

С чего это "не получиться"? В чем принципиальная разница в получении данных из консоли или из веб-форм или из полей графического интерфейса? Граничные условия не пересчитываются, потому что закладываются в функцию "на входе". Что будет если в числовое поле кто-то умудриться забить текст? Знаю, что в теории невозможно... Но уязвимости присутствуют как объективная реальность. А когда функция проверяет то, что ей поступило "на входе" и либо выводит предупреждение, либо аварийно завершается при некорректном значении, то уязвимости появиться гораздо сложнее.


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

раскрыть ветку (2)
Автор поста оценил этот комментарий

"Для больших проектов есть другой способ - эмуляция" дык это же и есть то тестирование, о котором идёт речь =)

раскрыть ветку (1)
Автор поста оценил этот комментарий
Когда начинали пиарить тесты тоже путались, вроде одно и то же... Эмуляция и тестирование выполняют одну и ту же задачу одним и тем же способом, но строятся по совершенно разным принципам.


Тесты - служат для проверки поведения программы и покрывают весь код.


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


То есть отличие в объекте тестирования тесты проверяют код, эмуляция саму программу.

Автор поста оценил этот комментарий

Нет, сначала пишут тесты, а потом уже код, в этом суть TDD. Добавляют новые тесты только при исправлении багов, чтобы была уверенность в отсутствии регрессий и при расширении функционала, но тут опять сначала тест - потом код.

раскрыть ветку (1)
Автор поста оценил этот комментарий

Сам-то принцип от этого не меняется. И заодно то, что вызывает у меня приступ бешенства - многие, кто говорят о TDD заявляют, что "работа прекращается, когда код начинает проходить все тесты".

Вы смотрите срез комментариев. Чтобы написать комментарий, перейдите к общему списку