1. Математика — гимнастика ума.
Как ни крути, но программирование — это математика. Не та математика, где диффуры и прочие пространства Минковского, а вполне себе простая описательная математика функций преобразования одного в другое. Умные люди придумали такое понятие, как "Дискретная математика", которая рассматривает графы и логические утверждения, которые обозваны в ней "Дискретными структурами". Графы — это всего лишь узлы и связи между ними. Они не так часто используются в "обычном" программировании, как логические утверждения, но тоже имеют место быть. Графы имеют несколько видов, для них существует целый класс алгоритмов, позволяющий найти какие-то оптимальные значения связей между узлами, упорядочить их и всякое такое прочее — о них мы тут говорить не будем. А вот о логических утверждениях стоит поговорить более развернуто.
1.1. Логика — раздел математики.
Про логику в научных журналах одним из первых начал писать еще Аристотель, а все программирование, по большому счету, — это присваивание и ветвление. Вот как раз логику программисту знать необходимо.
Итак, просто вспомнить заради приведу тут основные логические операторы и законы:
И — логическое умножение. Приоритет высокий.
ИЛИ — логическое сложение. Приоритет низкий.
НЕ — отрицание. Приоритет высочайший.
В выражении "А = Б И Ц ИЛИ Д И НЕ Ж" сначала будет вычислено "НЕ Ж", за ним все "И", и уже после, в самом конце, будет вычислено "ИЛИ".
Также существуют логические преобразования, которые помогут вам упрощать логические выражения. Они исходят из законов логики, сформулированных на заре цивилизации.
Законы логики.
1. Никакое высказывание не может быть истинным и ложным одновременно.
Тут все просто: выражение "Х = 1 И Х <> 1" всегда ложно.
2. Любое высказывание или истинно, или ложно — третьего не дано.
Ну с этим все должно быть ясно. При этом основные ошибки в программировании кроются как раз в сложных логических выражениях, которые или истины, или ложны но разработчик не знает, когда они истинны, а когда — ложны. Они просто сложны для него, )))
3. Утверждение истинно, а контрутверждение ложно.
Тут тоже все достаточно просто: "(А = Б) = НЕ (А <> Б)".
4. Силлогизм.
Классика: "Всякий человек смертен. Сократ — человек, следовательно он смертен". Примитивный пример может быть таким: "(А = Б И Б = Ц) = (А = Ц)".
Исходя из этих законов существуют преобразования логических выражений (не забываем про приоритеты):
НЕ (А ИЛИ Б) = НЕ А И НЕ Б
НЕ (А И Б) = НЕ А ИЛИ НЕ Б
А И (Б ИЛИ Ц) = А И Б ИЛИ А И Ц
А ИЛИ Б И Ц = (А ИЛИ Б) И (А ИЛИ Ц)
А ИЛИ А И Б = А
А И (А ИЛИ Б) = А
Интереса заради можно разобрать такое вот выражение, приведенное в этой вот публикации.
((ПН И ПНП) И (РН И РНП)) ИЛИ (( ПН = Ложь ) И (РН И РНП)) ИЛИ ((ПН И ПНП) И (РН = Ложь))
Преобразуем это выражение, убрав константы:
(А И Б) И (Ц И Д) ИЛИ НЕ Ц И (А И Б) ИЛИ НЕ А И (Ц И Д)
Тут условие будет истинным в следующих случаях: 1. А = Б = Ц = Д = ИСТИНА. 2. А или Ц = ЛОЖЬ, Б = Д = ИСТИНА. При том А может быть ЛОЖЬ только тогда, когда Ц = Д = ИСТИНА, а Ц может быть ЛОЖЬ только когда А = Б = ИСТИНА.
Отсюда можно сделать вывод, что если А И Б = ИСТИНА, то нас не интересует Ц И Д, и, соответственно, наоборот. Отсюда прямо следует, что данное условие эквивалентно следующему:
(А ИЛИ Ц) И (А И Б ИЛИ Ц И Д)
Какая логика преобразований тут использовалась? Из первоначального условия ясно, что (А И Б) И (Ц И Д) — это основное условие, при этом если А ИЛИ Ц неистинны, то для А становится бессмысленно Б, а для Ц — Д. В итоге у нас должно быть истинным одно из А или Ц. Так и запишем: А ИЛИ Ц. А дальше уже мы можем А И Б логически сложить с Ц И Д, т.к. у нас или А, или Ц истинно. При ложности А будет проверяться только истинность Ц и Д, а для ложности Ц — только А и Б. Если А и Ц ложны, то и само условие тоже будет ложно.
2. Принципы древних.
В комментариях к уже приведенной статье я отметил, что древние люди сформулировали достаточное число принципов, которые могут быть применены и к программированию тоже. Давайте пройдемся по ним.
2.1. Не стоит плодить сущности без необходимости
Данный принцип сформулировал Уильям Оккам, живший в XIII-XIV веках. Суть его в том, что если что-то можно объяснить без привлечения дополнительных сущностей, то привлекать эти сущности не нужно. Истоки же редуцирования (т.е. минимизации и упрощения) в логике сокрыты во глубине веков, а бритву и Оккама первым, если мне не изменяет память, скрестил Лейбниц (в действительности он не Оккама с ней скрестил, а номинализм, "протагонистом" которого был Оккам).
Давайте соотнесем это с программированием. В данном случае суть проста: не нужно делать лишнего. Т.е. лишних переменных, функций, процедур, действий. Лишнее обычно образуется не из задачи, как таковой, а из подзадачи, когда локальный творец не видит всего творения. Избежать лишних сущностей позволит хорошо проработанная архитектура решения. Исходя прямо из формулировки принципа, можно определить, что система, содержащая минимальное достаточное количество элементов будет лучше системы, в которой элементов будет больше.
При этом нужно понимать, что качели эффективности программного кода могут прямо зависеть от количества сущностей. И минимальное их количество может быть неэффективным, Например, если попытаться снизить количество потребляемой памяти, то время разработки и зачастую производительность такого экономного по памяти решения будут обычно хуже, чем у решения, не особо ограничивающего использование памяти, например, для кеширования часто используемых значений. Также запрос в цикле, обрабатывающий по одному элементу данных, будет обычно хуже, чем обработка массовой выборки (если, конечно, вы не обрабатываете только один элемент).
Но в большинстве других случаев стоит разобраться, нужны ли нам те или иные переменные, функции, процедуры, модули, документы, регистры, справочники, ПВХ или иные какие объекты. Следует стараться использовать уже имеющееся, и если этого действительно не хватает для реализации задачи, плодить новую сущность, предварительно посоветовавшись с архитектором (скрам с его покером планирования тут однозначно рулит).
2.2 Лучшее — враг хорошего.
Данный принцип любит употреблять некий В.В.Шахиджанян. И он тут вполне прав, т.к. нет пределу совершенству. Есть мнение, что люди, сидящие на сайтах знакомств так привыкают к тому, что найдется что-то лучше, что не особо хранят имеющиеся отношения, предполагая, что всегда найдется как минимум не хуже. И в этом что-то есть!
Если говорить о программировании, то этот принцип призывает к балансу сущностей без необходимости и работающего решения. Можно сколь угодно долго сокращать логическое выражение, но если оно работает, то не стоит грызть землю в поисках лучшего варианта — его может и не быть, кстати.
Отсюда как бы мораль: если есть работающий без ошибок механизм — не стоит перерабатывать его только исходя из понимания, что можно сделать лучше. Т.е. любя работающая программа лучше идеального ее проекта. Да, тезис спорный, но в ситуации быстрой разработки он оправдан.
2.3. Все гениальное — просто.
Так Йозеф Геббельс перефразировал слова Леонардо да Винчи. И если выкинуть из объяснения чего-либо все лишнее, то получится как раз простое и достаточное этого чего-либо объяснение. Другими словами, это предельный вариант принципа Оккама.
С точки зрения программирования, данный принцип должен сдерживать сложность, нарастающую в ходе проекта по созданию программного продукта. Если сложность получающейся системы высокая, то где-то у разработчиков проблемы. Сложность — это, фактически, совокупность возможных связей между компонентами системы. Понятно, что чем больше компонентов в системе, тем больше возможных связей между ними может быть образовано. Для достижения гениальности нужно и уменьшать количество компонетов, и пресекать лишние между ними связи.
2.4. Глаза боятся — руки делают.
В словаре народной фразеологии данное понятие отражено весьма полно:
Не надо слишком драматично воспринимать предстоящую работу, преувеличивать ее трудность: как бы тяжело ни казалось, если постоянно что-то делать — результат обязательно приходит. Выражение часто употребляется как самоутешение или при желании приободрить других.
Для разработчиков программного обеспечения данное выражение должно быть крайне полезно, т.к. сложность, с которой приходится работать, бывает весьма высока. Это как раз следствие того, что большинство программных продуктов (особенно на 1С) не представляют из себя образчиков гениальности — в них полно лишних сущностей, но это цена компромисса между работающим ПО и сферическим в вакууме ТЗ, которое никто и никогда не будет писать.
3. Мораль.
Исходя из вышесказанного могу подытожить следующим образом:
1. Разработчик должен знать о том, что логические выражения можно и нужно преобразовать так, чтобы в них не было ничего лишнего — ведь логические выражения — это и есть программирование. И если разработчик не может этого сделать, то пусть идет учиться не на очередной сертификат, а на курс логики.
2. Разработчик не должен придумывать кучу регистров, справочников, их реквизитов и прочего для решения своей задачи, если только задача не может быть решена без этого. И лучше подумать вместе с архитектором о том, как этого избежать. А если избежать не получается, то подумать и о том, как это можно будет использовать в будущих задачах.
3. Не стоит тратить множество времени на идеальное ТЗ — оно все равно скорее всего не будет идеальным, но полностью отказываться от раздумий на тему того, как это сделать, тоже не стоит.
4. Не стоит усложнять задачу. Иногда, если отвлечься, приходит неплохое и достаточно простое решение.
5. Не стоит уходить в шатдаун, испытывая сложность с пониманием задачи. Иногда просто начало работы над ней уже помогает включить мозг. И не стоит забывать о том, что сложные моменты в ходе отладки могут упрощаться.
(0) Всегда рекомендую читать классику — «Совершенный код» С. Макконнелл. Там написано все и подробно.
Не хочется обижать авторов статей, но они освещают только малый процент того, что есть в «совершенном коде».
(1) так я, например, постоянно предлагаю Макконнелла читать всем и каждому. Моя статья тут совершенно о другом — о том, что нужно знать программисту, чтобы вообще иметь возможность писать программы. Ну и о том, что совершенного кода написано не так много, что лучше написать не такой совершенный, но работающий код, чем не написать никакого кода )))
Отсюда прямо следует, что данное условие эквивалентно следующему:
(А ИЛИ Ц) И (А И Б ИЛИ Ц И Д)
ну неправильно же , исправьтесь
(А И Б) И (Ц И Д) ИЛИ НЕ Ц И (А И Б) ИЛИ НЕ А И (Ц И Д)
и
(А ИЛИ Ц) И (А И Б ИЛИ Ц И Д)
не эквивалентны
(3) не эквивалентны в двух случаях из 16-ти. Может Вы предложите, как сократить это выражение?
(4) ну например
Ц И Д И (НЕ А ИЛИ Б) ИЛИ НЕ Ц И А И Б
или
(НЕ Ц ИЛИ Д) И (НЕ А ИЛИ Б) И (Ц И Д ИЛИ А И Б)
наверняка есть и получше варианты
Просто оставлю здесь
Показать
(5) как вариант! Полезно иногда понимать, что где-то ошибаешься.
(7) может кто нибудь заморочится и напишет обработку на тему алгоритма Квайна-МакКлоски
(8) кстати, очень интереснаятема . Постараюсь нарисовать ее в ближайшее время.
2.4.1. Слона надо есть по кусочкам.
Если задача пугает громоздкостью и/или сложностью, разбейте ее на более простые подзадачи. И разбивайте до тех пор, пока они не станут простыми и легко реализуемыми.
Frustra fit per plura quod potest fieri per pauciora
Но почему почти никто не задумывается, что достаточное не всегда правильное? Привычка, так принято и иначе нельзя? Всего лишь вопрос, а почему нельзя? Потому что «Оккам так сказал»?
В терминах 1С еще Или НЕОПРЕДЕЛЕНо 🙂
(12) Только в случае если оно существует)))
(11) потому что правильное не всегда правильно
(12)
Результат логической операции не может быть неопределен. Или может? )))
(11) всегда есть смысл предметно поговорить об этом. Но для этого нужно какой-то пример разобрать. У Вас есть пример?
Хорошая статья. Порадовало упоминание создателя «Соло на клавиатуре» =)).
У некоторых программистов бывает еще так:
(15) В Булевой алгебре не может, т.к. эта алгебра определена на множестве {Истина, Ложь}
А в SQL может, т.к. там множество {Истина, Ложь, Null}
Спасибо автору за статью.
Процентов 80 работы программиста — это не написание кода, а его чтение (изучение чужого кода, отладка, изучение документации). У программистов 1С эта доля может доходить до 98 процентов.
Может кто-нибудь поделится, как читать код (опыт, методики, инструменты)?
Но, думаю, это тема для отдельной статьи.
Спасибо за внесенную лепту. А также, за своеобразный пинок меня, чтобы я продолжил публикации ))
Кайф. И сказать нечего.
(2) Кстати, по поводу Совершенного кода, в оригинале название книги «Code Complete», совсем другой нюанс смысла.
Про логику порадовало
С. Н. Виноградов, А. Ф. Кузьмин
Логика
УЧЕБНИК ДЛЯ СРЕДНЕЙ ШКОЛЫ СССР
*** 1954 ***
очень рекомендую….
Я правда читал для вузов, вышеприведенный попроще…
Можно ещё почитать занимательную логику или Рэймонд М. Смаллиан «Как же называется эта книга?».
(20)
Кстати, хорошая идея. Попробую изложить свое видение данной проблемы в эти выходные.
(26) Обязательно пишите, вроде неплохо получается 🙂
(24)
*** 1954 ***
Сорри, немного оффтопа. О вечном.
Недавно с удивлением узнал, что мой ребенок учит дифференциалы по Фихтенгольцу. По которому в свое время учился я и, секундочку, моя мама. ))
(28)
Тут оказалось, что учебники 40-50 гораздо более понятны и адекватнее современных. Энтузиасты взялись за переиздание. Кто использует говорят эффект потрясающий, школьники которые считались в школе безнадежно тупыми — выбиваются в уверенные хорошисты (но это по слухам — не проверял сам).
Хочу поблагодарить Сергея за поддержкустатьи про логику и математику
(18) про меня
не понял, это сарказм был в статье?
Процентов 80 работы программиста — это не написание кода, а его чтение (изучение чужого кода, отладка, изучение документации). У программистов 1С эта доля может доходить до 98 процентов.
Может кто-нибудь поделится, как читать код (опыт, методики, инструменты)?
Но, думаю, это тема для отдельной статьи. —Согласен
(23) не-а, как раз перевод «совершенный» тут самое то — «совершенный» оно от «свершился -> завершился»..
Завершенный, законченный, самодостаточный — как раз это значение у «complete».. а просто перевод «завершенный» — лишен смысла, который в самой книге.
«2. Любое высказывание или истинно, или ложно — третьего не дано.»
А как же Троичная логика?
ru.wikipedia.org/wiki/Троичная_логика
Перечень значений нечёткой трёхзначной логики с двумя чёткими и с одним нечётким значением помимо «истинно» и «ложно» включает также третье значение, которое нечётко и трактуется как «не определено» или «неизвестно», или, в простонародье, х.з.
Примерами значений нечёткой трёхзначной логики с одним чётким и с двумя нечёткими значениями являются: («меньше», «равно», «больше»), («уклон влево», «прямо», «уклон вправо») и другие.
Примерами значений нечёткой трёхзначной логики с тремя нечёткими значениями, к которым сводится очень большое количество практических народнохозяйственных задач, являются: («меньше», «равно, в допустимых пределах», «больше»), («уклон влево», «прямо, в допустимых пределах», «уклон вправо»), («холодно», «прохладно», «жарко») и другие.
Компьютер на троичной логикеhttps://ru.wikipedia.org/wiki/%D0%A1%D0%B5%D1%82%D1%83%D0%BD%D1%8C_(%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80)
(36) да, были люди в наше время… богатыри, не мы…
(34)
(34)
Тогда нужно акцентировать внимание на букве «Ё» в слове «совершённый». А вообще, я бы перевёл название во что-то вроде «Конечный код». В любом случае название «Совершенный код» несёт практически противоположный смысл, чем тот, который вкладывал Макконнелл.
(28)
Это не тот Фихтенгольц, который еще и по программированию учебники писал? Я, будучи школьником, изучал по нему Паскаль в 10-м классе, а в 11-й класс пошел в другую школу. Там препод посмотрел на книжку, по которой я учился, затем указал мне на лучший компьютер в классе и попросил, чтобы я не мешал ему на уроках.
А книжка, и в правду, давалась с кровью и седыми волосами. Только позже, когда мне попались в руки другие книги по программированию, я в сравнении осознал, насколько это было жестоко по отношению к моей невинной детской головушке…
(38)
«Конченный код» ))) Типа писал его совсем конченный программер )))
Ну уж кто чего видит…
для улучшения собственных навыков программирования идеально подходит парное программирование с более опытным наставником
понравилась мысль про «глаза боятся — руки делают». спасибо!
(42) этим мыслям тысячи лет)))