Вот я некоторое время назад подсел на Хаскель. Ключевое свойство - язык со строгой типизацией времени компиляции, но с выразительной системой типов. Вот там - вполне нормально. Почти все нетривиальные куски кода формулируются с помощью типов, и покрывать тестами остается пару-тройку мест, где реально посадить арифметическую ошибку или перепутать "меньше" с "больше".
У меня есть большой проект, где вообще нет ни одного теста. За три года успешно проскочили, не замеченные компилятором, одна арифметическая ошибка, одна логическая вышеупомянутого типа, и одна действительно нетривиальная, которую вообще непонятно, как тестировать. Была поймана логическим рассуждением - мне типа не нравилось то место, я на него посмотрел попристальнее, и ... Хрень работает, нареканий нет.
На C, разумеется, нереально. Разве что посредством компиляции хаскеля в C (ghc так умеет, но с библиотеками, вероятно, будет немалый геморрой). Или посредством написания на хаскеле DSL и кодогенератора в C к нему, но это тоже немалый геморрой, я полагаю. Я поэтому стараюсь не писать на C. Пока получается :)
Ну почему, они могут сказать, что вот уже собираются переписать на хаскеле...
Как бы уже почти реально.
Вот аргументировать агдой будет сложнее. Хотя если бы удалось, там тесты вообще были бы не нужны, пруфчекер в комплекте. Но увы, говорят, что для взаимодействия с RealWorld агде пока приходится говорить "мамой клянус!".
снобизм. да. именно снобизм. причем программиста из компании с немерянным бюджетом и неадекватным ЧСВ. и нет, я не про то, что тесты не нужны. но написание тестов -- тоже требует ресурсов. и если ты не гугл, то у тебя выбор -- или сделать новую фичу (даже, наеврное 3-4 новых фичи) или сделать тесты на старую фичу. в любом случае ты проиграл.
ну это не говоря уж о том, что тесты -- нихуя не серебрянная пуля и тестируют только то, о чём подумали что надо тестировать. а что не подумали -- и не тестируется. а в каком-нибудь TCP такой комбинаторный взрыв вариантов, требующих тестирования...
А вот их, кстати, часто ловят. Когда начинаешь строить систему типов для прочитанной задачи и видишь, что получается какая-то корявая фигня, идешь уточнять, и находишь ошибку. Были случаи.
Потому что некрасивый самолет не полетит, и если система типов получается корявой, то можно быть почти уверенным, что вычитанная задача не соответствует стоящей в реальности. А уж в прочтении ТЗ ошибка или в его написании - несущественно.
Не все знания о системе можно запихать в зависимые типы. Тем более знания о взаимодействии с внешним миром. Собственно, типы и прочий текст программмы следует рассматривать с точки зрения "что мы сделали", а тесты с точки зрения "что мы хотели". Ощибки могут быть и там и там, и хотеть мы можем странного и сделать по кривому. Но имея два взгляда на одну проблему легче поймать ошибки.
thesz зачем-то скрыл комментарий, отвечаю в пустоту. Возьмём, к примеру, Oracle, с которым общается наша программа. Посредством sql, который поверх net8, который поверх tcp, который поверх ip, далее ethernet, всякая физика и лирика в виде сетевых карточек. В каком состоянии должна находиться вся эта конструкция, чтобы мы могли сделать select? И что мы можем получить в ответ? Какие возможные состояния у этой конструкции? Должны ли мы предусмотреть просто реакцию на ORA-? Что происходит с коннектом после ошибки? А после таймаута? Не придётся ли нам воспроизвести в программе модель всей этой машинерии или мы будем упрощать? А как мы будем упрощать? Можно свести всё безумное состояние к паре Ok,Fail. Ну, или, к 3-4-10 более понятным состояниям. Насколько это упрощение верно отражает наш замысел? А верно ли мы поняли всю внешнюю модель? Всё это зависимыми типами не выразить, мы вынуждены сильно упрощать.А когда мы упрощаем, нам нужны тесты, чтобы убедиться, что упростили верно.
Скрытие комментариев - свойство сего блога. Видимо, комментарии не от друзей скрываются.
Ответ прост - нам не надо воспроизводить и/или перечислять все возможные состояния внешней системы. Достаточно отклассифицировать их настолько, чтобы было удобно.
Да, здесь нужны тесты. Но 1) мы и работаем с системой, что не имеет зависимых типов и 2) тесты будут высокоуровневыми, функциональными.
Юнит-тесты — ВООБЩЕ про другое. Это не фунциональное тестирование. Это — тестирование контрактов юнитов. Оно нужно ВООБЩЕ для другого: не для проверки, что наша система работает так, как мы задумали. А для проверки, что каждый мелкий ЮНИТ работает так, как ОН задуман. Потому что цель юнит-тестирования — другая: обеспечение ВОЗМОЖНОСТИ рефакторинга. В большой (БОЛЬШОЙ) системе без тестов просто страшно подойти к тому, чтобы переписать какой-нибудь кусочек: никогда не поймёшь, не изменил ли ты что-то, что потом при странных граничных условиях выстрелит. Наличие юнит-тестов позволяет (в идеале) делать это вообще недрогнувшей рукой: если юнит-тесты после рефакторинга прошли без ошибки, значит, ты ничего не сломал в переписанном юните.
1. Это важно при работе с юнитами с состоянием и (вот здесь очень важное) со слабой системой типов.
2. Рефакторинг не вносит нового функционала и не исправляет старые оошибки (он должен их сохранить - функционал не меняется). Это практически бесполезная деятельность.
3. Поскольку я имел счастье работать с системами без юнитов с состоянием и с хорошей системой типов, я уже не могу прорезонировать с вашим посылом.
no subject
Date: 2014-11-27 07:37 am (UTC)У меня есть большой проект, где вообще нет ни одного теста. За три года успешно проскочили, не замеченные компилятором, одна арифметическая ошибка, одна логическая вышеупомянутого типа, и одна действительно нетривиальная, которую вообще непонятно, как тестировать. Была поймана логическим рассуждением - мне типа не нравилось то место, я на него посмотрел попристальнее, и ... Хрень работает, нареканий нет.
no subject
Date: 2014-11-27 08:15 am (UTC)no subject
Date: 2014-11-27 08:44 am (UTC)no subject
Date: 2014-11-27 08:46 am (UTC)no subject
Date: 2014-11-27 10:05 am (UTC)Как бы уже почти реально.
Вот аргументировать агдой будет сложнее. Хотя если бы удалось, там тесты вообще были бы не нужны, пруфчекер в комплекте. Но увы, говорят, что для взаимодействия с RealWorld агде пока приходится говорить "мамой клянус!".
no subject
Date: 2014-11-27 10:08 am (UTC)no subject
Date: 2014-11-27 10:19 am (UTC)Это, конечно, не ядро ОС, но движение в нужном направлении.
no subject
Date: 2014-11-27 10:10 am (UTC)no subject
Date: 2014-11-27 10:13 am (UTC)no subject
Date: 2014-11-27 10:26 am (UTC)no subject
Date: 2014-11-27 10:29 am (UTC)no subject
Date: 2014-11-27 10:34 am (UTC)да. именно снобизм.
причем программиста из компании с немерянным бюджетом и неадекватным ЧСВ.
и нет, я не про то, что тесты не нужны.
но написание тестов -- тоже требует ресурсов.
и если ты не гугл, то у тебя выбор -- или сделать новую фичу (даже, наеврное 3-4 новых фичи) или сделать тесты на старую фичу. в любом случае ты проиграл.
ну это не говоря уж о том, что тесты -- нихуя не серебрянная пуля и тестируют только то, о чём подумали что надо тестировать. а что не подумали -- и не тестируется. а в каком-нибудь TCP такой комбинаторный взрыв вариантов, требующих тестирования...
no subject
Date: 2014-11-27 10:48 am (UTC)(no subject)
From:no subject
Date: 2014-11-27 10:39 am (UTC)no subject
Date: 2014-11-27 11:52 am (UTC)no subject
Date: 2014-11-27 03:00 pm (UTC)Потому что некрасивый самолет не полетит, и если система типов получается корявой, то можно быть почти уверенным, что вычитанная задача не соответствует стоящей в реальности. А уж в прочтении ТЗ ошибка или в его написании - несущественно.
no subject
Date: 2014-11-27 02:57 pm (UTC)Но так вот сходу не поручусь, я туда только издалека заглядывал.
no subject
Date: 2014-11-28 07:31 am (UTC)Тем более знания о взаимодействии с внешним миром.
Собственно, типы и прочий текст программмы следует рассматривать с точки зрения "что мы сделали", а тесты с точки зрения "что мы хотели".
Ощибки могут быть и там и там, и хотеть мы можем странного и сделать по кривому.
Но имея два взгляда на одну проблему легче поймать ошибки.
no subject
Date: 2014-11-29 07:28 pm (UTC)Вот какие?
no subject
Date: 2014-11-29 09:34 pm (UTC)Возьмём, к примеру, Oracle, с которым общается наша программа. Посредством sql, который поверх net8, который поверх tcp, который поверх ip, далее ethernet, всякая физика и лирика в виде сетевых карточек.
В каком состоянии должна находиться вся эта конструкция, чтобы мы могли сделать select? И что мы можем получить в ответ? Какие возможные состояния у этой конструкции?
Должны ли мы предусмотреть просто реакцию на ORA-? Что происходит с коннектом после ошибки? А после таймаута? Не придётся ли нам воспроизвести в программе модель всей этой машинерии или мы будем упрощать?
А как мы будем упрощать? Можно свести всё безумное состояние к паре Ok,Fail. Ну, или, к 3-4-10 более понятным состояниям.
Насколько это упрощение верно отражает наш замысел?
А верно ли мы поняли всю внешнюю модель?
Всё это зависимыми типами не выразить, мы вынуждены сильно упрощать.А когда мы упрощаем, нам нужны тесты, чтобы убедиться, что упростили верно.
no subject
Date: 2014-11-30 03:35 am (UTC)Ответ прост - нам не надо воспроизводить и/или перечислять все возможные состояния внешней системы. Достаточно отклассифицировать их настолько, чтобы было удобно.
Да, здесь нужны тесты. Но 1) мы и работаем с системой, что не имеет зависимых типов и 2) тесты будут высокоуровневыми, функциональными.
no subject
Date: 2014-11-30 08:51 am (UTC)no subject
Date: 2014-11-30 10:06 am (UTC)2. Рефакторинг не вносит нового функционала и не исправляет старые оошибки (он должен их сохранить - функционал не меняется). Это практически бесполезная деятельность.
3. Поскольку я имел счастье работать с системами без юнитов с состоянием и с хорошей системой типов, я уже не могу прорезонировать с вашим посылом.
no subject
Date: 2014-11-30 10:16 am (UTC)no subject
Date: 2014-12-01 11:56 am (UTC)Большое спасибо за вашу поддержку.
(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From:(no subject)
From: