Здравствуйте, FDSC, Вы писали:
FDS>Хм. А вот что делать, если мне нужно реализовать процедуру умножения транспонированных матриц (очень просто, неправда ли?). FDS>Варианты реализации:
FDS>1. Для того, что бы перемножить некоторым образом транспонированные матрицы я их транспонирую отдельной функцией и затем передаю в обычную процедуру умножения матриц FDS>Минус: понижение производительности. Ведь я мог бы перемножить матрицы без физического транспонирования
Матрицу физически транспонировать и не надо.
Сделай у матрицы флаг транспонированности, а внутри свойства доступа к элементам матрицы меняй индексы местами, если флаг транспонированности установлен.
Или, если боишься if-а при доступе к элементам матрицы, сделай класс "транспонированная матрица", унаследованный от матрицы, имеющий внутри ссылку на исходную матрицу и оверрайдни свойство доступа к элементам.
Здравствуйте, IT, Вы писали:
IT>На бумажке уже даже не помню когда писал. Писать начинаю в коде сразу, даже ещё не понимая что получится в результате. [cut] При таком подходе опысываемые тобой ошибки исключены.
А как можно при таком подходе оценить время необходимое на реализацию ?
"Если Вы отличаетесь от меня, то это ничуть мне не вредит — Вы делаете меня богаче". Экзюпери
Здравствуйте, IT, Вы писали:
IT> Только, к сожалению, по моим наблюдениям между умением говорить такие банальности и умением их применять лежит огромная пропасть, мостиком через которую как раз и являются практические приёмы и навыки.
В самую точку.
"Если Вы отличаетесь от меня, то это ничуть мне не вредит — Вы делаете меня богаче". Экзюпери
Здравствуйте, Mirrorer, Вы писали:
IT>>На бумажке уже даже не помню когда писал. Писать начинаю в коде сразу, даже ещё не понимая что получится в результате. [cut] При таком подходе опысываемые тобой ошибки исключены.
M>А как можно при таком подходе оценить время необходимое на реализацию ?
Очень просто. Это время равно от нуля, до времени необходимого на подчистку кода.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>То для чего можно написать юнит-тест То есть кусок кода, который можно выполнить не инициализируя всего приложения. Где-то так.
Вообще-то технология давно отлажана. Клепаешь фэйк-объекты (МОК-объекты) и оборачиваешь ими все что не лезет в концепцию юнит-тестов. Далее загружаешь нужное состояние и вперед.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: Ошибок не делает тот, кто ничего не делает
Здравствуйте, Andrei N.Sobchuck, Вы писали:
AVK>>Янус спроектирован таким образом. Только проблема там в другом месте.
ANS>О да. Просвети нас, чем же именно уникален Янус?
Это скорее к тебе вопрос.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IT, Вы писали:
IT>1. Настоящий индеец прежде всего заходит в меню Debug и в диалоге Exceptions включает галку Thrown на CLR Exceptions для managed языков. Это позволяет сэкономить не просто хучу, а туеву хучу времени при поиске ошибок. Отсюда следствие — настоящие индейцы не используют логику на исключениях, иначе весь кайф пропадает.
Жаль мы с тобой все же не всегда настоящие индейцы. Потому как после того как ты в Интеграции сам знаешь чего реализовал комбы со списками типов и методов в редактироуемом файле, то сразу стала проявляться суть настоящего индусяцкого кода лежащего в:
...\VsSDK\2007.02\VisualStudioIntegration\Common\Source\CSharp\LanguageService\CodeWindowManager.cs
// Omitting any of the following operator overloads
// violates FxCop rule: IComparableImplementationsOverrideOperators.
/// <include file='doc\CodeWindowManager.uex' path='docs/doc[@for="DropDownMember.Operator=="]/*' />public static bool operator ==(DropDownMember m1, DropDownMember m2) {
return m1.Equals(m2);
}
приводящего к ловине:
System.NullReferenceException occurred
Message="Object reference not set to an instance of an object."
Source="Microsoft.VisualStudio.Package.LanguageService"
StackTrace:
at Microsoft.VisualStudio.Package.DropDownMember.op_Equality(DropDownMember m1, DropDownMember m2)
Вот так один индус может испортить жизнь двум индейцам.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IT, Вы писали:
FDS>>Формой с методами обработки информации.
IT>Т.е. написал для отладки отдельный гуй?
А почему нет если задача требует? Вот представь, ты должен отдать список иконок другому приложнию (студии, например). Самый прсотой способ убедиться, что с картинками все ОК — склепать примитивную форму с ЛистВью в который выведены иконки.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IT, Вы писали:
IT>>>Кстати, один из способов, позволяющих решить эту проблему, это локальные функции. К сожалению, в C# этого нет, и пока, как я понял не планируется.
M>>Ну можно это будет лямбдами сэмулировать. Хотя для 3х уровней вложенности это ужастик получится, да.
IT>На каждую такую функцию уморишься делегаты ообъявлять. Короче, лажа это. Без крайней необходимости никто этим пользоваться не будет.
Кстати, илюстрация к грусному. По причине завязанности алгоритма на некоторые классы Студии был вынужден писать класс-хелпер на C# 2.0. Но к лямбдам и т.п. как-то прям тянет. В итоге родилось вот такое чудо:
#region MatchBraces()
private AuthoringScope MatchBraces(ParseRequest request)
{
if (!request.Sink.BraceMatching)
return GetDefaultScope(request);
// Steps:
// 1. Find token under text caret.
// 2. Determine that it is a paired token.
// 3. Determine paired token.
// 4. Find paired token in the source file.
// 5. Set info about paired tokens Sink and return it in AuthoringScope.#region Init vars
ProjectInfo projectInfo = GetProjectInfo(request);
if (projectInfo == null)
return GetDefaultScope(request);
NemerleSource source = projectInfo.GetSource(request.FileName);
IVsTextColorState colorState = source.ColorState;
Colorizer colorizer = source.GetColorizer();
NemerleScanner scanner = (NemerleScanner)colorizer.Scanner;
string lineText = source.GetLine(request.Line);
scanner.SetSource(lineText, 0);
#endregion// Steps: 1-3
BracketFinder bracketFinder = new BracketFinder(source, request.Line + 1,
request.Col + 1, scanner, colorState);
// 4. Find paired token in the source file.
ScanTokenInfo matchBraceInfo = bracketFinder.FindMatchBraceInfo();
if (matchBraceInfo != null)
{
// 5. Set info about paired tokens Sink and return it in AuthoringScope.
request.Sink.FoundMatchingBrace = true;
// Fix a bug in MPF: Correct location of left token.
// It need for correct navigation (to left side of token).
Token mactTok = matchBraceInfo.Token;
Location mactLoc = request.Reason == ParseReason.MatchBraces
&& !BracketFinder.IsOpenToken(mactTok)
? mactTok.Location.FromEnd() : mactTok.Location;
request.Sink.MatchPair( // Set tokens position info
Convert(bracketFinder.StartBraceInfo.Token.Location),
Convert(mactLoc), 0);
return new NemerleAuthoringScope(
projectInfo, request.Sink, request.FileName,
new SourceTextManager(projectInfo.GetSource(request.FileName)));
}
return GetDefaultScope(request); // we don't fing paired token
}
#endregion
#region BracketFinder class/// <summary>
/// Helper class which match paired token (brackets, brace, etc.)
/// </summary>private class BracketFinder
{
#region Fields
public ScanTokenInfo StartBraceInfo;
IVsTextColorState ColorState;
NemerleSource Source;
int StartLine;
ScanLexer Lex;
NemerleScanner Scanner;
#endregion
public BracketFinder(NemerleSource source, int startLine,
int startCol, NemerleScanner scanner, IVsTextColorState colorState)
{
#region Init fields
Scanner = scanner;
Source = source;
StartLine = startLine;
Lex = scanner.GetLexer();
Lex.SetFileName(source.GetFilePath());
ColorState = colorState;
#endregion
#region 2. Determine that it is a paired token. 3. Determine paired token.
// Get tokens of line under text carret into dynamic array.
List<ScanTokenInfo> lineToks = GetLineTokens(startLine, true);
// Find index of token which located under text carret.int index = FindIndex(lineToks,
delegate(ScanTokenInfo x)
{ return x.Token.Location.Contains(startLine, startCol); });
// If index is corret get corresponding token.
ScanTokenInfo startBraceInfo = index < 0 ? null : lineToks[index];
// Remember it, if token have paired token.if (IsPairedToken(startBraceInfo.Token))
StartBraceInfo = startBraceInfo;
else
{
// otherwise try get right-hand token...
startBraceInfo = RightHand(lineToks, index);
// Remember it, if token have paired token.if (IsPairedToken(startBraceInfo.Token))
StartBraceInfo = startBraceInfo;
}
#endregion
}
public ScanTokenInfo FindMatchBraceInfo()
{
if (StartBraceInfo == null)
return null;
// 4. Find paired token in the source file.
Token tok = StartBraceInfo.Token;
Predicate<Token> isStartBrace = GetMatchBracePredicate(tok);
Predicate<Token> isEndBrace = GetMatchBracePredicate(GetPairedToken(tok));
int nestedLevel = 1;
foreach (ScanTokenInfo tokInfo in GetTokenIter())
{
if (isEndBrace(tokInfo.Token))
nestedLevel--;
else if (isStartBrace(tokInfo.Token))
nestedLevel++;
if (nestedLevel == 0)
return tokInfo; // Match found!
}
return null; // Match not found.
}
#region GetTokenIter()
/// <summary>
/// Return iterator which allow iterate throw tokens of curent
/// source file. Iteration process start from token behind current
/// token and go forward or backward depending on type of start token.
/// If start token is open token (for example, "(" or "{") iteration
/// execute forward. If start token is close token (for example, ")"
/// or "]") iteration execute backward.
/// </summary>private IEnumerable<ScanTokenInfo> GetTokenIter()
{
bool isScanForward = IsOpenToken(StartBraceInfo.Token);
int startLine = StartLine;
// 1. Для первой строки находим токен и начиная от него сканируем вперед или назад.
List<ScanTokenInfo> tokInfs = new List<ScanTokenInfo>(
GetLineTokens(startLine, isScanForward));
int tokIndex = FindIndex(tokInfs, delegate(ScanTokenInfo ti)
{ return ti.Token.Location == StartBraceInfo.Token.Location; });
if (tokIndex < 0)
throw new Exception("tokInfs.IndexOf(startBraceInfo)");
// Scan first line from "start bracket" index.for (int i = tokIndex + 1; i < tokInfs.Count; i++)
yield return tokInfs[i];
if (isScanForward) // Scan next lines.for (int i = startLine + 1, count = Source.GetLineCount(); i <= count; i++)
foreach (ScanTokenInfo tokInf in GetLineTokens(i, true))
yield return tokInf;
else// Scan previous lines.for (int i = startLine - 1; i >= 0; i--)
foreach (ScanTokenInfo tokInf in GetLineTokens(i, false))
yield return tokInf;
}
#endregion
#region GetLineTokens()
/// <summary>
/// Get tokens of specified line.
/// </summary>
/// <param name="line">Line number which tokens it is necessary retrieve</param>
/// <param name="isForward">Direction of iteration (true is forward)</param>
/// <returns>Token list</returns>
List<ScanTokenInfo> GetLineTokens(int line, bool isForward)
{
ScanState scanState = GetLineState(line);
string lineText = Source.GetLine(line - 1);
Scanner.SetSource(lineText, 0);
Lex.SetLine(line, lineText, 0, null, null);
List<ScanTokenInfo> lst = new List<ScanTokenInfo>();
foreach (ScanTokenInfo var in GetLineTokens(Lex, scanState))
lst.Add(var.Clone());
if (!isForward)
lst.Reverse();
return lst;
}
/// <summary>Return colorer lexer state for specified line.</summary>private ScanState GetLineState(int line)
{
int state;
ErrorHandler.ThrowOnFailure(
ColorState.GetColorStateAtStartOfLine(line, out state));
return (ScanState)state;
}
/// <summary>
/// Imlementation of GetLineTokens(). Don't use this method directly!
/// </summary>
IEnumerable<ScanTokenInfo> GetLineTokens(ScanLexer lex, ScanState scanState)
{
ScanTokenInfo info = lex.GetToken(scanState);
scanState = info.State;
while (!info.IsEndOfLine)
{
yield return info;
info = lex.GetToken(scanState);
scanState = info.State;
}
}
#endregion
#region Paired token identification functions
public static bool IsOpenToken(Token token)
{
if (token is Token.BeginBrace) return true;
if (token is Token.BeginQuote) return true;
if (token is Token.BeginRound) return true;
if (token is Token.BeginSquare) return true;
if (token is Token.EndBrace) return false;
if (token is Token.EndQuote) return false;
if (token is Token.EndRound) return false;
if (token is Token.EndSquare) return false;
Token.Keyword kwd = token as Token.Keyword;
if (kwd != null)
{
if (kwd.name == "if") return true;
if (kwd.name == "else") return false;
}
throw new Exception("The token '" + token + "' not a brace!");
}
private static bool IsPairedToken(Token token)
{
if (token is Token.BeginBrace || token is Token.BeginQuote
|| token is Token.BeginRound || token is Token.BeginSquare
|| token is Token.EndBrace || token is Token.EndQuote
|| token is Token.EndRound || token is Token.EndSquare
)
return true;
Token.Keyword kwd = token as Token.Keyword;
if (kwd != null && (kwd.name == "if" || kwd.name == "else"))
return true;
return false;
}
/// <summary>
/// Return predicate function which check it argument is same token .
/// </summary>private static Predicate<Token> GetMatchBracePredicate(Token token)
{
if (token is Token.BeginBrace)
return delegate(Token t) { return t is Token.BeginBrace; };
if (token is Token.BeginQuote)
return delegate(Token t) { return t is Token.BeginQuote; };
if (token is Token.BeginRound)
return delegate(Token t) { return t is Token.BeginRound; };
if (token is Token.BeginSquare)
return delegate(Token t) { return t is Token.BeginSquare; };
if (token is Token.EndBrace)
return delegate(Token t) { return t is Token.EndBrace; };
if (token is Token.EndQuote)
return delegate(Token t) { return t is Token.EndQuote; };
if (token is Token.EndRound)
return delegate(Token t) { return t is Token.EndRound; };
if (token is Token.EndSquare)
return delegate(Token t) { return t is Token.EndSquare; };
Token.Keyword kwd = token as Token.Keyword;
if (kwd != null)
{
if (kwd.name == "if")
return delegate(Token t)
{
Token.Keyword kwd1 = t as Token.Keyword;
if (kwd1 != null)
return kwd1.name == "if";
return false;
};
if (kwd.name == "else")
return delegate(Token t)
{
Token.Keyword kwd1 = t as Token.Keyword;
if (kwd1 != null)
return kwd1.name == "else";
return false;
};
}
return null;
}
private static Token GetPairedToken(Token token)
{
if (token is Token.BeginBrace) return new Token.EndBrace(true);
if (token is Token.BeginQuote) return new Token.EndQuote();
if (token is Token.BeginRound) return new Token.EndRound();
if (token is Token.BeginSquare) return new Token.EndSquare();
if (token is Token.EndBrace) return new Token.BeginBrace(true);
if (token is Token.EndQuote) return new Token.BeginQuote();
if (token is Token.EndRound) return new Token.BeginRound();
if (token is Token.EndSquare) return new Token.BeginSquare();
Token.Keyword kwd = token as Token.Keyword;
if (kwd != null)
{
if (kwd.name == "if") return new Token.Keyword("else");
if (kwd.name == "else") return new Token.Keyword("if");
}
return null;
}
#endregion
#region Utils
static T RightHand<T>(IList<T> lst, int index) where T : new()
{
int nextIndex = index + 1;
if (nextIndex >= lst.Count)
return new T();
return lst[nextIndex];
}
private static List<T> Reverce<T>(IEnumerable<T> seq)
{
List<T> lst = new List<T>(seq);
lst.Reverse();
return lst;
}
static T Find<T>(IEnumerable<T> seq, Predicate<T> predicate) where T : class
{
foreach (T item in seq)
if (predicate(item))
return item;
return null;
}
static int FindIndex<T>(IList<T> lst, Predicate<T> predicate) where T : class
{
for (int i = 0; i < lst.Count; i++)
if (predicate(lst[i]))
return i;
return -1;
}
#endregion
}
#endregion
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IT, Вы писали:
_M>>но по крайней мере зверя ContextSwitchDeadLock я буду включать только через свой труп — он мне столько нервов попортил...
IT>Не включай. Я лично вообще такого исключения ни разу в жизни не видел.
Это похоже то из-за чего у нас отладка под студией навертывается .
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Вообще-то технология давно отлажана. Клепаешь фэйк-объекты (МОК-объекты) и оборачиваешь ими все что не лезет в концепцию юнит-тестов. Далее загружаешь нужное состояние и вперед.
Если нечто инициализируется где-то в недрах проги, то сделать мок может не быть возможности. В том то и вопрос, что нужно писать с учетом подобных операций.
N>>В идеале, тесты должны полностью воссоздавать все окружение, в котором работает система. Например, если используется база данных, то хорошие тесты должны уметь создать ее "с нуля", прогнав необходимые скрипты, заполнить данными и "погонять" в разных режимах
_M>Такие тесты уже на юнит тесты мало похожи и если я правильно понял это называется тестированием интеграции. Сейчас пишу такой тест, получается что-то типа "виртуального пользователя", который совершает все возможные действия с программой, начиная "с чистого листа". Только результаты выполнения каждой команды сверять смысла нет, да и сложно это. Просто если во время выполнения какой-нибудь команды возникает ошибка (а в методах много проверок входных параметров, проверок промежуточных результатов), то всё это дело останавливается. Вроде нормально получается, я на правильном пути?
Почти. Результаты проверять надо. В этом как раз помогут мок-объекты.
Но для этого архитектура системы должна быть достаточно "слоистой" или хотя бы модульной.
IT>Это не всегда возможно. Точнее, это возможно для ограниченного круга задач.
На данном этапе развития технологий фактически возможно для большинства задач.
Просто конструировать надо сразу с расчётом на тестирование.
Или (в теории) на основе готовых тестов.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Re[3]: Ребят, я понимаю, что вам смешно, но проблема правда
Здравствуйте, VGn, Вы писали:
IT>>Это не всегда возможно. Точнее, это возможно для ограниченного круга задач.
VGn>На данном этапе развития технологий фактически возможно для большинства задач.
UI в это большинство задач вписывается? 30 полей на форме с более менее зависимой логикой отображения и ты состаришься раньше, чем напишешь все возможные тесты. А когда напишешь, я добавлю ещё 10 полей. Только не в конец формы, а в случайном порядке с новой особенной логикой.
VGn>Просто конструировать надо сразу с расчётом на тестирование.
Конструировать надо не в расчёте на тестирование, а в расчёте на то, шоб оно работало как хочет клиент.
VGn>Или (в теории) на основе готовых тестов.
Ну да. Главное тесты, а без функциональности клиент как-нибудь переживёт.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
IT>UI в это большинство задач вписывается? 30 полей на форме с более менее зависимой логикой отображения и ты состаришься раньше, чем напишешь все возможные тесты. А когда напишешь, я добавлю ещё 10 полей. Только не в конец формы, а в случайном порядке с новой особенной логикой.
Утверждалась возможность, а не простота реализации, что тоже в конечном счёте вопрос инструментов.
VGn>>Просто конструировать надо сразу с расчётом на тестирование. IT>Конструировать надо не в расчёте на тестирование, а в расчёте на то, шоб оно работало как хочет клиент.
Нет. Так говорят малограмотные ПМы.
Это требования формулировать необходимо на основе пожеланий клиента.
Тесты — на основе требований.
А код — удовлетворяющий этим тестам, а соответственно и всему остальному в обратном порядке.
Тогда мы всегда сможем трассировать пожелания-требования-тесты-код при изменении любой составляющей.
И в конечном счёте не будет обычного бардака с требованиями и реализацией.
VGn>>Или (в теории) на основе готовых тестов. IT>Ну да. Главное тесты, а без функциональности клиент как-нибудь переживёт.
Если функциональность будет присутствовать только номинально, клиенту это тоже врядли понравится
(Кстати сейчас это — основная болезнь в нашей компании. Потому что не смотря на CMMI4 адекватного процесса разработки нет. А на самом деле это не такой уж тяжкий труд. Просто каждый на своём месте вместо постоянного п****ежа и пустых совещаний должен просто правильно делать свою работу. Конечно, обладая для этого соответствующей квалификацией.).
Здравствуйте, VGn, Вы писали:
IT>>UI в это большинство задач вписывается? 30 полей на форме с более менее зависимой логикой отображения и ты состаришься раньше, чем напишешь все возможные тесты. А когда напишешь, я добавлю ещё 10 полей. Только не в конец формы, а в случайном порядке с новой особенной логикой.
VGn>Утверждалась возможность, а не простота реализации, что тоже в конечном счёте вопрос инструментов.
Это как? В принципе сделать можно, но сложность не позволяет?
VGn>>>Просто конструировать надо сразу с расчётом на тестирование. IT>>Конструировать надо не в расчёте на тестирование, а в расчёте на то, шоб оно работало как хочет клиент.
VGn>Нет. Так говорят малограмотные ПМы.
ПМы могут говорить что угодно. Но в данном случае обратное обычно утверждают юные начинающие архитекторы.
VGn>Это требования формулировать необходимо на основе пожеланий клиента. VGn>Тесты — на основе требований.
Т.е. главное у нас всегда требования. А тесты — это всего лишь побочный эффект попытки добиться приемлемой сопровождаемости системы.
VGn>А код — удовлетворяющий этим тестам, а соответственно и всему остальному в обратном порядке. VGn>Тогда мы всегда сможем трассировать пожелания-требования-тесты-код при изменении любой составляющей. VGn>И в конечном счёте не будет обычного бардака с требованиями и реализацией.
Не понял как это связано. Когда меняются требования, то меняется код, а следовательно меняются и тесты. На бардак с требованиями это никак не влияет.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.