Thursday, March 24, 2011

Best way to copy a vector to a list in STL ?

Is iterating through the vector using an iterator and copying to a list the most optimal method of copying. Any recommendations?

From stackoverflow
  • Why would you iterate and not use the standard copy algorithm?

    std::copy( vector.begin(), vector.end(), std::back_inserter( list ) );
    
    workmad3 : Should be std::copy rather than stl::copy, but otherwise this is the preferred method when using iterators to copy.
  • You can try to use trickier things from the <algorithm> header, for example for_each or copy ... but they would amount to the same thing, in my opinion.

    workmad3 : for_each will amount to the same. Copy can be overloaded to provide much more efficient copy mechanics depending on the iterators provided, and is generally the preferred mechanism.
  • If you're making a new list, you can take advantage of a constructor that takes begin and end iterators:

    std::list<SomeType> myList(v.begin(), v.end());
    

    Kasprzol's answer is perfect if you have an existing list you want to append to.

  • Also see:
    http://stackoverflow.com/questions/421573/best-way-to-extract-a-subvector-from-a-vector

  • I like this suggestion for constructing a new list.

    std::list<SomeType> myList(v.begin(), v.end());
    

    But when appending to an existing list, the following may be optimal for small data sets. By "optimal", I mean that it is easiest to remember how to do and easiest to understand. (These are subjective statements, I'm sure it depends on how your brain is wired.)

    for ( unsigned i=0; i<v.size(); i++ ) myList.push_back(v[i]);
    

    Using iterators on vectors may be overly pedantic in many cases. Simple indexing usually works fine.

    Another thread addresses iterators vs. indices (here). In that thread, the taken answer basically preferred iterators because they are more generic. But if vectors are the most commonly used container type, I think it is reasonable to specialize this kind of simple algorithm.

Lua syntax highlighting in KDevelop

Does anyone know how to fix the Lua syntax highlighting in Kdevelop. The # symbol used to get the length of a table causes the remainder of the line to appear as if it is commented out.

t[#t+1] = "foo"

From stackoverflow
  • I don't know anything about Lua so I can't give you specific code, but to fix the highlighting you'd have to edit the KatePart Lua syntax highlighting file, located at $KDEDIR/share/apps/katepart/syntax/lua.xml (on my system $KDEDIR is /usr/kde/3.5). You can find a description of the XML format at http://kate-editor.org/article/writing_a_kate_highlighting_xml_file... they're not the clearest directions but I haven't found anything else equivalent. Thankfully there are plenty of examples included with KDE.

Generate a series of random numbers that add up to N in c#

How do I generate 30 random numbers between 1-9, that all add up to 200 (or some arbitrary N), in C#?

I'm trying to generate a string of digits that can add together to be N.

From stackoverflow
  • This program will attempt to give you the answer. But because you are dealing with random numbers, there is the possibility that this will never give you the answer.

    public static IEnumerable<int> GetRandom()
    {
        var rand = new Random();
        while (true)
        {
            yield return
            rand.Next(1, 9);
        }
    }
    
    public static List<int> GetThirtyThatAddToTwoHundred()
    {
        do
        {
            var current = GetRandom().Take(30);
            if (200 == current.Sum())
            {
                return current.ToList();
            }
        } while (true);
    }
    
    Igor Zelaya : you have to check that arbitraryN is not grater than 270
    JaredPar : @Igor, the solution is for the value 200. If it were a variable solution then yes i would need to check for a constant.
    Igor Zelaya : @JaredPar, it says "or an arbitraryN".
    lc : Stop picking nits, the code is easily changeable from 200 to a different number. You can even make it a parameter. Also, you don't HAVE to check it's not greater than 270. It's just nice to do some argument checking. Either way, it'll just infinite-loop and you know something is amiss.
    lc : Oh, and don't forget, if you do argument-checking, you should also throw if arbitraryN is less than 30.
    David Schmitt : Creating a new Random() each time will kill the performance and (through reseeding) also the quality of your solution.
  • My Original Statement:

    You can only generate 29 random numbers. The 30th number will be defined by the other 29 and the sum. This is statistically important...

    I wanted to add some clarification after thinking about it and pinging the community...

    I now believe my original statement to be false. It was too lenient(which lc pointed out). You can't even generate 29 truly random numbers. As you get closer and closer to 30, the final digits aren't random the same way that rnd[1..9] is random. lc tried to mitigate this in order to come up with a solution, but I believe the solution he came up with (and Spencer) answers a very different question. That question is "Of all the sets of 30 digits between 1 and 9 that add up to 200, construct one randomly".

    What I believe to be the case is that the question as stated is unsolvable which I believe can be proved with the Pigeonhole Principle (also used by Knuth to show that certain "random" shuffles weren't really random), but I haven't done the math.

    Good talk everyone.

    Adam Peck : What if the 29 are all ones? He wanted the numbers in the range of 1-9.
    Jason Punyon : Maybe I was a bit hasty in adding my big-O statement. Either way. In a trial that matches the requirements, (30 numbers that add up to 200) he can only generate 29 numbers. The 30th number won't be random.
    lc : Not quite. Definitely on the right track though, but Adam Peck is right about the requirements. If the first 29 numbers are 1, the 30th number has to be 171, which is out of the 1-9 bounds.
    Robert Gould : @JPunyon in this case I think you should generate 30 numbers, and if they fail the test (==300) you throwaway the whole series and start over.
    lc : But that just brings us to JaredPar's algorithm. There's a possibility it'll never give you the answer.
    lc : Very good point with the question's wording. I had made an assumption with the question and provided a way to get one of those sets, because generating 30 random numbers would almost always fail to meet the criteria. And I think you're right about the Pigeonhole Principle, but it's been a while.
  • If statistical bias from true randomness is acceptable, you can add numbers up to N - [max random number], then select the last number as N - sum(selected so far).

  • Algorithm:

    1. Set total = 200 (or whatever)
    2. Generate Random number between 1-9
    3. Check if (total - newRandomNumber >= 0), if no goto 6
    4. total -= newRandomNumber
    5. Add newRandomNumber to array, goto 2.
    6. newRandomNumber = total
    7. Add newRandomNumber to array if newRandomNumber != 0
    8. End
    Simucal : This is a pretty good method I think. The only problem is, you can't control the number of digits with this method.
  • The problem is we want all numbers to be bounded 1-9 and add up to N. So we have to generate each number one by one and determine the real bounds for the next number.

    This will of course generate statistical bias toward the end of the list, so I recommend shuffling the array once after generating.

    To determine the next number's bounds, do the following: Upper bound = take the remaining sum minus (the number of elements remaining * min). Lower bound = take the remaining sum minus (the number of elements remaining * max).

    Something like (untested):

    public static List<int> RandomList(int digitMin, int digitMax, 
                                       int targetSum, int numDigits)
    {
        List<int> ret = new List<int>(numDigits);
    
        Random random = new Random();
        int localMin, localMax, nextDigit;
        int remainingSum = targetSum;
    
        for(int i=1; i<=numDigits; i++)
        {
              localMax = remainingSum - ((numDigits - i) * min);
              if(localMax > max)
                  localMax = max;
    
              localMin = remainingSum - ((length - i) * max);
              if(localMin > min)
                  localMin = min;
    
              nextDigit = random.Next(localMin, localMax);
              ret.Add(nextDigit);
              remainingSum -= nextDigit;
        }
    
        return ret;
    }
    

    The idea here is as you generate numbers, the range of possible values for the remaining numbers gets smaller, like a limit function zeroing in on a target sum. Sort of.

    Edit: I had to change the for loop to be 1-based, because we want the number of elements left AFTER generating this one.

    Edit2: Put it in a method for completeness and changed length to be numDigits for readability.

    Simucal : Yea, but how will that guarantee a number of digits?
    lc : "length" is the number of digits. It zeroes in on the target sum and generates a "length" number of "nextNumber"s
    Simucal : @lc, interesting.. nice.
    lc : Thanks. JPunyon was on the right track, saying the 30th number would be defined by the first 29. Bounding each digit to 1-9 actually says that the last N numbers are defined by the first 30-N, where N varies two-dimensionally. Also we shouldn't force 7,9* at the end, when we can have 8,8,9* instead.
    Jason Punyon : I may be missing it because its late, but how does shuffling eliminate the bias?
    lc : Because the biased numbers aren't all grouped at the tail anymore.
    Jason Punyon : So spreading out the biased numbers makes them more random? Why would we ever worry about psuedorandom number sequences if we could just shuffle them around to get truly random number sequences?
    lc : No, no. Think about how you suggested that the 30th number was defined by the first 29. It's the same idea here, except it's not 30 and 29, it's N and 30-N, where N varies as the list becomes defined. As you choose numbers, there are only certain combinations left that are guaranteed to work.
    lc : ...That being said, if you happen to choose a bunch of low numbers, you're going to HAVE to choose high ones later to reach your target sum. And vice versa. Shuffling it hides the fact that the numbers were chosen in a certain order.
    Jason Punyon : I'll think overnight and come back in the morning...I've destroyed my work Friday already by staying up this late :-)
    lc : Haha, fair enough. :-) To put it in other words, just like you were saying, your earlier choices determine what your later choices have to be. It is still random because you always sample from the largest pool of possibilities available (every number is randomly chosen until you cannot anymore).
    Simucal : We also don't need Edit updates, just title your edits when you make them.. we have wiki-version control on all questions if we are curious about edits ;). Very good answer btw
    Spencer Ruport : +1 Didn't mean to steal your thunder here. I was working on a solution and posted before I saw this.
    lc : @Simucal Yeah, thank you, and I did think about adding them or not. I decided to add the Edit updates because I thought the 1-based bit was a good note to have, and because "length" was referenced in the comments.
  • public static List<int> getNumbers(int n)
        {
            Random random = new Random(DateTime.Now.Millisecond);
            List<int> obtainedNumbers = new List<int>(); 
            do
            {
                obtainedNumbers.Add(random.Next(1, 9));
            }
            while (n - obtainedNumbers.Sum() > 0);
            return obtainedNumbers;
        }
    

    JaredPar code likes me but its slow, it's like to throw a coin and hope to get the n value.Nice pieces of codes

    Simucal : Does this get 30 random digits that add up to N? Or a random number of digits?
    lc : Looks like a random number of digits and could actually go over the sum by up to 8.
    Rulas : lol I forgot that 30 was needed...
  • This method will return 30 random numbers that add up to an arbitraryN. It is possible do, to have some 0 values. if that is not feasible, just initialize the array all to one's and if the sum is greater to the arbitraryN, set vals[nextIdx] to 1 instead of 0. Hope this helps.

        private int[] getNumbers(int arbitraryN) {
            int[] vals = new int[30];
            int nextIdx = 0;
            int nextNumber=0;
            Random r = new Random();
            if (arbitraryN > 270 || arbitraryN < 30)
                throw new Exception("Not a Valid number");
            while (vals.Sum() < arbitraryN)
            {
                nextNumber = r.Next(1, 9);
                nextIdx = r.Next(29);
                vals[nextIdx] = nextNumber;
                if (vals.Sum() > arbitraryN)
                {
                    vals[nextIdx] = 0;
                    vals[nextIdx] = 270 - vals.Sum();
                    break;
                }
            }
            return vals;
        }
    
    Jason Punyon : The only way this algorithm completes is if the last number you choose coincidentally matches the only number that completes the set (sums to 200). Doing it enough times until you match doesn't make it any more random than setting it outright.
    Igor Zelaya : you are right, I will fix it...
  • I'm not sure what the statistics are on this but, the issue here is that you don't want to randomly select a number that makes it impossible to sum N with M number of entries either by overshooting or undershooting. Here's how I would do it:

    static void Main()
    {
        int count = 30;
        int[] numbers = getNumbers(count, 155);
        for (int index = 0; index < count; index++)
        {
            Console.Write(numbers[index]);
            if ((index + 1) % 10 == 0)
                Console.WriteLine("");
            else if (index != count - 1)
                Console.Write(",");
        }
        Console.ReadKey();
    }
    static int[] getNumbers(int count, int total)
    {
        const int LOWERBOUND = 1;
        const int UPPERBOUND = 9;
    
        int[] result = new int[count];
        int currentsum = 0;
        int low, high, calc;
    
        if((UPPERBOUND * count) < total ||
            (LOWERBOUND * count) > total ||
            UPPERBOUND < LOWERBOUND)
            throw new Exception("Not possible.");
    
        Random rnd = new Random();
    
        for (int index = 0; index < count; index++)
        {
            calc = (total - currentsum) - (UPPERBOUND * (count - 1 - index));
            low = calc < LOWERBOUND ? LOWERBOUND : calc;
            calc = (total - currentsum) - (LOWERBOUND * (count - 1 - index));
            high = calc > UPPERBOUND ? UPPERBOUND : calc;
    
            result[index] = rnd.Next(low, high + 1);
    
            currentsum += result[index];
        }
    
        // The tail numbers will tend to drift higher or lower so we should shuffle to compensate somewhat.
    
        int shuffleCount = rnd.Next(count * 5, count * 10);
        while (shuffleCount-- > 0)
            swap(ref result[rnd.Next(0, count)], ref result[rnd.Next(0, count)]);
    
        return result;
    }
    public static void swap(ref int item1, ref int item2)
    {
        int temp = item1;
        item1 = item2;
        item2 = temp;
    }
    

    I didn't have a lot of time to test this so apologies if there's a flaw in my logic somewhere.

    EDIT:

    I did some testing and everything seems solid. If you want a nice pretty spread it looks like you want something along the lines of Total = Count * ((UPPER + LOWER) / 2). Although I'm fairly certain that as the difference between UPPER and LOWER increases the more flexible this becomes.

    lc : Yes, that's basically what I was getting at in my answer, and yes, you should shuffle (good idea on a shuffle algorithm btw). For reference the tail numbers may not necessarily be lower; they could be higher too. But either way, there will be a statistical bias.
    Spencer Ruport : Yeah I realized that while I was at dinner. My bad. :D Fixed.
    lc : Yup, and no worries about "thunder-stealing" here. I was just pointing out that we had the same idea. (You also had the shuffle algorithm and time to test.) And for the record, I gave you +1 a while ago. :-)
    Fatal510 : Great job... it's what i wanted.
  • There is no guarrentee that 30 random numbers from 1-9 would add up to any specific N.

    What you can find is a list of numbers which will add up to N and are bounded from 1-9 but the number will not be 30 necessarily. I believe the minimum number of numbers you need is 23, being (22*9) + 2. The maximum of course will be 200 (200*1). So the length of the list is somewhere inside [23,200]. The chances that a random list may be length 30 is thus quite low. If all list lengths are obtainable (i think they are) your chances in the long run at about 0.5%.

    lc : Right, a random list of 30 numbers 1-9 will not necessarily add up to a specific N. But if you taper the bounds as the numbers get generated, you can coerce the list to be of a certain length. Take a look at my answer.
    simonjpascoe : if you edit the bounds so you're always picking something more favourable, you're not sampling from 1-9 each time.
    lc : The point is, you CAN'T sample from 1-9 each time like you said. Otherwise you'd end up with JaredPar's algorithm, which, like you say, would end about 0.5% of the time. You have to edit the bounds to fit the requirements of the question - generate a random list that adds up to N.
    lc : ...That is, sample from 1-9 as much as you can, but as the list becomes more defined, you sample from a smaller set of numbers. Your earlier choices determine what your later choices have to be. It is still random because you always sample from the largest pool of possibilities available.
    simonjpascoe : I think that conditioning your sample based on the previous outcomes introduces a strong bias. Undershooting your goal sum value by the less than 9 and then forcing the last one will get you the closest i think.
  • I think this is the simplest way to do it, so it may lack some sophistication however it will get you there.

            String output = "";
            int sum = 0;
            int result = 200;       //enter the "end number"
    
            Random r = new Random();
    
            while (sum != result) {
                int add;
                if ((result - sum) > 10)
                {
                    add = r.Next(1, 10);
                }
                else
                {
                    add = r.Next(result - sum + 1);
                }
    
                sum += add;
                output += add.ToString() + " + ";
            }
    
            output = output.Remove(output.Length - 2);
    
            Console.WriteLine(output);
    

    Hope it helps!

  • If you want an unbiased algorithm then the naive implementation is something like:

    while (true) {
      numbers = [];
      total = 0;
      for (i = 0; i < COUNT; ++i) {
        next = rand(BOUNDS);
        total += next;
        numbers.push(next);
      }
    
      if (total == TARGET) {
        return numbers;
      }
    }
    

    This is non-terminating and slow but it is not biased. If you want a unbiased algorithm I'm not convinced the algorithms posted here are unbiased.

  • After all the discussions here, there's one other way to generate a list that doesn't introduce bias. Yes, it does differ from what the question is asking, but instead of randomly choosing digits, you can randomly increment digits until you reach the sum. Like the following (again untested):

    public static List<int> RandomListByIncrementing(int digitMin, int digitMax, 
                                                     int targetSum, int numDigits)
    {
        if(targetSum < digitMin * numDigits || targetSum > digitMax * numDigits)
            throw new ArgumentException("Impossible!", "targetSum");
    
        List<int> ret = new List<int>(Enumerable.Repeat(digitMin, numDigits));
        List<int> indexList = new List<int>(Enumerable.Range(0, numDigits-1));
    
        Random random = new Random();
        int index;
    
        for(int currentSum=numDigits * digitMin; currentSum<targetSum; currentSum++)
        {
            //choose a random digit in the list to increase by 1
            index = random.Next(0,indexList.Length-1);
    
            if(++ret[indexList[index]] == digitMax)
            {
                //if you've increased it up to the max, remove its reference
                //because you can't increase it anymore
                indexList.RemoveAt(index);
            }
        }
    
        return ret;
    }
    

    The idea here is you keep a list of references to your number list. Choose a reference at random, and increment the corresponding number. If you can't increment it anymore, remove the reference so you don't choose it next time.

    Now there's no shuffling business to be done at the end of the day, although arguably this will still produce one of the available sets of answers to the question and it's a question of which one "feels better" or is faster to run.

    pro3carp3 : This is how I would approach the problem also.
    Jason Punyon : Wow has this been fun lc! My first impression is that this might look right...but how do you know this doesn't introduce the same bias as before? Won't it produce the same solution set and distribution as the first lc-Spencer algorithm? If you've got any links I'd love to see them.
    Jason Punyon : Now that I think about it I think I might remember this algorithm from numerical recipes in C...I have to look back
    lc : Well, the problem as defined (or rather as we re-defined it) produces the same bias either way, and yes it will produce the same solution sets as the first one, but the order may be different. This one doesn't require a shuffle, so it preserves the first random order (whatever that means)...
    lc : ...This algorithm, however, should theoretically produce the exact same output distribution as the naive (JaredPar's) algorithm (preserving order). The difference being that this will always exit. But, since the shuffling algorithm itself takes a random seed, everything is relatively equivalent.
    lc : Btw, I'm curious as to what you can dig up (re: numerical recipes in C).
  • In order to have an answer not biased towards smaller numbers (or any other bias), you would ideally generate all possible sets of numbers that add up to N. After you have all the sets, randomly select one of the sets. After you've selected the winning set, you can randomly shake up the order of the numbers within that set, if needed.

  • I thought I'd try a divide and conquer approach. It seems to work pretty well. I'm sure the results aren't truly random due to the constraining elements of the algorithm, but it comes close. Essentially, I split the list in two and the target sum in half and recurse until I get lists of 3 elements or less. Then I use a brute force iteration of random digits until these smaller sums are attained. Here's the code with a sample run below it.

    using System;
    using System.Collections.Generic;
    
    namespace AddUpClient {
        class Program {
    
            static void Main() {
                AddUpWorker worker = new AddUpWorker();
                int MinDigit = 1;
                int MaxDigit = 9;
                int ItemsToSum = 30;
                int TargetSum = 150;
    
                try {
                    //Attempt to get a list of pseudo-random list of integers that add up to the target sum
                    IList<int> Results = worker.AddUp(MinDigit, MaxDigit, ItemsToSum, TargetSum);
    
                    EvaluateResults(TargetSum, Results);
                    Console.ReadLine();
                }
                catch (Exception E) {
                    Console.Out.WriteLine("Error: {0}", E.Message);
                    return;
                }
    
            }
    
            private static void EvaluateResults(int TargetSum, IList<int> Results)
            {
                Console.Out.WriteLine("Results have {0} items.", Results.Count);
    
                int Sum = 0;
                foreach (int Result in Results) {
                    Sum += Result;
                    Console.Out.WriteLine("Result: {0} Running total: {1}", Result, Sum);
                }
                Console.Out.WriteLine();
                Console.Out.WriteLine("Result = {0}", (Sum == TargetSum ? "SUCCESS" : "FAIL"));
            }
        }
    
        internal class AddUpWorker {
    
            Random RGenerator = new Random();
    
            public IList<int> AddUp(int MinDigit, int MaxDigit, int ItemsToSum, int TargetSum) {
    
                Console.Out.WriteLine("AddUp called to sum {0} items to get {1}", ItemsToSum, TargetSum);
                if (ItemsToSum > 3) {
    
                    int LeftItemsToSum = ItemsToSum/2;
                    int RightItemsToSum = ItemsToSum - LeftItemsToSum;
    
                    int LeftTargetSum = TargetSum/2;
                    int RightTargetSum = TargetSum - LeftTargetSum;
    
    
                    IList<int> LeftList = AddUp(MinDigit, MaxDigit, LeftItemsToSum, LeftTargetSum);
                    IList<int> RightList = AddUp(MinDigit, MaxDigit, RightItemsToSum, RightTargetSum);
    
                    List<int> Results = new List<int>();
                    Results.AddRange(LeftList);
                    Results.AddRange(RightList);
                    return Results;
                }
    
                // 3 or less
    
                int MinSumWeCanAchieve = ItemsToSum*MinDigit;
                int MaxSumWeCanAchieve = ItemsToSum*MaxDigit;
    
    
                if (TargetSum < MinSumWeCanAchieve)
                    throw new ApplicationException("We added up too fast");
    
                if (TargetSum > MaxSumWeCanAchieve)
                    throw new ApplicationException("We added up too slow");
    
                //Now we know we can achieve the result -- but it may not be too efficient...
    
                int[] TrialNumbers = new int[ItemsToSum];
                int MaxIteration = 100000;
                int IterationPrintInterval = 1000;
                int TrialSum;
                bool PrintIteration;
    
                for (int Iteration = 1; Iteration <= MaxIteration; ++Iteration) {
    
                    PrintIteration = ((Iteration % IterationPrintInterval) == 0);
    
                    if (PrintIteration)
                        Console.Out.WriteLine("Iteration {0} attempting to sum {1} numbers to {2}",
                            Iteration, ItemsToSum, TargetSum);
    
                    TrialSum = 0;
                    for (int j=0; j < ItemsToSum; ++j) {
                        TrialNumbers[j] = RGenerator.Next(MinDigit, MaxDigit + 1);
                        TrialSum += TrialNumbers[j];
                    }
                    if (PrintIteration)
                        ShowArray(string.Format("Iteration: {0}", Iteration), TrialNumbers);
    
                    if (TrialSum == TargetSum) {    //Yay
                        ShowArray(string.Format("Success in {0} iterations: ", Iteration), TrialNumbers);
                        return new List<int>(TrialNumbers);
                    }
                    //try again....
                }
    
                throw new ApplicationException(string.Format("Maximum of {0} trials exceeded", MaxIteration));
            }
    
            private void ShowArray(string Prefix, int[] numbers)
            {
                for (int i = 0; i < numbers.Length; ++i) {
                    if (i == 0)
                        Console.Write("{0} {1}", Prefix, numbers[i]);
                    else
                        Console.Write(", {0}", numbers[i]);
                }
                Console.WriteLine();
            }
        }
    }
    
    AddUp called to sum 30 items to get 150
    AddUp called to sum 15 items to get 75
    AddUp called to sum 7 items to get 37
    AddUp called to sum 3 items to get 18
    Success in 10 iterations:  7, 2, 9
    AddUp called to sum 4 items to get 19
    AddUp called to sum 2 items to get 9
    Success in 12 iterations:  5, 4
    AddUp called to sum 2 items to get 10
    Success in 2 iterations:  1, 9
    AddUp called to sum 8 items to get 38
    AddUp called to sum 4 items to get 19
    AddUp called to sum 2 items to get 9
    Success in 11 iterations:  4, 5
    AddUp called to sum 2 items to get 10
    Success in 6 iterations:  8, 2
    AddUp called to sum 4 items to get 19
    AddUp called to sum 2 items to get 9
    Success in 3 iterations:  8, 1
    AddUp called to sum 2 items to get 10
    Success in 1 iterations:  4, 6
    AddUp called to sum 15 items to get 75
    AddUp called to sum 7 items to get 37
    AddUp called to sum 3 items to get 18
    Success in 3 iterations:  4, 6, 8
    AddUp called to sum 4 items to get 19
    AddUp called to sum 2 items to get 9
    Success in 17 iterations:  3, 6
    AddUp called to sum 2 items to get 10
    Success in 24 iterations:  1, 9
    AddUp called to sum 8 items to get 38
    AddUp called to sum 4 items to get 19
    AddUp called to sum 2 items to get 9
    Success in 3 iterations:  2, 7
    AddUp called to sum 2 items to get 10
    Success in 3 iterations:  1, 9
    AddUp called to sum 4 items to get 19
    AddUp called to sum 2 items to get 9
    Success in 4 iterations:  5, 4
    AddUp called to sum 2 items to get 10
    Success in 2 iterations:  9, 1
    Results have 30 items.
    Result: 7 Running total: 7
    Result: 2 Running total: 9
    Result: 9 Running total: 18
    Result: 5 Running total: 23
    Result: 4 Running total: 27
    Result: 1 Running total: 28
    Result: 9 Running total: 37
    Result: 4 Running total: 41
    Result: 5 Running total: 46
    Result: 8 Running total: 54
    Result: 2 Running total: 56
    Result: 8 Running total: 64
    Result: 1 Running total: 65
    Result: 4 Running total: 69
    Result: 6 Running total: 75
    Result: 4 Running total: 79
    Result: 6 Running total: 85
    Result: 8 Running total: 93
    Result: 3 Running total: 96
    Result: 6 Running total: 102
    Result: 1 Running total: 103
    Result: 9 Running total: 112
    Result: 2 Running total: 114
    Result: 7 Running total: 121
    Result: 1 Running total: 122
    Result: 9 Running total: 131
    Result: 5 Running total: 136
    Result: 4 Running total: 140
    Result: 9 Running total: 149
    Result: 1 Running total: 150
    
    Result = SUCCESS
    
  • Backtracking?

  • So I have to ask: Is there an actual purpose for this, or is it just an exercise or homework assignment? There is a lot of work going on to prevent "bias". Is this an actual requirement, or will any fairly random solution do? Without knowing the requirements it's really easy to waste a lot of time. If this is a real problem, please explain what the actual requirements are.

Model view controller

I have a tree control in my GUI (with naturally lots of GUI/platform specific functions to handle the nodes).
I have a data model with its own complex set of nodes, children, properties etc..
I want the tree to display a representation of the model, be able to send messages to the nodes inside the model and be told to redraw itself when the model changes.

But I don't want the GUI code to need to know the details of the model's data types and I don't want to pollute the model by linking it to the GUI classes.

I can't get my head around how the controller is supposed to do this and what functions it should provide?

(this is in C++ but that shouldn't matter)

From stackoverflow
  • Qt provides a group of classes for model-view programming. You can hook a tree view to a filesystem model, for example, and neither directly know anything about each other (except a pointer to the model in the view).

  • Your requirements are:

    • Tree displays representation of model
    • Nodes in tree can send messages to nodes inside model
    • Tree redraws itself based on model changes

    I don't know exactly what kind of data you're working with here, but a hierarchical model is a fairly simple thing. I'll take it as a given you know how to iterate hierarchical data and populate a tree view.

    Your controller should have member function(s) for sending messages to the model. The parameters should be a model element and the message you want to send. This way, the UI is completely unaware of how the message gets to the element, but can get the messages through.

    The last requirement is more tricky, and depends on a few things (e.g., the lifetime of the controller, application architecture, etc.) I'm going to assume the controller lives as long as the tree view does. If that's the case, then your controller should provide a way to set a callback on model changes. Then, when the controller changes the model, it can callback to the UI without being aware of the UI.

  • You need a controller that sits outside the display widget but has the state of the tree (in MFc there are CTreeView/CTreeCtrl classes - there is a similiar separation in Qt) the tree controller handles all the data storage and calls redraws on the tree widget.
    Changes in the tree widget get sent to the tree controller - so this controller needs to know about the gui functions.

    The model will need set/get functions for all the relevant parameters for the nodes. But these can return simple types so aren't dependent on the gui.

    Updating the view form the model requires sending a message, if you don't want the model to know about your gui messaging the best you can do is register a callback function (a void pointer to a function) from the tree controller - and call this to do an update. This update function can then query the model for the changes.

  • i think your troubles start with an unfortunate choice of words. the 'control' thingies doesn't have anything to do with the 'controller' in MVC. that's why some GUI libraries use other names (widgets is a common one).

    your 'tree control' is the view, not the controller. it should be tied to the GUI, both for display, and to get GUI events and turn them into 'tree events'.

    the controller gets those 'tree events' and does the necessary modifications to the model. that's where you couple the 'action' with the 'response'.

  • GUI "controls" don't quite fit neatly into a model-view-controller pattern because they typically have their own internal model rather than accepting a reference to one. If the control is structured that way, you'll need an adapter class that "data-binds" the control's internal model to the underlying data model.

    This can accomplish something similar to what model-view-controller would, except that the adapter class plays the role both of a view hookup component (updating the GUI from the data model) and a controller (interpreting GUI events into model actions).

  • First Solution: You can implement a "Subject observer" pattern between model and view, with model as the subject and view as the observer. Whenever there is a change in the state of model, it can fire a event to all the observers those are registered, they can update themselves.

    Second Solution: Introduce a controller, which registers with model as observer. Upon receiving a event for update from Model, it can update the view. Even you can decouple view from controller using one more subject observer pattern between controller and view

    Third Solution: Use MVP pattern. Model view Presenter. This pattern used whenever there is no much computation in controller i.e., job of the controller is just to update its corresponding view. Here controller becomes Presenter.

Can I know how much of a XML document is processed by an XSL transformation?

I have rather large input XML files that must be converted to a given format with XSL. These XSL files have been hand-crafted, and we want to make sure that every non-empty text node in the original document is taken into account, i.e. either value-of'ed, copy-of'ed, or read and concatenated with something else.

Is this even possible? I.e., is it possible to know how much of an input document is "covered" by an XSL transformation?

From stackoverflow
  • You could extract all the text from the original Xml and then search if these strings are in the resulting document. This isn't any proof that really everything was converted, but you might find some obviously missing parts.

    lindelof : Yes but my problem is that some text might be converted, e.g. date fields might be converted from one locale to another.
    sth : I feared that would be the case...
  • The best I can come up with now is to add something like this to the end of your xsl:

    <xsl:template match="text()[normalize-space()]">
      To battle stations!
      This sneaky tag tried to escape: <xsl:value-of select="name(..)"/>
    </xsl:template>
    

    But it really depends on <xsl:apply-templates/> being called in all the right places and probably won't do it for non-trivial stylesheets...

    Dimitre Novatchev : Unfortunately, the described technique is useful only to capture unmatched text nodes. A text node may not be matched by any template but it still can be accessed/copied by the code of other templates. On the other side even if a text node is matched by a template it still may not be copied!
    Dimitre Novatchev : Note, I haven't downvoted you :)
  • The only way I have done this this in the past is by stepping through the XSL with a product like Altova's XMLSpy. This is very tedious for large XSL and XML documents of course but have found it necessary sometimes to find out what is going on with transformations.

  • The general answer is negative.

    Also generally impossible is the implementation of the less-ambitious idea to find all text nodes to which no template was matched during runtime. This is so, because even if matching templates are defined, they can only be selected for processing as result of an <xsl:apply-templates> with a "select" attribute that selects the specific text nodes.

    Whether or not this is done during run time is generally impossible to analyze.

    It is also not possible in general to analyze every XPath expression used in the select attribute of <xsl:value-of/> and of <xsl:copy-of>, because such an expression may contain an xsl variable and we must know the runtime contents of this variable in order to determine what nodes will be selected.

Is it possible to track every http/url redirects using .NET?

I'm doing a windows forms application and it requires me to log every url redirect that's happening on the user's machine. Like when a user googles something and he clicked on a sponsored link, there will be a number of redirects that'll happen there and i would like to track those redirects.

Is there any listener class that I can use to accomplish this?

From stackoverflow
  • I think you mean referrer, not redirect. If that's the case, in global.asax, in the application_begin method, log httpcontext.current.request.referrer.uri.

  • If you're trying to monitor any browser the user may be running, implement a pass-through HTTP proxy and monitor the requests. The browser itself will still need to be configured to go through the proxy, and this process itself is browser-dependent.

    While it is fairly straightforward, even a pass-through proxy is a nontrivial task, so you may want to base it on some third-party code such as Mentalis.org Proxy.

    See Fiddler for an example of a tool that does this for debugging purposes.

    Christian Nunciato : Nice -- I'd heard of Fiddler, but hadn't yet tried it out. Looks like it should solve the poster's question, too, since it can be incorporated into a .NET project. Thanks for the tip!
    Leon Tayson : Not using a WebBrowser control & I'm trying to monitor any browser the user may be running. I've used fiddler and it would be great if I can implement listening to http redirects from my windows forms app. Imagine this app as a service app which listens to url/http requests

Can the halting problem be solved for any non-turing languages?

The halting problem cannot be solved for turing complete languages and it can be solved trivially for some non TC languages like regexes where it always halts.

I was wondering if there are any languages where it has both the ability to halt and not halt and there is also an algorithm that can determine whether it halts.

From stackoverflow
  • The halting problem does not act on languages. Rather, it acts on machines (i.e., programs): it asks whether a given program halts on a given input.

    Perhaps you meant to ask whether it can be solved for other models of computation (like regular expressions, which you mention, but also like push-down automata).

    Halting can, in general, be detected in models with finite resources (like regular expressions or, equivalently, finite automata, which have a fixed number of states and no external storage). This is easily accomplished by enumerating all possible configurations and checking whether the machine enters the same configuration twice (indicating an infinite loop); with finite resources, we can put an upper bound on the amount of time before we must see a repeated configuration if the machine does not halt.

    Usually, models with infinite resources (unbounded TMs and PDAs, for instance), cannot be halt-checked, but it would be best to investigate the models and their open problems individually.

    (Sorry for all the Wikipedia links, but it actually is a very good resource for this kind of question.)

    FryGuy : Can't all machines be represented as the set of inputs that they accept, i.e. a language?
    A. Rex : @FryGuy: but you can't give this information to a program, because that representation is infinite.
  • The short answer is yes, and such languages can even be extremely useful.

    There was a discussion about it a few months ago on LtU: http://lambda-the-ultimate.org/node/2846

  • Yes. One important class of this kind are primitive recursive functions. This class includes all of the basic things you expect to be able to do with numbers (addition, multiplication, etc.), as well as some complex classes like @adrian has mentioned (regular expressions/finite automata, context-free grammars/pushdown automata). There do, however, exist functions that are not primitive recursive, such as the Ackermann function.

    It's actually pretty easy to understand primitive recursive functions. They're the functions that you could get in a programming language that had no true recursion (so a function f cannot call itself, whether directly or by calling another function g that then calls f, etc.) and has no while-loops, instead having bounded for-loops. A bounded for-loop is one like "for i from 1 to r" where r is a variable that has already been computed earlier in the program; also, i cannot be modified within the for-loop. The point of such a programming language is that every program halts.

    Most programs we write are actually primitive recursive (I mean, can be translated into such a language).

    obvio171 : Wait, so are regular expressions of the kind that *always halt* (as the OP says), or of the kind that may not halt, but one can always say if it does or not? Asking because of this question: http://stackoverflow.com/questions/1241215/do-all-regular-expressions-halt
    A. Rex : I don't know if I would say regular expressions actually define a model of computation. In any case, it is always possible to tell in finite time whether a given string matches a given regular expression.

ORM performance cost

Does anyone have any experience that indicates what kind of performance hit a developer could expect by choosing to use an ORM (in Django, RoR, SQLAlechemy, etc) over SQL and hand-designed databases? I imagine there are complicating issues, including whether specifying a database within the constraints of an ORM increases or decreases the chances of creating an efficient database structure (based on the developer's level of experience), and the question of how well the developer constructs either the SQL or ORM-based queries (again based on his/her experience). Any information regarding these or intrinsic performance issues would be really interesting to me.

From stackoverflow
  • My advice is not to worry about this until you need to - don't optimise prematurely. An ORM can provide many benefits to development speed, code readability and can remove a lot of code repetition. I would recommend using one if it will make your application easier to develop.

    As you progress through the development use benchmarks and profiling to determine the bottlenecks in the code and if needed you can bypass the ORM and use manual queries where they are required. Normally you will be able to improve the speed of the ORM using caching and database indexes (amongst other things) and then you can decide where manual queries are required. For the most part, the ORM performance will probably acceptable and the benefits of using it will far outweigh the performance cost.

    Arthur Thomas : yep, I agree with this. The ORM may do something things nicely that you might not optimize with manual SQL without tweaking anyway.
  • This will depend a lot on the what you compare it with. The the coder writing the hand code is a total hack it might be a boon rather than a hit. Clearly it can go the other way as well.

  • It also depends on what you're using as an ORM. In my experience, Hibernate is a pig, in terms of speed, resource usage and startup time. LINQ to SQL, on the other hand, is an extremely light SQL wrapper, whose impact you'd likely barely (if at all) notice.

  • Performance has always been an after thought in most DAL Layer development / architecture. I think its about time we start questioning the performance of these ORM tools, for the so-called ease of development they promise:

    The 2 biggest areas of performance issues in ORMs are:

    1. Inability to write Optimum SQL. You have to use an Object Query Language which is interpreted into SQL by the framework. Mostly it is good SQL, but often enough it is not the most efficient SQL.

    2. Reflection. Most ORM frameworks use Reflection to populate objects with Data from the database. Reflection operations are costly, and with increasing number of load and data, the performance degradation becomes obvious.

    Other performance issues that arise are because of inefficient Database Design or Entity Model design due to the tight coupling of Entity objects to Tables.

  • See ORMBattle.NET - its peformance tests are designed exactly for this purpose. There is "SqlClient" column showing peak possible performance of same operations executed directly.

    jmans : This is great--maybe someone will contribute some non-.NET ORMs.
    Alex Yakunin : This would be really great...

WBR Alternative in XHTML

I've been using tags in the thead cells for my tables, so I can control where browsers break long words. This works great, but its not XHTML compliant. What is the best alternative to using the wbr tag, that is valid XHTML? Example:

<table>
  <thead>
    <tr><th>ThisIsAReally<wbr />LongWord<th></tr>
  </thead>
  <tbody>
    <tr><td>...</td></tr>
    <tr><td>...</td></tr>
    <tr><td>...</td></tr>
  </tbody>
</table>
From stackoverflow

Maven Embedded Jetty Container fails to load Taglibs: Unable to initialize TldLocationsCache

Hi all,

I'm using the Maven Cargo Plugin to startup a Jetty web container for running some integration tests in a separate project module.

The problem i'm battling with occurs when i added taglibs into the jsp pages and tried hitting them from the integration tests. When jetty tries to compile the pages it fails with this error:

org.apache.jasper.JasperException: Unable to initialize TldLocationsCache: null

The web app works fine when run in an installed Tomcat container or standalone Jetty run through maven on the command line, so i think the problem must be down to something to do with how cargo embeds jetty and then how jetty compiles the app.

I've tried running in forked and unforked modes, adding the taglibs to the container classpath, explicitly defining taglibs in web.xml and having no config there...all to no avail.

Here's the test project i'm using to debug:

web.xml

<?xml version='1.0' encoding='UTF-8'?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<display-name>taglibs-test</display-name>

<jsp-config>
 <taglib>
  <taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
  <taglib-location>/WEB-INF/tld/c.tld</taglib-location>
 </taglib>
</jsp-config>

And the test module pom.xml:

<?xml version="1.0" encoding="UTF-8"?>

http://maven.apache.org/maven-v4_0_0.xsd">

...

<build>

  <!-- Integration Test Embedded Servlet Container -->
  <plugin>
   <groupId>org.codehaus.cargo</groupId>
   <artifactId>cargo-maven2-plugin</artifactId>
   <configuration>
    <wait>false</wait>
    <container>
     <containerId>jetty6x</containerId>
     <type>embedded</type>
     <log>${project.build.directory}/log</log>
     <dependencies>
      <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>jstl</artifactId>
      </dependency>
      <dependency>
       <groupId>taglibs</groupId>
       <artifactId>standard</artifactId>
      </dependency>
     </dependencies>
     <systemProperties>
      <DEBUG>true</DEBUG>
     </systemProperties>
    </container>
    <configuration>
     <properties>
      <cargo.servlet.port>8090</cargo.servlet.port>
      <cargo.logging>high</cargo.logging>
     </properties>
     <deployables>
      <deployable>
       <groupId>test</groupId>
       <artifactId>web</artifactId>
       <type>war</type>
       <properties>
        <context>taglibs-test</context>
       </properties>
      </deployable>
     </deployables>
    </configuration>
   </configuration>
   <executions>
    <execution>
     <id>start-container</id>
     <phase>test-compile</phase>
     <goals>
      <goal>start</goal>
     </goals>
    </execution>
    <execution>
     <id>stop-container</id>
     <phase>package</phase>
     <goals>
      <goal>stop</goal>
     </goals>
    </execution>
   </executions>
  </plugin>
 </plugins>
</build>

Here's the stacktrace from the error:

    2009-01-24 13:53:06.766::WARN:  /taglibs-test/index.jsp: 
org.apache.jasper.JasperException: Unable to initialize TldLocationsCache: null
    at org.apache.jasper.compiler.TldLocationsCache.init(TldLocationsCache.java:253)
    at org.apache.jasper.compiler.TldLocationsCache.getLocation(TldLocationsCache.java:224)
    at org.apache.jasper.JspCompilationContext.getTldLocation(JspCompilationContext.java:526)
    at org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:422)
    at org.apache.jasper.compiler.Parser.parseDirective(Parser.java:492)
    at org.apache.jasper.compiler.Parser.parseElements(Parser.java:1552)
    at org.apache.jasper.compiler.Parser.parse(Parser.java:126)
    at org.apache.jasper.compiler.ParserController.doParse(ParserController.java:211)
    at org.apache.jasper.compiler.ParserController.parse(ParserController.java:100)
    at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:155)
    at org.apache.jasper.compiler.Compiler.compile(Compiler.java:295)
    at org.apache.jasper.compiler.Compiler.compile(Compiler.java:276)
    at org.apache.jasper.compiler.Compiler.compile(Compiler.java:264)
    at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:563)

I've tracked this down to the following lines in jasper's TldLocationsCache:

   private void init() throws JasperException {
        if (initialized) return;
        try {
            processWebDotXml();
            scanJars();
            processTldsInFileSystem("/WEB-INF/");
            initialized = true;
        } catch (Exception ex) {
            throw new JasperException(Localizer.getMessage(
                    "jsp.error.internal.tldinit", ex.getMessage()));
        }
    }

http://svn.apache.org/repos/asf/tomcat/jasper/tc6.0.x/src/share/org/apache/jasper/compiler/TldLocationsCache.java

Any help is greatly appreciated!!

cam

From stackoverflow

How Can I Write Zend Framework URLs That Have Anchor Tags In The Body?

Using the standard MVC set up in Zend Framework, I want to be able to display pages that have anchors throughout. Right now I'm just adding a meaningless parameter with the '#anchor' that I want inside the .phtml file.

<?= $this->url(array(
    'controller'=>'my.controller',
    'action'=>'my.action',
    'anchor'=>'#myanchor'
));

This sets the URL to look like /my.controller/my.action/anchor/#myanchor

Is there a better way to accomplish this? After navigation to the anchor link, the extra item parameter gets set in the user's URL which is something I would rather not happen.

From stackoverflow
  • Hi, one of possibilities is to override url helper, or to create a new one.

    class My_View_Helper_Url extends Zend_View_Helper_Url
    {    
        public function url(array $urlOptions = array(), $name = null, $reset = false, $encode = true)
        {
         if (isset($urlOptions['anchor']) && !empty($urlOptions['anchor']))
         {
          $anchor = $urlOptions['anchor'];
          unset($urlOptions['anchor']);
         }
         else
         {
          $anchor = '';
         }
    
            return parent::url($urlOptions, $name, $reset, $encode).$anchor;
        }
    }
    

    this helper override url helper, problem is, that you can't use parameter called 'anchor', because it will be changed into anchor in url.

    you will call it as in your's example

    <?= $this->url(array(
        'controller'=>'my.controller',
        'action'=>'my.action',
        'anchor'=>'#myanchor'
    ));
    

    I hope it helps

  • There are multiple ways you could go about implementing a fragment id into your URLs. Below are some options, along with some pros and cons for each.

    Direct Add

    You could simply add the "#$fragment_id" after your url() call. Inelegant, but simple. If you don't use page anchors much (i.e. One or two pages only), this is the way to go.

    Write a custom url() helper

    You could write a custom version of url() appending an optional 5th argument for the fragment id:

    class My_View_Helper_Url extends Zend_View_Helper_Url
    {    
        public function url(array $urlOptions  = array(), $name   = null, 
                                  $reset       = false,   $encode = true, 
                                  $fragment_id = null)
        {
            $uri = parent::url($urlOptions, $name, $reset, $encode);
    
            if(!is_null($fragment_id)) {
                $uri .= "#$fragment_id";
            }
    
            return $uri;
        }
    }
    

    This way, anchor (and anchor/fragment id) information is kept strictly withing the realm of the View. This is good for general use, but can get a little unwieldy for the default route. Also, this is still a little too hard-coded for some uses.

    Write a custom Route class (Extreme)

    As a third option, you could write a custom version of the Zend_Controller_Router_Route class(es), specifically the assemble($data, $reset, $encode) method (the match($path) method ignores fragment ids by default).

    Using this method can be quite tricky, but very useful, especially if use is only limited to specific routes (this method can be used to base the fragment id off of any variable).

    Caveat

    Certain considerations must be taken into account when using fragment ids. For example, query strings have to precede the fragment id in the uri, otherwise, the query string ignored by PHP. However, most ZF applications tend to avoid use of query strings, so it may not be an issue.

  • I think the Extreme method of writing a custom route class is better because other helper will have the same behavior (like the redirector action helper).

How to resolve specific circular dependency: DAL & Logging

Some "high risk" data operations need to be logged. In this case, the "high risk" operations are defined as writes to our ERP system. It happens that we are logging those events to our SQL Server database.

Pseudo-code:

Public Class MyCompany.DAL.ERP {
  Public void WriteToERP(string msg) {
    // ... do the write
    MyCompany.Logging.Write("Wrote msg: " + msg);
  }
}

Public Class MyCompany.Logging {
  Public void Write(string msg) {
    MyCompany.DAL.ExecuteSQL("Insert INTO EventLog VALUES " + msg);
  }
}

What is the best practice to eliminate this tight coupling?

From stackoverflow
  • Maybe you could have your logging component, moved to a seperate assembly (I'm assuming this is C# code), raise an event, that the caller could register for before calling Logging.Write(). After Logging.Write() returns, unregister from the event. In the event handler you could execute your MyCompany.DAL.ExecuteSQL("Insert INTO EventLog VALUES " + msg) call.

  • Hmm, IMHO logging is an infrastructure concern. You can use it in your DAL, but your logger should not use your DAL.

    If you remove the dependency your logger has on your DAL, then you should be able to use your logger in other projects as well.

  • You can create a custom TraceListener (System.Diagnostics) to insert into your company's SQL Server database. Then use Trace / TraceSource (System.Diagnostics) for your logging in your application's code. You can then use standard .NET configuration to use your custom TraceListener at design time. That way, if you ever need to change your event logging, you just have to change the TraceListener. Plus you could reuse the TraceListener in other applications.

    You could also use the Logging Application Block of the Enterprise Library and many other 3rd party logging solutions.

    Adrian K : +1 - As the EntLibs are heavily driven by config you can have a consistent logging sub-system in place which is cleanly seperated from your application (in areas such as DAL); you can log stuff to a n application db or somewhere else - it's all loosely coupled.
  • I've decoupled this situation before in two ways: Status changes and Log events.

    First way is to create an IHaveStatus interface like such:

    /// <summary>
    /// Interface for objects that have a status message 
    /// that describes their current state.
    /// </summary>
    public interface IHaveStatus
    {
        /// <summary>
        /// Occurs when the <seealso cref="Status"/> property has changed.
        /// </summary>
        event EventHandler<StatusChangedEventArgs> StatusChanged;
        /// <summary>
        /// The current status of the object.  When this changes, 
        /// <seealso cref="StatusChanged"/> fires.
        /// </summary>
        string Status { get; }
    }
    

    As your object does stuff, you set your Status property. You can configure your property setter to fire the StatusChanged event when you set it. Whoever uses your objects can listen to your status changed event and log everything that happens.

    Another version of this is to add a Log events to your objects.

    public event EventHandler<LogEventArgs> Log;
    

    The principal is pretty much the same, only your objects would be less chatty than a Status-driven log (you only fire the event when you specifically want to log something).

    The idea is that its the responsibility of callers outside of your DAL to hook these events up to the proper log (hopefully set by using DI). Your DAL is oblivious to who or what is consuming these events, which separates these concerns well.

  • The common thread among the responses seems to be the suggestion to implement something like the observer pattern.

    (Let me know if there's a better summary statement. I'll update accordingly.)

  • Actually, if by high-risk data you mean criticial/important to know it is how it is supposed to be data, and also if you need to have the logs in the database (some kind of meta-data), then the solution should be completely different as what others have suggested.

    The situation I described would mean that the result of a database transaction should have both the logging data and the data itself in the database at any given time. One should not be done independently from the other.

    As a result, this kind of "logging" should be done as part a single database transaction and the DAL should make sure that both items are inserted correctly at the same time in the same transaction.

    Failure to do so could have the following side effect:

    • Having only one of the data or log inserted in the db.
    • Having only one of the data or log inserted in the db before the other, meaning that a system relying on the fact that both must be present at any given time might randomly fail in specific circumstances.
    Larsenal : It's not so much metadata. We're dealing with writes to a slow, error-prone system. The logging is done to the fast, reliable database as a sort of fallback to identify and recover from problems with the "bad" database. This whole issue stems from the fact that one database is relatively unreliable.
    Loki : Ok then I will keep my answer for the info you added, but it shall not apply to your situation.
  • To avoid the circular dependency DAL -> Logger -> DAL, I'd propose you have two layers of DAL: "simple DAL", and "logging DAL".

    The "simple DAL" ist just a DAL. The "logging DAL" builds on the "simple DAL"; it manipulates the DB using the simple DAL, and also logs stuff, again using the simple DAL. So you have:

    [application logic] --uses--> [logging DAL] --uses--> [simple DAL] --uses--> DB

    If you want to do stuff to the DB that does not need to be logged ("low risk" operations ;-)) you could use "simple DAL" directly and bypass the logging DAL.