Skip to content

Clean up Confirm abstraction #19

@jzabroski

Description

@jzabroski
  1. Func value = null, but null is really a marker value to be coerced to true. This signature should be re-written using an Option type aka Nullable for reference types. Not quite the same thing semantically as Maybe, because we are trying to explicitly capture the fact we can handle a None case for the user.
  2. The whole idea of requireConfirm is kind of messy. The documentation says "Writes out buffered entries in a log activity that was entered with requireConfirm set to true." So I have a couple of observations here. First, why should calling this method depend on a flag set at the Log.Enter level? This is sort of like what some researchers call Type State - the methods that are allowed to be called depend on the state of the type instance. We can mimic Type State in .NET by essentially making the Log class parametric - Log where T is a LogType. This may also result in better JIT code, since the overload doesn't exist and the final could would generate two separate IL execution blocks for each generic type.
  3. The idea of buffering entries needs to be more carefully thought through - I think it could result in deadlocks or at least dirty reads. Perhaps a Confirm and ConfirmWrite abstraction.
  4. I can see you are recording elapsed time at each Confirm checkpoint, but how do I output that elapsed time? This would be really helpful for our Performance Engineers to read our logs. More of a question, which may lead to more clean up :)
  5. [Edit: Digging deeper, I see that private void StartTiming() is what actually controls the stop watch. (I am not sure why this is necessary?)]

    I think you are probably already on this thought pattern already - I see the comment "// TODO: (LogActivity) generalize extensions that are triggered on boundary enter" which suggests each extension basically has an AOP cut-point that you can weave "advice" extensions into.

    This final list falls under "dealing with multiple Confirmed entries and flushing multiple entries in thread-safe ways".

    1. Perhaps not the best place to ask this, but why does Complete() null out the entry.Message if the LogActivity falls out of scope (e.g., using statement)? I don't think entry should be stateful like this.
    2. I don't see what the variable "confirmed" is for - it seems to be set but never used. It doesn't (Seem to) make sense in the presence of multiple confirm entries.
    3. Similarly, I don't see why you set requireConfirmed = false before the buffer is emptied. Isn't it possible for the buffer to add messages if the LogActivity is accessed from multiple threads?
    4. The ConfirmationList is hard-coded to stop at 100 - see Formatter.ListExpansionLimit = 100; - so this essentially means I can have at most 100 calls to Confirm actually logged. A simple test for this would be to use Its.Log and take each of the C# examples from http://www.99-bottles-of-beer.net/ and change the value to > 100 for # of beer bottles. This would also test Its.Log's output is correct across many different C# language features. You would simply find/replace Console.WriteLine(s) with Log.Write(() => s)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions