c# - Good Design For Regex, Capture Groups And Unit Testing -


in project i'm experimenting using regular expressions distinguish between various types of sentences , map them functions handle these sentences.

most of these sentence handling functions take arguments sentence itself, parsed out capture groups in regular expression.

ex: "i paid $20 2 cookies" matched 1 of regular expressions in parse tree (a dictionary). regex match extract $20 group "price", , 2 group "amount". mapping correct handler function , calling follows:

foreach(keyvaluepair<regex, type> pair in sentencetypes) {     match match = pair.key.match(text);     if(match.success)     {         ihandler handler = handlerfactory.createhandler(pair.value);         output = handler.handle(match);     } } 

example of simple handler class.

public class notecookiepricehandler     {         public string handle(match match)         {             double payment = convert.todouble(match.result("${payment}"));             int amount = convert.toint32(match.result("${amount}"));              double price = payment / amount;             return "the price $" + price;         }     } 

i trying set unit tests moq out, when realized can't mock match object, nor regex. thinking more design seems flawed in general, depending on named groups being correctly parsed , handed handler class without interface.

i looking suggestions on more effective design use in passing parameters correctly mapped handler function/class, passing match object seems problematic.

failing that, in figuring out way mock regex or match appreciated, , @ least me solve short term problem. both lack default constructors, , having hard time getting moq create objects of them.

edit: ended solving @ least mocking problem passing dictionary of strings match groups, rather (un-moq-able) match object itself. i'm not particularly happy solution, recommendations still appreciated.

foreach(keyvaluepair<regex, type> pair in sentencetypes)         {             match = pair.key.match(text);             if(match.success)             {                 ihandler handler= handlerfactory.createhandler(pair.value);                 foreach (string groupname in pair.key.getgroupnames())                 {                     matchgroups.add(groupname, match.groups[groupname].value);                 }                 interpretation = handler.handle(matchgroups); 

one way avoid bad design start principles of design instead of problem wish resolve. 1 of reasons why test driven development powerful in transforming quality of code. way of thinking did exist way before tdd though under name: design contract. allow me demonstrate:

what ideal handler like? how this:

interface ihandler {     string handle(); } 

implementation:

public class notecookiepricehandler : ihandler {       private double payment;     private int amount;      public notecookiepricehandler(double payment, int amount) {         this.payment = payment;         this.amount = amount;     }      public string handle() {         return "the price $" + payment / amount;     } } 

now starting ideal design, perhaps tests design. how can sentence input of sentences sent handlers? well, problem in computer science can solved layer of indirection. let's sentence parser not create handler directly, uses factory create one:

interface handlerfactory<t> t: ihandler  {     t gethandler(keyvaluepair<string, string> capturegroups); } 

you create 1 factory per handler, enough find way create generic factory. using reflection example match capture group name constructor parameters. based upon data types of constructor parameters automatically let generic handler factory convert strings correct data types. testable creating fake handlers , asking factory populate them using key value pair string inputs.


Comments

Popular posts from this blog

python - How to create a legend for 3D bar in matplotlib? -

java - Multi-Label Document Classification -

php - Dynamic url re-writing using htaccess -