This is my second post about AppHarbor, I suggest you to read my first impression. I am reading a lot about continuous deployment lately and AppHarbor provide great implementation for simple web applications deployment. - Source Control – Support Git to host your code
- Continuous integration – Check build per commit and run NUnit as part of each build
- Deployment Script – Each successful commit can be deploy in one click
- Rollback – Even after passing build and tests it can be that you still have bugs, so you can simply check older version and deploy it till you commit a fix
 Code and publish is so easy, this is by far this better than using FTP for such things and the option to run tests makes it even more fun.  The option to rollback to previous commit\version is trivial but so important. Moreover, by clicking on “show” you can check the build log and see the tests-run.  You can click the tests link to read more about each test Tip - UrlParameter does not exist: When first trying to deploy my code it failed during compilation. I got this output:
Global.asax.cs(18,67): error CS0103: The name 'UrlParameter' does not exist in the current context I am not sure why, it could be that I am using early beta (didn’t update for a long time), anyhow I fixed this by changing the global.asax.cs from using UrlParamters.Optional to "". You can read more here: http://haacked.com/archive/2010/02/12/asp-net-mvc-2-optional-url-parameters.aspx
Everyone knows Google app engine But what about .net apps? Meet AppHarbor (Thanks Gadi) So I wanted to give it a chance and after playing for less than an hour: - Enable you to build \ host \ deploy web apps
- Provide both Version control and hosting service
- Absolutely free (for now)
- Damn simple
Short tutorial on how to do it: - Create your appharbor account + create new application
- Hopefully you have Git installed (msysgit downloads)
- Init empty Git repository
git init test1 - Copy your files to this directory (download from here: https://github.com/appharbor/appharbor-splash )
- Add files and subdirectories
git add . - Create your remote repository
git remote add appharbor https://username@appharbor.com/test-178.git - Commit your code
git commit -m 'firstcommit' - Almost forgot, we are working on Git - so don't forget to push...
git push appharbor master Till here everything should work but I had a small issue, got this error: error setting certificate verify locations: I've found out that it is all about versions (git --version) - So check yours and upgrade if needed Here you can find great cheat sheet for Git commands: http://ionrails.com/2009/08/07/git-commands-adding-and-committing-cheatsheet/ Btw, AppHarbor support Databases and Running unit-testing after successful builds – I will post about those features later on.
Lately my “find usages” (shift+F12) stopped working. I tried to restore ReSharper again and again but it fails (ReSharper –> find usages –> General –> restore ReSharper) I’ve found out that some other shortcuts still working (for example: find usages advanced, CTRL+SHIFT+ALT+F12) Then I checked the visual studio binding (Tools->Options->Keyboard) and find out that ReSharper.Find binding is missing. I thought about fixing this manually – but god knows what also is not working. And then I found out the magical button called RESET -> clicking on this and running the restore ReSharper again solve this issue! Cheers…
Test methods must be written as production code. While writing your tests you must act the same methods you write for your production code which means: - human-readable (code standard, pattern etc.)
- code re-use (copy paste is never acceptable)
- etc...
This is a code you will probably find in your test projects 1: [Test] 2: public void GetCommentsByQuery_LookFormHmmmText_FindAtLeaseOne() 3: { 4: SvnLogParser parser = new SvnLogParser(); 5: string textToSearch = "Hmmm..."; 6: var results = parser.GetCommentsByQuery(comment => comment.Contains(textToSearch)); 7: CollectionAssertExtensions.IsNotEmpty(results); 8: } 9: 10: [Test] 11: public void GetCommentsByQuery_LookFormBugText_FindAtLeastOne() 12: { 13: SvnLogParser parser = new SvnLogParser(); 14: string textToSearch = "bug"; 15: var results = parser.GetCommentsByQuery(comment => comment.Contains(textToSearch)); 16: CollectionAssertExtensions.IsNotEmpty(results); 17: }
You can see that the two methods are pretty much the same, the only change is the textToSearch variable. There are some excuses for such duplication:
- "We want two different names... to easily understand the failiure reason"
- "we want it to be easy to read, without context switches..." (method calls and un-needed inheritance complexity)
We, of course, can refactor this code, like this:
1: [Test] 2: public void GetCommentsByQuery_LookFormBugText_FindAtLeastOne() 3: { 4: string textToSearch = "bug"; 5: GetCommentsByQuery_AssertAllItemsStartsWith(textToSearch); 6: } 7: 8: 9: [Test] 10: public void GetCommnentsByQuery_LookForHmmmText_VerifyInsideComment() 11: { 12: string textToSearch = "Hmmm..."; 13: GetCommentsByQuery_AssertAllItemsStartsWith(textToSearch); 14: } 15: 16: public void GetCommentsByQuery_AssertAllItemsStartsWith(string textToSearch) 17: { 18: SvnLogParser parser = new SvnLogParser(); 19: var results = parser.GetCommentsByQuery(comment => comment.StartsWith(textToSearch)); 20: 21: CollectionAssertExtensions.AllItemsSatisfy(results, res => res.Comment.StartsWith(textToSearch)); 22: }
This is better when you think of clone detection: less identical rows and the logic was extracted to one method. But people might say that they can't see the AAA (Arrange, Act, Assert) and they want it in one place, Moreover, in such code sample, it is harder to find all the input parameters, cause they will be spread all over the TestFixture methods.
NUnit 2.5 added TestCaseAttribute, this can help us write tests that are:
- more readable
- shorter test-fixture
- all-in-one-place tests
1: [TestCase("Hm...")] 2: [TestCase("bug")]2: [TestCase("bug")] 3: public void GetCommentsByQuery_LookForText_FindAtLeastOne(string textToSearch) 4: { 5: SvnLogParser parser = new SvnLogParser(); 6: var results = parser.GetCommentsByQuery(comment => comment.Contains(textToSearch)); 7: CollectionAssertExtensions.IsNotEmpty(results); 8: }
Here you can avoid the duplication and you won't need to refactor your Tests to more than one method, while you still see them running using the given parameter, for example when the second parameter will fail you will see this output:
------ Test started: Assembly: App.Tests.dll ------
TestCase 'App.Tests.NewFolder1.SvnLogParserTests.GetCommentsByQuery_LookForText_FindAtLeastOne("Hm...")'
failed:
Expected: True
But was: False
C:\ShaniData\ProjectsByTitle\Delver\App.Tests\NewFolder1\SvnLogParserTests.cs(75,0): at App.Tests.NewFolder1.CollectionAssertExtensions.IsNotEmpty[T]
C:\ShaniData\ProjectsByTitle\Delver\App.Tests\NewFolder1\SvnLogParserTests.cs(33,0): at App.Tests.NewFolder1.SvnLogParserTests.GetCommentsByQuery_LookForText_Find...
4 passed, 1 failed, 0 skipped, took 0.78 seconds (NUnit 2.5).
The output will point the given method and the parameter used - which will ease finding the error. You can extend reading about the usage here
For more background about when we use this API you can read my last post about Rendering Objects to Html Simple Rendering of query: 1: var query = new StringTemplate("SELECT $column$ FROM $table$;"); 2: query.SetAttribute("column", "name"); 3: query.SetAttribute("table", "User"); 4: var data = query.ToString();
We will refactor this sample to handle the queries from an outside source:
1: var group = new StringTemplateGroup("SimpleTemplates",@"C:\Templates\TemplateEngineTestCase"); 2: var query = group.GetInstanceOf("1_simple"); 3: query.SetAttribute("column", "name"); 4: query.SetAttribute("table", "User"); 5: var data = query.ToString();
Rows 1,2 - loading the template data from a source file.
Here is the Template (1_simple.st):
//1_simple.st
SELECT $column$ FROM $table$;
Template Anonymous Type:
In the last template usage (1_simple.st) We bind the parameters using strings only. but we also have a better options: let's assume we wrote down such template:
//2_simpleObjects.st
Full Name: $Person.FirstName$ - $Person.LastName$
But let's assume that we don't have the Person class\instance, we can simply write it using the anonymous types:
1: var user = new {FirstName = "Shani", LastName = "Raba"}; 2: var group = new StringTemplateGroup("OOTempaltes", @"C:\Templates\TemplateEngineTestCase"); 3: var query = group.GetInstanceOf("2_simpleObjects"); 4: 5: query.SetAttribute("Person", user);
You can also use this kind of bindings for setting template-attributes from each one of the Person sub-classes.
Template list:
Till now it is all pretty simple to implement by yourself, but the real issue here is the List binding feature. You can write such template:
//3_simpleLoop.st
$items: {num1|
<li>$num1$</li>
}$
$end$
and bind the list using this code:
1: var templateFolder = new StringTemplateGroup("SimpleLoopTemplates", @"C:\Tempaltes\TemplateEngineTestCase"); 2: var template = templateFolder.GetInstanceOf("3_simpleLoop"); 3: 4: template.SetAttribute("items", new List<string> {"Shani", "Doron", "Nati", "Yossi"});
Conclusion:
- The code is pretty simple, the templates engine implements good functionality and is well documented.
- The StringTemplate syntax is easy to learn and well documented.
- I still don't like it when I need to learn a new language\syntax - it will sharpen the newbie's curve.
- StringTemplate is missing good Object2Template Designer.
Background: We are writing a new task for the ArcGis Explorer, this task needs to place images on the globe using its X,Y coordinates. While for each instance on the globe we need to render its details as html. Mission: Rendering the objects to html, we are still didn't find the right place (on the server or on the client), but let assume that they both need to do the same job. Ideas: - Render in code:
This is the naive way of thinking. while you are first thinking about this problem you might think to add the object an ToHtml() method. Always think about the: Single Responsibility Principle (SRP). You can still think about Writing an HtmlWriter or HtmlRenderer class that gets object and render the object using reflection or something else, but than you will find yourself indenting you JavaScript\html\CSS in C#, for example you can watch this code:
1: var items = new List<string> {"Shani", "Doron", "Nati", "Yossi"}; 2: var sb = new StringBuilder(); 3: items.ForEach(currentItem => 4: sb.AppendFormat("<li>{0}</li>", currentItem) 5: ); 6: string data = sb.ToString();
Let's think about the time we will need to change the UI from <li> to one with style or maybe even change the list to be styled as table...
- XSL - is pretty more dynamic than code, isn't it?
So we are now looking for something more dynamic, something that we can read from a file so we can give it to our designer to play with the UI. This lead us to the second option: at my past all our reports were rendered using XSL files, personally I don't like this option. But the main reason is that we will need to serialize our objects to XML, while in most cases all you need is to render only few fields.
- Let's found another Template Engine:
The first one I can think of is the MVC Engine or Brail. after some searching reading and Testing I found StringTemplate. Here is a simple code for using the API:
1: var templateFolder = new StringTemplateGroup("SimpleLoopTemplate", @"\TemplateEngineTestCase\WinApp"); 2: var template = templateFolder.GetInstanceOf("3_simpleLoop"); 3: //here we are binding our list to the template 4: template.SetAttribute("items", new List<string> {"Shani", "Doron", "Nati", "Yossi"}); 5: var data = template.ToString(); and here is the template (file name: 3_simpleLoop.st):
1: $items: {num1| 2: <li>$num1$</li> 3: }$ 4: $end$
Conclusion:
The StringTemplate give us an API to solve our problem - and using such code and template we can render our Models to different Views.
But is this API is easy or even stable?
In later posts we will see more samples using the StringTemplate. Hopefully samples for using Brail too.
Last month I've presented a simple newbie's tutorial about NTS - Net Topology Suite. Here you can download the code sample & presentation. What is it NTS (Net Topology Suite)? - implements geometry model defined in OpenGis Consortium (OGC)
- implements simple features inside the OpenGis Consortium (OGC) as Geographic Data access
- implements Some great OGC writers as: GmlWriter (Geographic markup language), WktWriter (Well Known Text)
How do I know whether I need NTS: - You are coding a GIS (Geographic Information Systems) applications
- You want to use a known Convention for Point, Polygon, Polyline etc.
- You want simple implementation for OGC
3 times No - you don't need this 3 times Yes - you must read this article and probably use it. You can read more about Kml & C#3.0 - at my last post. I will keep posting more samples in the near future.
This post inspired by Gal Ochana. Gal is a new gifted programmer at my team, she presented a great presentation about Linq to XML - you can download code here. The great bonus at her presentation was the Linq to Kml Sample, I would like to share this with you. The kml itself is an XML file at our sample it looks like this: 1: <?xml version="1.0" encoding="UTF-8"?> 2: <kml xmlns="http://www.opengis.net/kml/2.2"> 3: <Placemark> 4: <name continent="America">America</name> 5: <description>Attached to the ground. Intelligently places itself at the height of the underlying terrain.</description> 6: <Point> 7: <coordinates>-100.0822035425683,37.42228990140251,0</coordinates> 8: </Point> 9: </Placemark> 10: <Placemark> 11: <name continent="Africa">Africa</name> 12: <description>Attached to the ground. Intelligently places itself at the height of the underlying terrain.</description> 13: <Point> 14: <coordinates>20.0822035425683,20.42228990140251,0</coordinates> 15: </Point> 16: </Placemark> 17: <Placemark> 18: <name continent="Asia">Asia</name> 19: <description>Attached to the ground. Intelligently places itself at the height of the underlying terrain.</description> 20: <Point> 21: <coordinates>42.0822035425683,33.42228990140251,0</coordinates> 22: </Point> 23: </Placemark> 24: <Placemark> 25: <name continent="Europe">Europe</name> 26: <description>Europe</description> 27: <Point> 28: <coordinates>100.0822035425683,62.42228990140251,0</coordinates> 29: </Point> 30: </Placemark> 31: </kml>
You can read more about Kml here.
Screen-shot of the above kml in the ArcGis-Explorer:
You can see in the above Kml file sample the continents represented as a simple points, of course you can extend it to include polygons, poly-lines or anything else that valid within KML standard. The only things that differs Kml from the known Xml file is the namespace that we will need to handle in our code, let's see the query itself:
1: XNamespace ns = "http://www.opengis.net/kml/2.2"; 2: 3: XDocument kmlDoc = XDocument.Load(InputKml); 4: 5: var result = from placemark in kmlDoc.Descendants(ns + "Placemark") 6: where (placemark.Element(ns + "name") 7: .Attribute("continent").Value == 8: Continents.SelectedItem.ToString()) 9: select placemark;
line 1: declare the full namespace that will be used for the attributes and Tags line 3: loading the kml input file line 5-9: run a simple query to select a single continent, pay attention to the namespace that we concatenate for selecting the right node.
Here you can see a screen-shot with the result of the above query using the "Asia" continent as the selected item.
Enjoy.
Dev Academy 3 just finished, but if you feel you missed a lecture or maybe missed the whole day, you can sit back download the code and full length lectures. You can find everything in here http://www.microsoft.com/israel/msdn/devacademy3/2.aspx. Pay attention: while the presentation were written in English, the session all of them were in Hebrew but you can also enjoy the code. I recommend on this lectures: - Dev301, Eyal Vardi lectures about Http Web Services: Great performer, good subject, lots of code
- Dev 402, Sasha Goldshtein lectures about Concurrent Programming: I didn't like his style, but still some great samples.
- Arc 301, Yair Siwek lectures about "Velocity": Great performer, funny guy. You must watch this session.
Enjoy.
The last day of Tech-Ed, two more lectures to go: TDD, MVP & UX - (by Ron Jacobs) Ron made a great lecture, about Test-Driven-Development and about having a rich User-interface (or as he called it, not only interface but also experience - with events) but still can test it using Model-View-Presenter pattern. he also explain the differences. Here are some great posts for the differences: Martin Fowler, Alex, Nikola. He also talked about Passive View. and showed a great code sample (I didn't find the presentation or the code in his blog, The sample was great, I wish it will be uploaded to its blog) My grade to Ron's lecture: 9/10 F# Introduction - (by Luke Hogan) Luke had a great lecture about the F#. F# is a functional (and Object Oriented) programming language for .Net, which is something very geeky I might say. (you can found his lecture & samples here). There are some cool things I found useful in this language such as using the let for variable and methods using the same syntax, for example: let data = (1,2,3) let g(x) = sum + x*x the data is immutable by default so it will reduce the frequency of bugs by reducing the amount of special case-code. it is also can be passed between threads easily. Something else in the F# is the pattern matching you can use (I didn't realy know the syntax so it would be better for you reading the code at Luke's blog). you can train yourself with F# using this tutorial. Why using F#? it still not so clear for me, but as Luke said: It is a bridge between the the Dev team and the Research Team. Luke also recommended the usage for the F# for Data-Mining because of the pattern matching, and for scientific data analyst. My Grade to Luke's lecture: 9/10 This is the last post for the TechEd week (here is a link to Day 1, Day2).
This is the main day of TechEd were we had lectures from 8:00 till 19:00 Here are my list of lectures for that day: Optimizing and Extending ASP.NET Ajax - for going beyond the update panel - (by Assaf Shely) This was a lecture of 400, at least that is what they wrote. in reality that was an introduction for Ajax, he explain about the update panel and about JSON. The only thing I want to add from this lecture is all he says about ASP.NET Ajax 3.6 - which can support browser history capabilities. My grade to Assaf's lecture: 6/10 (a big disappointment) DDC & ASP.NET MVC (by Noam King) DDC - dynamic data controls (you can read here), MVC - Model View Controller (you can read more in my last post about ASP.NET MVC). Noam showed a simple usage of the MVC API, and a simple creation of a web site from the DDC API, those both samples are the simple web casts you can find and learn in 15 minutes. a big waste of time (again) My grade to Noam's lecture: 8/10 (Noam is a great lecturer, the problem was the level of the lecture - All they should do is to write: Intro at the beginning of the lecture description) Service Host Customization (by Eyal Vardi) Finally a great lecture for the second day. It was a great one. you can download the lecture here. Eyal showed a great sample for Config manager - which helps you manage your configurations details (addresses for example) - and in such way you can manage it inside your DB or something else - better than a configuration file (it gave me some great ideas for my next posts). He also used the ServiceHost VIsualizer - I even started to use it at my place. Next we dive into the Service Model Layer and its behaviors. I'll probably write about each of them in the near future. For now, there were 4 demos: Demo 1: CD - Channel dispatcher - writing you own Error Handler, we also talk about the throttling. Demo 2: Saving persistence of the Service inside a given Service Host. Demo 3: DR - Object Pooling using the Dispatcher Runtime, it is a great sample. Demo 4: Serialization Issues - Eyal wrote a sample-infrastructure for handling Serialization and DeSerialization without using the known-types.
Go Gold with Silverlight (by Laurence Moroney) This was an Introduction to Silverlight (of course), the only thing I liked about the lecture is the way he explained the differences between Silverlight 1.0 to Silverlight 2, while Silverlight 1.0 - is web friendly UI the Silverlight 2 - is .net based programming model with improve productivity. Laurence showed some cool samples (most of them you can find here, here, here and here), the one I liked the most is a Server servlet (written using J2EE) but the client that consume it is a .net web client (Silverlight) - at my place, one of our teamd, has some Java assets and they want to use it, so they start develop their own UI like in Java for movies\Audio\Web-Parts\Ajax capabilities - this sample could help them a lot. My grade to the Laurence lecture is 7/10 - Laurence was great the problem was the lecture agenda - I really had enough from the Silverlight previews (so either call it preview\intro or show some code in it)
Restfulness (by Ron Jacobs) First you should read this book (as they said - this is all you need to know about REST) After David Chappell's lecture about REST for the first day people told me not to take another REST-lecture, but I did - and - IT WAS GREAT!. you can read more on Avi's post. Ron gave more details about the implementation of REST using the WCF. for example: How do you notify the sender about error in REST, you can't send XML back to the client... The answer is simple: for example for deleting non-existing row you will get 404 (HTTP Error code) - I might admit I like this one, the problem is that you should write your own fault architecture to return those codes back, _still_ not implemented at the REST attributes of the WCF. (one more sample: an internal error in your code will probably should return 500 - un-handled exception) Here is another thing that is still not so easy to do in your WCF implementation - how you can ask for a response? for example you would like to get the JSON return value and not the simple xml... in REST - all you need to do is to add the extension to your request, but you still need to implement it in the WebMethodAttribute by yourself. And there were more samples, you can download them here... (Ron's website). {you can also read more in Wortzel's post} My grade to Ron's lecture is: 9/10.
I've read Avi Wortzel's great post "Host Multiple services in windows service". Avi create his own Windows Service which on start knows to also start other services such as: Simple Windows Service and WCF Service. At my place one of my developers, Elad (blog-less), wrote a spike for running our own Windows Service which can manage all Wcf Services in a given dll, (we didn't like the usage of IService which cause us to change the Wcf Service and implement a specific methods for windows - while the WCF team works hard to cause the framework to be generic to all hosts) . In Elad's solution we will iterate over the dll's classes which had the [ServiceContractAttribute] above it. And now: while turning on\off the main (windows) Service it will also start\shutdown all existing WCF Services. Today I dig a little bit the MSDN and the IDE directory and found WcfSvcHost.Exe which also knows to start\stop all Wcf Services in a given DLL. This one is great, it even had its own UI to manage each service by itself. Here you can see me running Wortzel's WcfService using WcfSvcHost.exe with no code written at all. I didn't test the whole functionality of this application, but it looks good enough for your basic services and samples, I still believe that on sophisticated scenarios we will still need to use Avi's-like-code.
Here at Doron's post about Object Initializers he raised a question about the IL generated from the compiler while generating Object Initializer.
//Object Initializer GeoPoint point1 = new GeoPoint() { X=22.555, Y=36.444, CoordinateSystem=GeographicCoordinateSystem.Wgs84 }; //Associative Init GeoPoint point3 = new GeoPoint(); point3.X = 22.555; point3.Y = 36.444; point3.CoordinateSystem= GeographicCoordinateSystem.Wgs84;
That two samples are not the same, this is because of not having an atomic assignment possibility at the second piece of code. you can have further reading at Bart's blog post.
Enjoy.
|