Wiki

Clone wiki

SortingV2 / ProgramMain

Home

#Program.Main()

The Main() method in Program houses the logic we would use in actual service. However, since we want ot be able to switch traceability on and off as needed, there are several important parts that need to be pointed out.

##Initial Construction

At the beginning of Main(), we see various Admin classes being created, and details being added to these classes via dependency injection. The first class being created is the TraceAdmin, which is a decorator for the TraceController. After the TraceAdmin is constructed, we add a handful of trace modes to it, and set it start using the Count Trace mode.

TraceAdmin traceAdmin = new TraceAdmin(new TraceController());
traceAdmin.AddTraceMode(new NoTrace())
    .AddTraceMode(new XmlTrace())
    .AddTraceMode(new XmlSmallTrace())
    .AddTraceMode(new HtmlTrace())
    .AddTraceMode(new CountTrace())
    .AddTraceMode(new CountDataTrace())
    .AddTraceMode(new XmlSmallDataTrace());

traceAdmin.UpdateSetting(4); // setting count trace as default

Next, we create a DataGeneratorAdmin which decorates a DataGeneratorCollection. Afterwards, five data generators are injected.

DataGeneratorAdmin dataGeneratorAdmin = new DataGeneratorAdmin(new DataGeneratorCollection());
dataGeneratorAdmin.AddDataGenerator(new RandomDG())
    .AddDataGenerator(new Ordered())
    .AddDataGenerator(new Reverse())
    .AddDataGenerator(new Repeated())
    .AddDataGenerator(new QuickSortWorstCase());

Next, we create a DataServiceAdmin, which takes in the dataGeneratorAdmin and traceAdmin from the earlier steps. The traceAdmin is of particular note here. DataServiceAdmin needs access to it for the factories. This way, a DataServiceAdmin is able to construct DataSets using the current active factories. Anytime the factories are changed by TraceAdmin, DataServiceAdmin will automatically use them.

var database = new DataServiceAdmin(dataGeneratorAdmin, traceAdmin);

Next, we create a SorterAdmin instance. The SorterAdmin is a decorator for SortCollection which is injected. Of important note here is that we see the TraceAdmin being passed in during construction again. This is due to the fact that the SortCollection used the factories to construct sorter instances. Once again, anytime the factories are changed by TraceAdmin, SorterAdmin will automatically use them.

var sorterAdmin = new SorterAdmin(new SortCollection(traceAdmin));
sorterAdmin.AddSorter(new Simple())
    .AddSorter(new Selection())
    .AddSorter(new Insert())
    .AddSorter(new Quick())
    .AddSorter(new QuickInsert())
    .AddSorter(new Heap());

##Main Loop The main loop presents us with a menu of options to select.

###1-6 Sorting Data Each of these options select a sort type to apply to the data. Conceptually, they can be viewed as the request a client sends the service.

if (sorterAdmin.UpdateSetting(command - 1))
{
    Console.WriteLine($"Executing {sorterAdmin.SettingDescription}");
    traceAdmin.RefreshFactories();
    var data = database.GetData();
    var sort = sorterAdmin.GetSorter();
    data.PreCheckData();
    var timer = Stopwatch.StartNew();
    sort.Sort(data);
    timer.Stop();
    int outOfOrder = data.ResponseData();
    if (outOfOrder == 0)
    { Console.WriteLine("All data is in order"); }
    else
    {
        Console.WriteLine($"Error: {outOfOrder} elements out of order");
    }
    Console.WriteLine(traceAdmin.GetTraceData(sorterAdmin.SettingDescription, database.SettingDescription));
    Console.WriteLine($"Elapsed: {timer.ElapsedMilliseconds}ms");
    Console.WriteLine();
}

When the request is executed, several important steps occur. The call we want to note is this:

traceAdmin.RefreshFactories();

What is happening is that we are ensuring that the correct factories are active in traceAdmin. If and type of tracing is active, then a new tracer will be created, and be passed into a new set of trace capable factories. The purpose of this is to ensure we are starting with a blank slate to record the trace data. We don't reuse a tracer or trace factories to avoid situations where data from one request is mixed with the data of another request.

Note 1: the issue here is that the tracer and trace factories contain state information. This means each separate request needs its own factory set. Likewise, trace factories should never be shared between threads.

Note 2: Careful inspection of the NoTrace mode will show that the functional factories are always being reused. This is safe, since the functional factories have no state info in them.

For the rest of the loop, The only other spot we see traceAdmin is near the end when we extract the trace data for display in the console.

Due to the fact we injected traceAdmin into the other classes, we can write most of our code without having to explicitly use the factories. That has been abstracted away for us.

###7 Set Quick / Insert Min Segment Size This lets us change the segment size which causes QuickInsertSort to stop using QuickSort, and switch over to InsertSort. It is provided to allow experimentation with QuickInsertSort, and how it interacts with different segment sizes, and various data sets.

###8 Database Admin This option provides sub options that allow us to change the size of the data set, as well as its ordering.

###9 System Admin This option lets us control which trace mode is active. It is named System Admin since this setting would actually be controlled by System Administration system in a real service.

###0 Exit Terminates the loop.

Updated