Blog Archive

Home
Filter by: Open Source

Compilers are what make the software world function.  Really, where would we be without ‘em?  But compilers are like clans – you stick with the family.  Just like Romeo and Juliet, you can’t marry your enemies sister’s cousin, it just ends up in tragedy.  For the longest time, the .Net and C# world has been considered an “enterprise” thing, and by that we do not mean Captain Kirk and Spock:  .Net is for corporations, not the web.  It’s not Nodejs.  It’s slow.  It’s for the nerds who ain’t the cool nerds.  So take your compiler and stay on your side of the street.

Well, these days technology is a lot like the Berlin wall coming down, and like the union of the eastern and western European countries, the lines are blurred with static compiled languages of C# and Javascript.  You see, these days you compile C# code to Javascript.  In fact, a dirty secret is that you could do that for many years now.

DuoCode Is The New Kid On The Block

A new entry in this field is DuoCode.  From the site:

“DuoCode is an alternative compiler, powered by Microsoft® Roslyn, and integrated in Visual Studio.

It magically cross-compiles your C# 6.0 code into high-quality readable JavaScript code, enabling rapid development of web applications utilizing the extensive features of the C# language, the Visual Studio IDE, and the .NET Framework base class libraries.

Development in C# with Visual Studio brings great productivity wins, thanks to strong-typing, code completion, compile-time error checking, static analysis, code navigation and refactoring.

Develop HTML5 applications using strongly-typed and documented class-definitions of the entire DOM class library (including HTML, CSS, SVG and WebGL definitions).”

DuoCode works with Visual Studio and will compile assemblies from multiple projects to Javascript.  DuoCode claims to support LINQ, classes, Generics, lambda expressions, extension methods, and many features that are the strengths of C#.

The Question:  Should All C# Capabilities Be Ported To Javascript?

Does Javascript need type checking and casting?  Yes, no need to check that a int is not a string, but tying yourself to a compiler for Javascript is going to introduce a different type of workflow for your client side development.  Part of the refreshing aspects of Javscript is not having to compile constanctly.  ”You have to ‘build’ your website, hehe …” meant you have to sit and wait for Visual Studio to compile and deploy before you could debug.  One of the main reasons for adpating MVC and leaving ASP.Net Webforms behind was to get away from the stilted, awkward development process when you wanted to examine an issue with your app’s UX.  Compiling your Javascripts feels a bit like a step backwards.

That said, LINQ and lambda expressions are a really good thing.  They’re like power tools for your boilerplate code. Javascript, while having tools like underscoreJS and lodash, is still an open field in this respect.  That’s not to say that there are no alternatives and efforts to build those type of capabilities; indeed, there are hundreds of open source projects and other efforts to create better functionality, and with EM6 on the horizon things like iterators will become part of the new Javascript specification.

Quite Hemming and Hawing – Why Would I Need This?

Ok, under what circumstances will you need this capability, and more importantly, is the generated Javascript any good?  In response to the former query, you may have a series of objects that are tested, run on your server, and you want those to

also run in your UX.  Maybe you have a state machine and a process that you want to run on a mobile device and instead of transpiling it to Mono or Swift you want to go the HTML 5 route.  Or, perhaps you want to port a portion of your code base to nodeJS for message brokering.  This could help tremendously.

Yet lurking in the background here is this:  what does the ported Javascript look like, and if there are issues where do you go to fix them?  Are they a Javascript issue, or are the origins from C#, compounded by the code compiling to Javascript?

So what do you think?  

This post focuses on getting started with RavenDB, so we’ll set aside our focus on workflows for a bit.  It’s included in the ApprovaFlow series as it is an important part of the workflow framework we’re building.  To follow along you might want to get the source code.

RavenDB is a document database that provides a flexible means for storing object graphs.  As you’ll see a document database presents you with a different set of challenges than you are normally presented when using a traditional relational database.

The storage “unit” in RavenDB is a schema-less JSON document.  This takes the form of:  Because you are working with documents you now have the flexibility to define documents differently; that is, you can support variations to your data without have to re-craft your data model each time you want to add a new property to a class.  You can adopt a “star” pattern for SQL as depicted here, but querying can become difficult.  Raven excels in this situation and one such sweet spot is:

Dynamic Entities, such as user-customizable entities, entities with a large number of optional fields, etc. – Raven’s schema free nature means that you don’t have to fight a relational model to implement it.

Installing and Running RavenDB

The compiled binaries are easy to install.  Download the latest build and extract the files to a share.  Note that in order to run the console you are required to install Silverlight.  To start the server, navigate to the folder[] and double click “Start.cmd”.  You will see a screen similar to this one once the server is up and running:

The console will launch it self and will resemble this:

How To Start Developing

In Visual Studio, reference Raven with Raven.Client.Lightweight.  For CRUD operations and querying this will be all that you will need.

First you will need to connect to the document store.  It is recommended that you do this once per application.  That is accomplished with


var documentStore = new DocumentStore {Url = "http://localhost:8080"};
documentStore.Initialize();

Procedures are carried out using the Unit of Work pattern, and in general you will be using these type of blocks:


using(var session = documentStore.OpenSession())
{
   //... Do some work
}

RavenDB will work with Plain Old C# Objects and only requires an Id property of type string.  An identity key is generated for Id during this session.  If were were to create multiple steps we would have identities created in succession.  A full discussion of the alternatives to the Id property is here.

Creating a document from your POCOs’ object graphs is very straight forward:


public class Person
{
    public string FirstName { get; set; }
	public string LastName { get; set; }
	public string Id { get; set; }
	public int DepartmentId { get; set; }
    // ...
}

var person = new Person();

using(var session = documentStore.OpenSession())
{
   session.Store(person);
   session.SaveChanges();
}

Fetching a document can be accomplished in two manners:  by Id or with a LINQ query.  Here’s how to get a document by id:


string person = "Person/1";  //  Raven will have auto-generated a value for us.
using(var session = documentStore.OpenSession())
{
   var fetchedPerson = session.Load<Person>(personId);
   //Do some more work
}

You’ll note that there is no casting or conversion required as Raven will determine the object type and populate the properties for you.

There are naturally cases where you want to query for documents based on attributes other than the Id. Best practices guides that we should create static indexes on our documents as these will offer the best performance. RavenDB also has a dynamic index feature that learns from queries fired at the server and over time these dynamic indexes are memorialized.

For your first bout with RavenDB you can simply query the documents with LINQ.   The test code takes advantage of the dynamic feature.  Later you will want to create indexes based on how you most likely will retrieve the documents.  This is different that a traditional RDMS solution, where the data is optimized for querying.  A document database is NOT.

Continuing with our example of Person documents we would use:


int departmentId = 139;

using(var session = documentStore.OpenSession())
{
   var people = session.Query<Person>()
                          .Where(x => x.DepartmentId == departmentId)
                          .ToList();
}

In the source code for this post there are more examples of querying.

Debugging, Troubleshooting and Dealing with Frustration

Given that this is something new and an open source project you may find yourself searching for help and more guidelines.  One thing to avail yourself of while troubleshooting is the fact that RavenDB has REST interface and you can validate your assumptions – or worse, confirm your errors – by using curl from the command line.  For example, to create a document via http you issue:

curl -X POST http://localhost:8080/docs -d "{ FirstName: 'Bob', LastName: 'Smith', Address: '5 Elm St' }"

Each action that takes place on the RavenDB server is displayed in a log on the server console app.  Sensei had to resort to this technique when troubleshooting some issues when he first started.  This StackOverflow question details the travails.

Another area that threw Sensei for a loop at first was the nature of the RavenDB writing and maintaining indexes.  In short, indexing is a background process, and Raven is designed to be “eventually consistent”.  That means that there can be a latency between when a change is submitted, saved, and indexed in the repository so that it can be fetched via queries.  When running tests from NUnit this code did not operate as expected, yet the console reported that the document was created:


session.Store(teamMember);

int posttestCount = session.Query<TeamMember>()
                .Count();

According to the documentation you can overcome this inconsistency by declaring that you are willing to wait until RavenDB has completed its current write operation.   This code will get you the expected results:


int posttestCount = session.Query<TeamMember>()
              .Customize(x => x.WaitForNonStaleResults())
              .Count();

Depending on the number of tests you write you may wish to run RavenDB in Embedded mode for faster results.  This might prove useful for automated testing and builds.  The source code provided in this post does NOT use embedded mode; rather, you have need your server running as this gives you the opportunity to inspect documents and acclimate yourself to the database.

There is much more that you can do with RavenDB, such as creating indexes across documents, assign security to individual documents, and much more.  This primer should be enough to get you started.  Next post we’ll see how RavenDB will fit into the ApprovaFlow framework.  Grab the source, play around and get ready for the next exciting episode.

 

This is the fourth in a series of posts for ApprovaFlow, an alternative to Windows Workflow written in C# and JSON.Net.  Source code for this post is here.

[gigya src="http://listen.grooveshark.com/songWidget.swf" width="250" height="40" flashvars="hostname=cowbell.grooveshark.com&songID=1211234&style=metal&p=0" wmode="window"]

Last Time on ApprovaFlow

In the previous post we discussed how the Pipe and Filter pattern facilitated a robust mechanism for executing tasks prior and after a transition is completed by the workflow state machine.  This accomplished our third goal and to date we have completed:

Model a workflow in a clear format that is readable by both developer and business user. One set of verbiage for all parties.  Discussed in Simple Workflows With ApprovaFlow and Stateless.

•  Allow the state of a workflow to be peristed as an integer, string, etc.  Quickly fetch state of a workflow.  Discussed in Simple Workflows With ApprovaFlow and Stateless.

•  Create pre and post processing methods that can enforce enforce rules or carry out actions when completing a workflow task.  Discussed in ApprovaFlow:  Using the Pipe and Filter Pattern to Build a Workflow Processor

These goals remain:

• Introduce new functionality while isolating the impact of the new changes. New components should not break old ones

• Communicate to the client with a standard set of objects. In other words, your solution domain will not change how the user interface will gather data from the user.

• Use one. aspx page to processes user input for any type of workflow.

• Provide ability to roll your own customizations to the front end or backend of your application.

It’s the Small Changes After You Go Live That Upset You

The goal we’ll focus on next is Introduce new functionality while isolating the impact of the new changes. New components should not break old ones, as it’s the small upsetters that lurk around the corner that your users will think up that will keep you in the constant redeployment cycle. If we implement a plug-in system, then we can prevent the new features from breaking the current production system. Implementing these changes in isolation will lead to faster testing, validation and happier users.

We lucked out as our implementation of the Pipe And Filter pattern forced us to create objects with finite functionality.  If you recall each step in our workflow chain was implemented as a filter derived from FilterBase and this lends itself nicely to creating plug-ins.  The Pipe and Filter pattern forces us to have a filter for each unique action we wish to carry out.  To save data we have a SaveData filter, to validate that a user can supply a Trigger we have the ValidateUserTrigger, and so on.

“Great, Sensei, but aren’t we still constrained by the fact that we have to recompile and deploy any time we add new filters?  And, if I have to do that, why bother with the pattern in the first place?”

Well, we can easily reduce the need for re-deploying the application through the use of a plugin system where we read assemblies from a share and interrogate them by searching for a particular object type on application start up.  Each new feature will be a new filter.  This means you will be working with a small project that references ApprovaFlow to create new filters without disturbing the existing architecture.   We’ll also create a manifest of approved plug-ins so that we can control what is used and institute a little security since we wouldn’t want any plugin to be introduced surreptitiously.

Plug-in Implementation

The class FilterRegistry will perform the process of reading a share, fetching the object with type FilterBase, and register these components just like we do with our system components.  There are a few additions since the last version, as we now need to read and store the manifest for later comparison with the plug-ins.  The new method ReadManifest takes care of this new task:

<pre><code>private void ReadManifest()
{
string manifestSource = ConfigurationManager.AppSettings["ManifestSource"].ToString();

Enforce.That(string.IsNullOrEmpty(manifestSource) == false,
“FilterRegistry.ReadManifest – ManifestSource can not be null”);

var fileInfo = new FileInfo(manifestSource);

if (fileInfo.Exists == false)
{
throw new ApplicationException(“RequestPromotion.Configure – File not found”);
}

StreamReader sr = fileInfo.OpenText();
string json = sr.ReadToEnd();
sr.Close();

this.approvedFilters = JsonConvert.DeserializeObject>>(json);
}

</code></pre>

The manifest is merely a serialized list of FilterDefinitions. This is de-serialized into a list of approved filters.With the approved list the method LoadPlugin performs the action of reading the share and matching the FullName of the object type between the manifest entries and the methods in the assembly file:

<pre><code>

public void LoadPlugIn(string source)
{
Enforce.That(string.IsNullOrEmpty(source) == false,
“PlugInLoader.Load – source can not be null”);

AppDomain appDomain = AppDomain.CurrentDomain;
var assembly = Assembly.LoadFrom(source);

var types = assembly.GetTypes().ToList();

types.ForEach(type =>
{
var registerFilterDef = new FilterDefinition();

// Is type from assembly registered?
registerFilterDef = this.approvedFilters.Where(app => app.TypeFullName == type.FullName)
.SingleOrDefault();

if (registerFilterDef != null)
{
object obj = Activator.CreateInstance(type);
var filterDef = new FilterDefinition();
filterDef.Name = obj.ToString();
filterDef.FilterCategory = registerFilterDef.FilterCategory;
filterDef.FilterType = type;
filterDef.TypeFullName = type.FullName;
filterDef.Filter = AddCreateFilter(filterDef);

this.systemFilters.Add(filterDef);
}
});
}

</code></pre>

That’s it. We can now control what assemblies are included in our plug-in system.  Later we’ll create a tool that will help us create the manifest so we do not have to managed it by hand.

What We Can Do with this New Functionality

Let’s turn to our sample workflow to see what possibilities we can develop.  The test CanPromoteRedShirtOffLandingParty from the class WorkflowScenarios displays the capability of our workflow.  First lets review our workflow scenario.  We have created a workflow for the Starship Enterprise to allow members of a landing party to request to be left out of the mission.  Basically there is only one way to get out of landing party duty and that is if Kirk says it’s okay.  Here are the workflow’s State, Trigger and Target State combinations:

State Trigger Target State
RequestPromotionForm Complete FirstOfficerReview
FirstOfficerReview RequestInfo RequestPromotionForm
FirstOfficerReview Deny PromotionDenied
FirstOfficerReview Approve CaptainApproval
CaptainApproval OfficerJustify FirstOfficerReview
CaptainApproval Deny PromotionDenied
CaptainApproval Approve PromotedOffLandingParty

Recalling the plots from Star Trek, there were times that the medical officer could declare the commanding officer unfit for duty. Since the Enterprise was originally equipped with our workflow, we want to make just a small addition – not a modification – and give McCoy the ability to allow a red shirt to opt out of the landing party duty.

Here’s where our plugin system comes in handy.  Instead of adding more states and or branches to our workflow we’ll check for certain conditions when Kirk makes his decisions, and execute actions.  In order to help out McCoy the following filter is created in a separate project:

<pre><code>

public class CaptainUnfitForCommandFilter : FilterBase
{
protected override Step Process(Step input)
{
if(input.CanProcess & input.State == “CaptainApproval”)
{
bool kirkInfected = (bool)input.Parameters["KirkInfected"];

if(kirkInfected & input.Answer == “Deny”)
{
input.Parameters.Add(“MedicalOverride”, true);
input.Parameters.Add(“StarfleetEmail”, true);
input.ErrorList.Add(“Medical Override of Command”);
input.CanProcess = false;
}
}

return input;
}
}

</code></pre>

This plug-in is simple: check that the state is CaptainApproval and when the answer was “Deny” and Kirk has been infected, set the MedicalOverride flag and send Starfleet an email.

The class WorkflowScenarioTest.cs has the method CanAllowMcCoyToIssueUnfitForDuty() that demonstrates how the workflow will execute. We simply add the name of the plug-in to our list of post transition filters:

<pre><code>
string postFilterNames = “MorePlugins.TransporterRepairFilter;Plugins.CaptainUnfitForCommandFilter;SaveDataFilter;”;
</code></pre>

This portion of code uses the plug-in:

<pre><code>

// Captain Kirt denies request, but McCoy issues unfit for command
parameters.Add(“KirkInfected”, true);

step.Answer = “Deny”;
step.AnsweredBy = “Kirk”;
step.Participants = “Kirk”;
step.State = newState;

processor = new WorkflowProcessor(step, filterRegistry, workflow);
newState = processor.ConfigurePipeline(preFilterNames, postFilterNames)
.ConfigureStateMachine()
.ProcessAnswer()
.GetCurrentState();

// Medical override issued and email to Starfleet generated
bool medicalOverride = (bool)parameters["MedicalOverride"];
bool emailSent = (bool)parameters["StarfleetEmail"];

Assert.IsTrue(medicalOverride);
Assert.IsTrue(emailSent);
</code></pre>

Now you don’t have to hesitate with paranoia each time you need introduce a variation into your workflows. No more small upsetters lurking around the corner. Plus you can deliver these changes faster to your biggest fan, your customer. Source code is here.   Run through the tests and experiment for your self.


ActiveEngine Software by ActiveEngine, LLC.