Уже дал: "Языки программирования и схемотехника СБИС". Уточняю: 7-й том 11-томника по микроэлектронике, К.Фути, Н.Судзуки, М. "Мир" 1988.
Цитатаrrrfer ()
Искал по части слова всел-енная - ничего нет.
А Вы, батенька, тормоз. О том, что все сущности, рассматривающиеся в задаче, программисты издавна называют "вселенной", Вы не в курсе? Или, все-таки, прикидываетесь? Страуструп: "Главное в хорошем проекте - прямо отразить какое-либо понятие "реальности", т.е. уловить понятие из области приложения классов, представить взаимосвязь между классами строго определенным способом, например, с помощью наследования, и повторить эти действия на разных уровнях абстракции. Но как мы можем уловить эти понятия? Как на практике решить, какие нам нужны классы? Лучше поискать ответ в самой области приложения, чем рыться в программистском хранилище абстракций и понятий". ***
Цитатаrrrfer ()
Процитируйте меня, где я "сначала заявляю", а "затем утверждаю".
Пожалуйста:
Цитатаrrrfer ()
Про части информационной модели вселенной впервые прочитал у тебя.
Цитатаrrrfer ()
Не видел ни одной программы, ну посмотри тут...
***
Цитатаrrrfer ()
если твое решение работает не достаточно эффективно (на это указывает приписка в скобках к первому пункту)
Не тормозите. Год написания видели? В те годы даже прямую линию чере if-ы рисовали, чтобы избежать деления. ***
Цитатаrrrfer ()
Структуры данных - это не таблицы
А таблицы - не структуры данных... Да перестаньте, наконец, рвать слова из контекста и прочтите, наконец, хоть что-то из того, на что я ссылался... Как ни назовите структуру данных, главное в ней, что беря из нее параметры и адреса процедур, я могу избежать "елочки" - проверки всех возможных условий при каждом событии в программе.
Скажу проще: если в вашей программе есть ф-ии (классы) не влезающие в один экран редактора, значит, вы не умеете писать ни на C, ни на C++. Если, в вашей программе есть строки, отличающиеся друг от друга в меньшем числе мест, чем их общее число - тоже. Быдлокодеры любят повторять: "логика, убивающая мозг",- когда их пытаются заставить программировать.
Скажу проще: если в вашей программе есть ф-ии (классы) не влезающие в один экран редактора, значит, вы не умеете писать ни на C, ни на C++.
В 80х годах были такие метрики кода, как экран редактора. Сейчас у всех широкие мониторы и строка не ограничивается 80 символами. Это с одной стороны. С другой стороны, причем тут структуры данных?
Цитата
А таблицы - не структуры данных... Да перестаньте, наконец, рвать слова из контекста и прочтите, наконец, хоть что-то из того, на что я ссылался...
Я писал выше, что про таблицы впервые прочитал у вас. По контексту я понял что имеется ввиду массив со табулированными значениями, но ко всему остальному бреду, который вы генерируете в этом случае это не имеет отношения.
Цитата
А Вы, батенька, тормоз. О том, что все сущности, рассматривающиеся в задаче, программисты издавна называют "вселенной", Вы не в курсе? Или, все-таки, прикидываетесь?
Аргументы кончились, вы перешли на оскорбления? И таки да, я впервые слышу чтобы программисты что-то там называли "вселенной", видимо не с теми общаюсь.
Цитата
Страуструп: "Главное в хорошем проекте - прямо отразить какое-либо понятие "реальности", т.е. уловить понятие из области приложения классов, представить взаимосвязь между классами строго определенным способом, например, с помощью наследования, и повторить эти действия на разных уровнях абстракции. Но как мы можем уловить эти понятия? Как на практике решить, какие нам нужны классы? Лучше поискать ответ в самой области приложения, чем рыться в программистском хранилище абстракций и понятий".
Тут страуструп (или не он, т.к. гугл нашел цитату во многих источниках, видимо копипастят) рассказывает как производить декомпозицию задачи на части. Имея ввиду ОО-декомпозицию. Как это связано с САБЖем?
Цитата
Цитата
Процитируйте меня, где я "сначала заявляю", а "затем утверждаю".
Цитата
Пожалуйста:
Цитата
Про части информационной модели вселенной впервые прочитал у тебя.
Цитата
Не видел ни одной программы, ну посмотри тут...
Да, и где тут противоречия? - ты используешь какую-то стремную терминологию, которую только ты сам и понимаешь. Но существуют нормальные ОО-программы, которые я лично видел и писал их на работе.
Цитата
Уже дал: "Языки программирования и схемотехника СБИС". Уточняю: 7-й том 11-томника по микроэлектронике, К.Фути, Н.Судзуки, М. "Мир" 1988.
Номер страницы давай, я не буду весь седьмой том перечитывать. Ты уже был пойман на недобросовестных пруфах.
Сообщение отредактировал rrrfer - Воскресенье, 26 Июля 2015, 20:22
Например это могли бы быть таблицы Брадиса или типа того.
Уже близко. Вам осталось принять, что управляющую ф-ию тоже можно вычислить заранее.
Цитатаrrrfer ()
Сейчас у всех широкие мониторы и строка не ограничивается 80 символами.
Однако, встретить ф-ию, которая не влезает в "современный экран", достаточно просто. Например, в приведенном выше Python-примере были ф-ии длиннее 100 строк. Очевидно, что в то, что ф-ия такой длины работает правильно можно только верить.
Цитатаrrrfer ()
По контексту я понял что имеется ввиду массив со табулированными значениями, но ко всему остальному бреду, который вы генерируете в этом случае это не имеет отношения.
Зачем строить предположения? У Броуди все очевидно.
Цитатаrrrfer ()
Тут страуструп (или не он, т.к. гугл нашел цитату во многих источниках, видимо копипастят) рассказывает как производить декомпозицию задачи на части.
Речь не декомпозиции, а о вселенной используемых сущностей.
Цитатаrrrfer ()
Но существуют нормальные ОО-программы, которые я лично видел и писал их на работе.
Возможно, но я таких не видел. Только обычные плохие C -программы с использованием C++-парадигм исключительно для обфускации.
Цитатаrrrfer ()
Номер страницы давай, я не буду весь седьмой том перечитывать.
Ну, как бы, весь этот том посвящен исключительно ООП. Быдлокодеры любят повторять: "логика, убивающая мозг",- когда их пытаются заставить программировать.
Сообщение отредактировал Gudleifr - Воскресенье, 26 Июля 2015, 20:52
rrrfer, не берите себе в голову. Просто C++-программ не существует в природе, а почему, C++-кодеру не понять. Иначе, С++-программы существовали бы. Быдлокодеры любят повторять: "логика, убивающая мозг",- когда их пытаются заставить программировать.
Страуструп: " Чем лучше программист знает С, тем труднее будет для него при программировании на С++ отойти от стиля программирования на С".
ЦитатаGudleifr ()
Я тоже. В xxx-надцатый раз повторяю: не видел ни одной серьезной программы, написанной в ОО-стиле. Только "процедурные". (Если уж на то пошло, видел единственную действительно структурную серьезную программу: TeX Кнута).
Как человек, начинавший писать на Си в 1994 году, и столкнувшийся с С++ только в 1998 могу подтвердить по крайней мере три вещи: - очень трудно перейти от процедурного стиля программирования к ООП в его изначальном (академическом) понимании. Лично у меня это получилось только после работы с коммерческими проектами на Smalltalk и и попробовав другие подходы на Modula/Lisp (крайне косвенно) - Говнокодинг на С++ распространён так сильно, что обогнать его сможет разве что неумелое применение С# под Unity3D. Я и большую часть своих программ на С++ иначе как говнокодингом сейчас, взглянув на них, не назову. - Я понимаю, что тут накладывается моё субъективное восприятие, но сугубо imho - ООП как изначально преподаваемая парадигма породила еще больше говнокода и тут уже, увы, никуда не деться. Очень сложно посадить людей сначала освоить что-либо за пределами ООП. Засилье скриптеров (не мыслящих алгоритмов отдельно от языка реализации), а не программеров - свершившийся факт.
Сообщение отредактировал AlexRabbit - Воскресенье, 26 Июля 2015, 23:08
С++ — язык, который изучается постепенно. Лишь после того, как будет сделан последний шаг, разрозненные приемы и фрагменты синтаксиса начинают складываться в общую картину. По-моему, изучение С++ чем-то напоминает подъем на лифте. Дзынь! Второй этаж. С++ — это усовершенствованный вариант С, с сильной типизацией (которую, впрочем, при желании можно обойти) и удобными комментариями //. Любой программист на С, если он не хочет подаваться в менеджеры, должен двигаться дальше… а Бьярн Страуструп (Господи, благослови его) придумал для этого отличную возможность. Дзынь! Третий этаж. С++ — хороший, хотя и не потрясающий объектно-ориентированный язык программирования. Не Smalltalk, конечно, но чего ожидать от языка, работающего с такой головокружительной скоростью? С++ — это Cobol 90-х, политически выдержанный язык, которые гарантирует финансирование вашего проекта высшим руководством. А уж если С++ достаточно часто упоминается в плане, можно надеяться на удвоение бюджета. Это тоже хорошо, потому что никто толком не умеет оценивать проекты на С++ и управлять ими. А что касается инструментария — глаза разбегаются, не правда ли? Дзынь! Последний этаж, все выходят. Но позвольте, где же «все»? Лифт почти пуст. С++ — это на самом деле не столько язык, сколько инструмент для создания ваших собственных языков. Его элегантность заключается отнюдь не в простоте (слова С++ и простота режут слух своим явным противоречием), а в его потенциальных возможностях. За каждой уродливой проблемой прячется какая-нибудь умная идиома, изящный языковой финт, благодаря которому проблема тает прямо на глазах. Проблема решается так же элегантно, как это сделал бы настоящий язык типа Smalltalk или Lisp, но при этом ваш процессор не дымится от напряжения, а на Уолл-Стрит не растут акции производителей чипов памяти. С++ — вообще не язык. Это мировоззрение или наркотик, меняющий способ мышления.
Быдлокодеры любят повторять: "логика, убивающая мозг",- когда их пытаются заставить программировать.
Зачем нужен C++, если есть C, scala/java? По моему чем скорее это недразумение само себя искоренит - тем лучше. А STL - это вообще эпичный опус, в который без лсд лучше вообще не заглядывать. C++ напоминает рабочего, которому в угоду рабочего процесса, прикрутили железные руки, естественно оторвав натуральные. Допустим в C визуальное восприятие тоже может страдать, но те конструкции, что творят C++ программисты - это конечно ни в какое сравнение. Так и получается: и не ООП, и не C, т.е. мутант-педераст.
Wald_Kiefer, Вы забыли, где находитесь. Большая часть Форума - о конструкторах, т.е. об обезьянниках позволяющих что-то сделать, "не вылезая наружу". А современный C++ - это тоже "все в одном флаконе", но с претензией на профессионализм. Конструктор, доведенный до коммерческого идеала. Быдлокодеры любят повторять: "логика, убивающая мозг",- когда их пытаются заставить программировать.
Wald_Kiefer, Вы забыли, где находитесь. Большая часть Форума - о конструкторах, т.е. об обезьянниках позволяющих что-то сделать, "не вылезая наружу". А современный C++ - это тоже "все в одном флаконе", но с претензией на профессионализм. Конструктор, доведенный до коммерческого идеала.
Зачем нужен С, если есть ASM? Зачем нужен ASM, если можно в машинных кодах писать? Зачем компьютер использовать, если можно все в ручную на бумаге посчитать? Зачем...
По теме.
Зависит от задачи. На работе, где в основном пишу HPC вещи, плюсы в использую в режиме "Си с классами", ибо там голые массивы, да еще и руками выровненные под кэш и т.п. суровая необходимость, так что в ООП не развернешься. При разработке же обычных приложений(десктопный и серверный софт) на плюсах, за применения сишных конструкций и подходов в любой нормальной конторе бьют по рукам, так что там только ООП в максимально чистом виде.
C генерирует высокопроизводительный машинный код, но не поддерживает ООП, scala/java не генерирую высокопроизводительный машины код, но поддерживает ООП. С++ генерирует высокопроизводительный машинный код и поддерживает ООП.
Вопросы еще есть?)
Есть предположение что JVM сама написана па плюсах. Мои проекты: - Свободный и открытый клон World Of Goo - TrueEngine2D (2D игровой фреймворк основанный на FreeBASIC)
[GameMaker: Studio v1.4.9999]
Сообщение отредактировал OpenGOO - Вторник, 22 Декабря 2015, 16:25
Он, по сути, вообще не генерирует код, т.к. является, по сути, просто макроассемблером. Что пишу - то и получаю.
ЦитатаOpenGOO ()
C ... не поддерживает ООП
Не поддерживает ООП в стиле C++. Никто не мешает использовать методы ООП в C, или иметь доступ к ОО-библиотекам.
ЦитатаOpenGOO ()
С++ генерирует высокопроизводительный машинный код
Только, если не пользоваться дурацкими библиотеками (типа STL, табличку я приводил), не провоцировать компилятор на создание избыточных конструкторов и отказаться от умных указателей и прочего мусора.
ЦитатаOpenGOO ()
С++ ... поддерживает ООП.
В стиле C++? к нормальному ООП отношения не имеющему. Быдлокодеры любят повторять: "логика, убивающая мозг",- когда их пытаются заставить программировать.
Gudleifr, вы почти правы, за исключением: 1. С по сути, не просто макроассемблер. 2. Иметь доступ к ОО-библиотекам это не ООП. 3. Это только ваше мнение. 4. Не существует нормального ООП. Мои проекты: - Свободный и открытый клон World Of Goo - TrueEngine2D (2D игровой фреймворк основанный на FreeBASIC)
Gudleifr, вот вы так часто высказываете своё мнение по поводу С++ и STL... Но могли бы вы показать пример своего ООП кода? Просто такое ощущение, что вы всех призываете вернуться к процедурному программированию + вручную дёргать для каждой мелочи API ОС, забить на то, что уже давным-давно существует.
Мне такую идейку подсказали, что я даже поддержал её. Идея в том чтобы использовать C# и Си. То есть если не хватает скорости C#, то дописывать критические секции в виде библиотек на Си. Я думаю, это будет случаться крайне редко. У C++ огромное количество проблем по сравнению с C#. Что касается скорости, то 3DsMax полностью написан на C# - работает шустро.
Я обычно использую не ООП, а метод проблемно-ориентированного языка. Т.е. не строю иерархию объектов, а изобретаю язык, на котором задача описывается естественно, а затем его реализую. Например, простенькая библиотека переупаковки байтовых полей выглядит у меня так:
Код
#include "all.h"
/* Описание формата: <формат> ::= <массив> | <формат> [ "." ] <массив> ; -- следующие в памяти друг за другом фрагменты -- точка только для читабельности <массив> ::= <блок> | "(" <формат> ")" <блок> ] ; -- повторяющиеся фрагменты <блок> ::= [ <счетчик> ] [ <направление> ] ; -- простые блоки <счетчик> ::= NUM | "N" ; -- NUM байт (или повторов предыдущего блока), -- N - "до конца строки" (по умолчанию) <направление> ::= "D" | "B" -- в прямом (D, по умолчанию) или обратном (B) порядке Порядок: "естественным" порядком считается порядок, при котором самый правый бит - самый значащий (внутри байтов он поддерживается автоматически, при хранении байтов в памяти в виде строки или слова - обратный, т.е. естественным считается "B" (он же "NB")); Ограничения: В случае если лень ставить D, нужно поставить точку между <массивами>; NUM - неотрицательное десятичное число. Расширения: В любом месте можно поставить имя в кавычках (апострофах). */
static BYTE get_lex(i) /* лексический анализатор */ STRING *i; { num = 0; if (lexlit[**i] == 8) { /* имя в кавычках */ str = ++(*i); while (lexlit[*(*i)++] != 8); num = *i - str - 1; return 8; } if (lexlit[**i] != 9) return lexlit[*(*i)++]; while (lexlit[**i] == 9) /* число */ num = num * 10 + *(*i)++ - '0'; return 9; }
STRUCT(block) { /* узел дерева */ TREE(block) STRING name; /* указатель на имя, хранящееся в формате */ int ns; /* длина имени */ int thr; /* # текущего прохода */ int n, d; /* число подблоков, направление */ int s; /* сумма длин подблоков */ int is; /* сам или входит в блок с выбранным именем */ int s_nm; /* сумма длин подблоков нужного имени */ };
DEL0(block) /* деструктор узла */ TFREE(block) /* деструктор дерева */
static add_block(cur) /* добавить младшего сына */ pblock *cur; { pblock t; t = (*cur)->child; if (!t) { MALLOC(t, block) (*cur)->child = t; } else { while (!t->next) t = t->next; MALLOC(t->next, block) t = t->next; } t->dad = *cur; *cur = t; }
static get_sum(cur, nm, ns, is) /* расчет длины подблоков */ STRING nm; /* с учетом имени */ pblock cur; { pblock t; if (!is && nm && cur->name && cur->ns == ns && !strncmp(nm, cur->name, cur->ns)) is =1; cur->is = is; if (t = cur->child) while (t) { cur->s += get_sum(t, nm, ns, is) * t->n; cur->s_nm += t->s_nm * t->n; t = t->next; } else { cur->s = 1; if (is) cur->s_nm = 1; } return cur->s; }
static test_tree(cur, t) /* тестовая выдача дерева блоков */ pblock cur; { pblock c; int i; for (i = 0; i < t; i++) printf("\t"); printf("n=%d d=%d s=%d is=%d s_nm=%d", cur->n, cur->d, cur->s, cur->is, cur->s_nm); if (cur->name) { char *s; NALLOC(s, cur->name, cur->ns) printf("\t\"%s\"", s); } printf("\n"); if (c = cur->child) test_tree(c, t + 1); if (c = cur->next) test_tree(c, t); }
static build(o, cur, n, p, l) /* генерация таблиы перестановок */ pblock cur; /* n - куда, p - откуда */ int *o; { pblock t; int i; if (!cur->n) /* блок до конца строки */ cur->n = (l - p) / cur->s; for (i = 0; i < cur->n; i++) /* повтор подблоков */ if (t = cur->child) /* подблоки */ build(o, t, n + i * cur->s, cur->d ? p + (cur->n - i - 1) * cur->s : p + i * cur->s, /* учет порядка */ p + (i + 1) * cur->s); else /* байты */ o[n + i] = cur->d ? p + cur->n - i - 1 : p + i; n += cur->s * cur->n; if (t = cur->next) n = build(o, t, n, p + cur->s * cur->n, l); return n; }
static build_nm(o, cur, n, p, l) /* генерация таблиы перестановок */ pblock cur; /* с учетом имени */ int *o; /* n - куда, p - откуда */ { pblock t; int i; if (!cur->n) /* блок до конца строки */ cur->n = (l - p) / cur->s; for (i = 0; i < cur->n; i++) /* повтор подблоков */ if (t = cur->child) /* подблоки */ build_nm(o, t, n + i * cur->s_nm, cur->d ? p + (cur->n - i - 1) * cur->s : p + i * cur->s, /* учет порядка */ p + (i + 1) * cur->s); else /* байты */ if (cur->is) o[n + i] = cur->d ? p + cur->n - i - 1 : p + i; n += cur->s_nm * cur->n; if (t = cur->next) n = build_nm(o, t, n, p + cur->s * cur->n, l); return n; }
static build_n(cur, p, l) /* пересчет полей с учетом имени и, */ pblock cur; /* возможно (l != 0), длины входа */ { pblock t; int i, n; n = 0; if (!cur->is) { if (t = cur->child) n = build_n(t, p, p + cur->s) * cur->n; } else n = 1; if (l && !cur->n) /* блок до конца строки */ n *= (l - p) / cur->s; else if (t = cur->next) n += build_n(t, p + cur->s_nm * cur->n, l); return n; }
static parser(root, f, l, nm, ns) /* генерация дерева блоков */ pblock root; BYTE *f; STRING nm; /* с учетом имени */ { int c; pblock cur; cur = root; while (c = get_lex(&f)) { /* взять лексему */ if (c == '.') /* принудительно следующий блок */ add_next(&cur); if (c == '(') { /* повторяющийся блок */ if (cur->n) /* следующий блок */ add_next(&cur); add_block(&cur); } else if (c == 9) { /* длина блока в подблоках */ if (cur->n) /* следующий блок */ add_next(&cur); cur->n = num; } else if (c == 8) { /* имя блока */ cur->name = str; cur->ns = num; } else if (c == 'N') { /* длина остается 0 */ if (cur->n) /* следующий блок */ add_next(&cur); } else if (c == 'B') /* обратный порядок в блоке */ cur->d = 1; /* 'D' - ничего не делает */ else if (c == ')') /* конец блока */ cur = cur->dad; } cur = root; while (cur) { /* рассчитать длину подблоков */ get_sum(cur, nm, ns, 0); cur = cur->next; } /* test_tree(root, 0); */ }
static int *make_o(f, l) /* создать табоицу перестановки f->"" */ STRING f; { int *o; pblock root; /* охватывающий блок */ ALLOC(o, int, l) /* выделить место под таблицу */ MALLOC(root, block); parser(root, f, l, NULL, 0); /* построение дерева блоков */ build(o, root, 0, 0, l); /* генерация таблицы */ freeblock(root, 1); /* удаление дерева */ return o; }
static int *make_o_nm(f, l, nm, lo) /* создать табоицу перестановки f->"" */ STRING f, nm; /* с учетом имени */ int *lo; { int *o; pblock root; /* охватывающий блок */ ALLOC(o, int, l) /* выделить место под таблицу */ MALLOC(root, block); parser(root, f, l, nm, strlen(nm)); /* построение дерева блоков */ *lo = build_nm(o, root, 0, 0, l); /* генерация таблицы */ freeblock(root, 1); /* удаление дерева */ return o; }
gswap(fi, fo, ti, to, l) /* копировать l байтов из ti в to, */ STRING fi, fo, ti, to; /* согласно форматов fi и fo */ { int i, *oi, *oo; oi = make_o(fi, l); /* перестановочная таблица fi->"" */ oo = make_o(fo, l); /* перестановочная таблица fo->"" */ for (i = 0; i < l; i++) /* копирование ti->to с перестановкой */ to[oo[i]] = ti[oi[i]]; }
gget(fi, fo, ti, to, l, nm) /* вывести в to (согласно fo) все */ STRING fi, fo, ti, to, nm; /* значения полей с именем nm из ti */ { /* (формата fi и длиной l) */ int i, *oi, *oo, lo; oi = make_o_nm(fi, l, nm, &lo); /* перестановочная таблица fi->"" */ if (lo) { /* имя найдено */ oo = make_o(fo, lo); /* перестановочная таблица fo->"" */ for (i = 0; i < lo; i++) /* копирование ti->to с перестановкой */ to[oo[i]] = ti[oi[i]]; } return lo; }
ggetnum(f, l, nm) /* выдать количество полей */ STRING f, nm; /* с именем nm из формата f */ { /* при длине входного текста l */ int n; pblock root; /* охватывающий блок */ MALLOC(root, block); parser(root, f, l, nm, strlen(nm)); /* построение дерева блоков */ n = build_n(root, 0, l); /* пересчет полей */ freeblock(root, 1); /* удаление дерева */ return n; }
gset(fi, fo, ti, to, l, nm) /* заместить в ti (формата fi и */ STRING fi, fo, ti, to, nm; /* длины l) все поля с именем nm */ { /* на to (формата fo) */ int i, *oi, *oo, lo; oi = make_o_nm(fi, l, nm, &lo); /* перестановочная таблица fi->"" */ if (lo) { /* имя найдено */ oo = make_o(fo, lo); /* перестановочная таблица fo->"" */ for (i = 0; i < lo; i++) /* копирование to->ti с перестановкой */ ti[oi[i]] = to[oo[i]]; } return lo; }
pname_list gfields(f) /* выдергивание имен из формата; */ STRING f; /* имена остаются в формате, */ { /* хранятся только указатели */ pname_list x; int c; x = NULL; while (c = get_lex(&f)) {/* взять лексему */ if (c == 8) { /* имя блока */ pname_list t; MALLOC(t, name_list) t->s = str; t->ns = num; t->next = x; x = t; } } return x; }
BYTE I[900], O[900];
main() { int i, l; STRING fi; pname_list p; /* scanf("%d", &l); read_hex(I, l); write_hex(I + 72 + 36, 32); printf("\n"); */ fi = "'C_UZ'64.4'C_UZ_IMIT'4'IM_UZ'(32'C_LMK'.4'C_LMK_IMIT')20.4'C_FSG'.4'C_FSG_IMIT'"; /* l = gget(fi, "", I, O, l, "C_LMK_IMIT"); write_hex(O, l); printf("\n"); p = gfields(fi); */ printf("%d\n", ggetnum(fi, 828, "C_LMK_IMIT")); }
Можно видеть, что я нигде не ставлю проверок допустимости параметров. Это основное правило обеспечения работоспособности кода. Умные данные - это самый верный способ оставить в коде дыру. Пусть код валится как можно чаще и пусть все ошибки будут видны на верхнем уровне - тогда будет шанс их обнаружить. *** Наиболее удобный этап выйти на удобный проблемно ориентированный язык - перед началом планирования в обычном блокноте попытаться нарисовать программу как некую Incredible Machine (в крайнем случае - панель прибора/план завода, который вы будете эмулировать/асучивать). Например (художник я еще тот, проект):
Или текстом см. там. *** Если модель не удается проработать на бумаге, то получается срашненько. Например, как в Лунолете. *** Но, конечно, этот метод лучше всего работает в языке FORTH. Быдлокодеры любят повторять: "логика, убивающая мозг",- когда их пытаются заставить программировать.
Сообщение отредактировал Gudleifr - Четверг, 24 Декабря 2015, 15:10
Переключение между managed и unmanaged кодом не бесплатное.
Цитата8Observer8 ()
Я думаю, это будет случаться крайне редко.
При написании простой логики и правда, вполне достаточно C#, однако, все обстоит иначе при работе с большими объемами памяти.
Цитата8Observer8 ()
У C++ огромное количество проблем по сравнению с C#
Проблемы не в языке, а у тех, кто не умеет его использовать. Сам по себе C++ не несет каких-то подводных камней, если не использовать хитрые конструкции языка. Выделил память, поработал с ней, освободил. В C# же правила несколько усложняются: объект никогда не будет удален, пока к нему есть доступ, многие объекты используют дополнительные ресурсы, которые нужно освободить (обычно все такие объекты имеют реализацию интерфейса IDisposable). Тот же деструктор у объекта вызывается когда захочет GC, что тоже может поставить в тупик новичка.
По крайней мере у меня сложилось такое впечатление, т.к. я много лет писал на C++ и когда перешел на C#, то в первые месяцы все время натыкался на подобные ньюансы.
ЦитатаStorm54 ()
изобретаю язык, на котором задача описывается естественно, а затем его реализую
У Вас есть опыт коммерческой разработки или хотя бы опыт работы в команде? Ни в одном проекте не встречал более одного скриптового языка (аля LUA), каждый из которых был бы заточен под конкретную задачу. А уж тем более, писать свой язык - слишком дорого и не в одной нормальной конторе на такое бы не согласились, если, конечно, этот язык не планируют использовать для сотен, а то и тысяч задач.
Сообщение отредактировал Storm54 - Среда, 23 Декабря 2015, 17:55
Storm54, цитируйте аккуратнее, а то я чуть не просмотрел Ваше замечание.
Есть три Unix- и один Forth-способ написать свой язык. Насколько они трудны? Судите сами:
1. Если язык служит чисто служебной цели, как в примере выше, то его очень просто реализовать на любом языке. Развитием этого метода служат языки C++ и Python, но они ущербны. На C++ невозможно написать ничего кроме C++, а на Python написать что-то сложное просто проблемно.
2. Если язык достаточно прост, но требует развитых интерфейсов, то его можно реализовать просто средствами Unix-скриптования. shell, sed, awk... Например, можно написать Perl-обработчик команд и засунуть его в Tcl/Tk-оболочку. Так можно лепить достаточно сложные продукты:
Подробнее см. там. Я там предлагаю даже более простой набор (Perl+HTML).
3. Если язык сложен, но Unix предлагает спарку lex + yacc и их последлвателей. Компиляторы компиляторов. На входе - грамматика, на выходе - готовый компилятор. Минус, как в C++ - требование полноценной НИОКР по проходу "сверху вниз", как однажды написанную сложную иерархию классов фиг подправишь, так и грамматику "чуть-чуть" не улучшишь.
4. Наконец, FORTH. Ядро языка пригодное для развертывания вашего языка пишется на коленке за две недели. Затем вы строите свои лексиконы строго по вашему решению задачи, перекладывая свои мысли в программу один-в-один. Минусы? FORTH-программы пишутся очень быстро и очень компактны, но это касается только исходных текстов. Готовые программы не такие уж и быстрые и маленькие.
Есть ли альтернативы написанию своего языка? Я, разумеется, имею в виду случай большой программы (для маленькой ничего изобретать особо и не надо).
Большой кусок, возможно войдет в "заметки", неоконченный
Возможно, настоящие писатели могут писать свои романы в свободной форме - все более углубляя и расширяя произведение - и не имеют проблем с добавлением новых поворотов сюжета или свежих идей туда, куда надо. Возможно даже, есть программисты, способные так же писать программы - постепенно добавляя все новые и новые возможности, и без труда преодолевают тот рубеж, на котором мои программы если и не перестают работать, то начинают терять в фунциональности после каждого исправления ошибок, вызванных очередным "улучшением". Однако, я не видел ни таких программистов, ни таких программ. Если угодно, эту проблему описал Дейкстра еще в 70-е годы XX века. А Брукс сделал популярной ее формулировку: "Серебряной пули не существует".
Какие же способы, кроме очевидного "взять и написать то, что надо", существуют?
Видимо, есть два "философских" способа. Первый - рассматривать большую программу как машину, собранную из других машин, связанных простыми интерфейсаи (см. "Заметки о структурном программировании" Дейкстры). Вопрос модификации программы т.о. решается как замена одной из машин на другую с тем же интерфейсом Второй - изобретение языка, на котором решение задачи можно описать достаточно просто. Пограмма в этом случае тредставляется как набор переводчиков с языка на язык.
Т.к. между понятиями "машина" и "язык" в программировании существует взаимооднозначное соответствие, то выбор "философии" определяется, скорее тем, с чем мы имем дело - с компилятором или с интерпретатором.
Каковы практические решения, порожденные нашей философией? И, самое главное, какие подводные камни нас ожидают?
1. "Плюем и копипастим". Очевидно, что чем "последовательнее" куски кода, тем длиннее они могут быть. Но где найти столь выразительный язык, чтобы на нем можно было бы писать без "петель"? На помощь приходят Операционные Системы. Они разрешают пользователю писать только отдельные главы "Что произойдет, когда пользователь нажмет на кнопку?", "Что надо не забыть при размещении окна на экране?",.. А связь между главами берут полностью на себя. В такой умной среде даже достаточно сложно привязанную к сюжету "главу" можно просто приписать в конец программы. Минус подхода, разумеется, в том, что здесь не писатель управляет сюжетом, а сюжет - писателем. Мы постоянно видим вокруг программы, напрягающими пользователя заполнением ненужных ему форм, требуя от него ненужных подтверждений очевидного, навязывая ненужные ритуалы.
2. "Структутное программирование". В своей книге "Дисциплина программирования" Дейкстра ввел аксиоматику соединения программных глав в единое произведение. Два важнейших способа - операторы выбора и цикла. Со временем аксиоматика забылась и программисты уверовали, что цикл может гарантировать им чуть ли не кибернетическую ультраустойчивость, а выбор обеспечит возможность учеть "все". Эти два оператора ответственны за увеличение мусора в программах на один, а то и два, порядка. Чтобы это оценить нуджно вспомнить аксиоматику. Она проста (если не вникать в математику): основное качество цикла не способность вовремя остановиться, а способность сохранять т.н. "инвариант цикла", что позволяет ему не пойти вразнос; с выбором все очевиднее - этот оператор должен учитывать все варианты не в смысле "все что придет в голову", а в смысле "честной мат.логики" - всех возможных наборов значений переменых, входящих в условие выбора. Как это работает?
Обычная ошибка применения циклов - "матрешка". Циклы вкладываются один в другой не "по логике", а "по сюжету". Кроме потерь на лишние переборы, порожденые именением одной-двух переменных состояния, приходится слишком долго проверять, не был ли поврежден "инвариант". А, если программист сам плохо понимает, какой инвариант к какому циклу относится, число проверок/восстановлений растет в геометрической прогрессии.
Аналогичная ошибка в использовании оператора выбора является "елочка". Вместо последовательной обработки отдельных переменных состояния, при неудачном распределении последних, получается громоздкое дерево. Для всех вариантов значения первой переменной, проверяются все значения второй, для каждого значения второй - все значения третьей... В сложных елочках часто происходит более одной проверки одного одного условия, т.к. понять была ли ранее сделана та или другая проверка достаточно сложно, особенно после внесения пары-другой исправлений.
Как избежать матрешки и елочки? Нужно стараться отделить логику управления от других вычислений программы. А затем - попытаться ее упростить по правилам обычной математики.
Несмотря на трудность правильного применения структурного програмирования, оно позволяет писать очень красивые (и доказуемо правильные) программы.
3. "Масштабирование". С ростом популярности языка C термин "структурное программирование" стал использоваться в другом значении - как программирование путем бесконечной группировки структур (кода и данных) в более крупные структуры. Появилось так же и его доведение до абсурда - "объектно-ориентированное програмирование" - создание неких универсальных структур (объединяющих - "инкапсулирующих" - в себе и код, и данные вместе).
Для увеличения сложности таким путем, очевидно, характерен "синдром чайника" - когда "вылить уже налитую воду" проще, чем переписать процедуру "кипячения".
Другой источник мусора при таком подходе - избыточность предохранительных процедур, которые "для универсальности и безопасности" вставляют во все процедуры, где неправильные данные могут вызвать ошибки. Такой подход не только приводит к жуткой избыточности ненужных проверок, но и служит источником ошибок - необнаружению критических сбоев.
ЦитатаStorm54 ()
У Вас есть опыт коммерческой разработки или хотя бы опыт работы в команде?
Уже отечал: да и да. Но, кстати, раз уж вспомнил Дейкстру:
Цитата
Наконец, эта задача позволяет нам рассеять некоторые сомнения, вызванные тем, что коммерческие программы являются чем-то особенным. (Если уж говорить о чем-то особом, то, скорее, о характере коммерческих программистов...)
Быдлокодеры любят повторять: "логика, убивающая мозг",- когда их пытаются заставить программировать.
Сообщение отредактировал Gudleifr - Среда, 23 Декабря 2015, 19:08
При написании простой логики и правда, вполне достаточно C#, однако, все обстоит иначе при работе с большими объемами памяти.
Разработчик посмотрит на техническое задание и скажет: "Так, здесь очень простая логика, поэтому напишу ПО на C#, а вот эта задача требует очень много памяти, значит, решу на C++". Но пока у меня нет задач, где требуется много памяти. C# мне прежде всего нравится своей простотой, безопасностью и богатством конструкций: свойства, события, атрибуты, интерфейсы, делегаты и т.д. А ещё тем, что можно можно легко и естественно использовать модульные тесты: mock- и fack объекты, то есть NUnit и NSubstitute, которые легко можно поставить через NuGet. На C++ недружелюбное использование Google Mock и исключений. Я сам с 2007 по 2015 работал на C++, так что я могу сравнивать эти языки.
Сообщение отредактировал 8Observer8 - Среда, 23 Декабря 2015, 19:34