Open baseTwo opened 2 months ago
Is the real problem here that the class is hard to use because we don't have the proper public interface established for it yet?
Before we go creating a lot of extra services that will only have one implementation made by us, and are unlikely to be implemented by consumers directly to establish non-default behavior, we should review how SDK users are expected to interact with this class to accomplish a goal.
The basic use case of this SDK is to go from CQL text to outputting either source code or producing an assembly, and ideally, an interface into that assembly. They want to be able to do something like this:
var cql = File.ReadAllText("mylib.cql");
var measure = cql.Compile();
var patientBundle = ....
var result = measure.Numerator(bundle);
That would be the most intuitive way to use our code. Alternatively, something like this could work:
var cql = File.ReadAllText("mylib.cql");
var bundle = ...
var result = Cql.RunMeasure(cql, bundle, "Numerator");
We have the machinery in place in the current design to write the public interfaces that do these things.
FWIW, I think if we do anything to the AssemblyCompiler, we should revert all the unnecessary abstractions. The 1.0 version did not have CSharpCodeStreamPostProcessor
or AssemblyDataPostProcessor
and is being used successfully in production. There are simpler ways to provide extension points for "I want to execute some code on a stream at some point" (e.g. events) that do not require extra classes.
The AssemblyCompiler has multiple responsibilities which violates SOLID principles. They are:
CSharpLibrarySetToStreamsWriter.ProcessDefinitions(...)
to process each library in aLibrarySet
using theDefinitionDictionary<LambdaExpression>
output from the expression builder, to generate C# code into an in-memory streamCSharpCodeStreamPostProcessor.ProcessStream(...)
on the generated C# code in-memory streamAssemblyDataPostProcessor.ProcessReferenceAssembly(...)
for each referenced assemblyAssemblyDataPostProcessor.ProcessAssemblyData(...)
on each generated in-memory .NET assemblyHere is a diagram of all the actors in the process
This needs to be refactored into multiple services:
LibrarySet
on theDefinitionDictionary<LambdaExpression>
output from the expression builder, an returns an enumerable ofStream
. A factory method must be provided for the streams by the caller.