In the previous post I told you we decided to write our own report system, so we’ll have an html page for each letter or report fixed contents and some kind of a special pattern for their interchangeable parts.
From now I will only say report but remember it could be a letter too.
Our program read through those html pages and find their interchangeable parts according to the pattern and replace them with the actual values(which were determined by users).
So after some discussions between me and my boss we found out we should have a Parser module which extract out interchangeable parts. After that we pass those parsed parameters to a Getter module which gets their actual values and then we give those values back to the parser again and it replaces them in the report, So we’ll end up with a complete report with actual values in it, PERFECT.
Just so you know our patterns were these:
*Because “~” and “
” don’t have any meaning in html we used them.*
We used Regex for our patterns. First one is for simple things like ~LetterNo~ or ~Title~ and etc which will be set by users directly. Second one is for repeatable things like collections or one-to-many and many-to-many relationships between our Entities in the system.
For example imagine we have a File entity which has a one-to-many relationship with Person entity(each File contains a collection of Persons) so we should be able to get values for all of those persons and put them in the report, ergo the string in the page is something like this which matches with the pattern:
now for each person in the collection we get Name and Family values and put them in the report (in this case we have two persons for simplicity of example):
So I started to write my first test for this Parser module(you should always have tests and yet better than that you should do TDD as much as possible in your applications
Here’s my first test (BTW, I wrote this module with TDD approach):
So I wrote this function for getting all the parameters:
The next two tests that I wrote were these:
So for making these tests pass I wrote these two methods and also used them later in other parts:
At this point, I could get all the parameters from the input content(which in our case is html string) and also could extract Key and Value from any string which matches with my “TEMPLATE_PATTERN”;
Now I should be able to replace the actual values with parameters which I detected with “GetAllParameters” method, so that led me to this test:
Then I wrote this method for replacing values:
At this step I wrote another test for Parser which checked handling a string that matches with “TEMPLATE_PATTERN” and replace values in it as many times as needed:
This test led me to this function:
Ok, everything was fine and I almost had whatever I needed at the first place for my Parser Module.
Now was the time for writing the main Parse method which takes a string and a getter then return a result string which is filled with actual values. For this purpose I handled all the templates at first and after that I handled all the other parameters in the input text:
As you saw, after I found out what I need, I tried to write it step by step. I never made a big decision and never wrote something big, instead I tried to do everything little bit at a time, any decision I made was for at most 5 minutes later. I wrote my test first then I wrote a production code which made that failing test passed. At last coverage of this module was 98%(which is a great coverage by the way).
Of course the code you saw is not the first version I wrote. After I made each test passed, I stopped writing tests and code and did some Refactoring on the code I just wrote, So I ended up with a CLEAN CODE with small methods(each of them does one thing and does it well) and that’s one of the numerous benefits of TDD.
*There is more about this report system, I'm gonna talk about it soon ...*