In this post I'm going to document a recent freelance project I worked on. Why I enjoyed working on it and what I did that was vastly different to the way I build software in my "day job".
Complex by Default?
I've worked on large pieces of software for most of my career, they're often complex, there's (almost always) some kind of strange and specific incantation you need to do, to get the solution/projects building and running correctly.
I really enjoy using C# - I'm quite productive in it, and I enjoy the direction .NetCore is persuing (performance, composability etc). With .NetCore, I find creating and getting started with applications much easier, and deployment is usually a breeze (with Azure) - compared to .NetFramework.
What does everyone else think?
Whilst trawling Twitter in my free time, I sometimes come across tweets about how C# (ASP.Net Core) is too difficult and designed only for "complex line-of-business" applications. I wanted to prove to myself (and hopefully you) that it's not true at all.
With .NetCore you can stand up a Web Server, with one C# file and not a lot of code. All samples I've seen online look too simplistic, but I wondered to myself, what if I could create something other than a "Sample App" and actually write minimal (yet tidy) code to actually perform a task. This idea sat with me for months, until...
I secured a small piece of work for a well-known online betting company, to write a small single page web application for an upcoming promotion.
The brief was to create a username/email capture site, where new and existing members of the betting site could submit entries to the competition. The prize was a signed football shirt from a "modern footballing legend" and would run for less than 3 weeks.
Only a few interactive elements were required on the page - a high-quality image of the prize, links to terms and conditions etc.
There were 2 input (text) fields on the screen, a tickbox to confirm the user is over 18 and a big submit button at the bottom.
The required turn-around for this project was short, I'd have a couple of weeks at most to get this done. I work Mon-Fri 9-5, so only evenings and weekends were available.
My initial thought for this kind of project would be a simple ASP.NET MVC Project, with a JSON API (to POST the competition entry) and a MS SQL Server database to store the entries. Now, looking back over that sentence things start to add up quickly, there'll be multiple views (
.cshtml) files, I'll likely use EF Core to talk to the database (there'll be migrations too). The list grows, and more moving parts means more complexity, which equals a higher chance of bugs.
I'd chosen to run this on Azure - it's what I'm most familiar with, and given timescales are tight - I haven't got the time to be exploring/learning other providers.
The project was a fixed fee (for Development, Hosting, Maintenance) - so the smaller cost on my side, means more profit!
Now, Azure SQL Db (DTU model) pricing is very competitive/reasonable. I likely could have gotten away with paying $6 for a single month's use of the database, which would have satisfied my needs. However, I'm a penny-pincher and that $6 is better in my pocket than Microsoft's. Also, having (and paying) for a SQL Db with one table (4 Columns), to maybe store a couple of thousand entries in seemed excessive. Alternatively I could look at Azure Table/Blob storage to store the data, they're great products, however that also feels like more complexity than I need.
CSV to the Rescue!
A simple CSV file in the root of my application would easily solve my needs. It's also really easily consumed by the Client when they want to pick a winner at random!
One CSV file, with 4 columns (Email, Username, CreatedDate, IPAddress) gives me enough information for each recorded entry to the competition.
I was chatting about this approach to a developer friend and the first point he raised was "Hang on, what about multiple requests writing to the file at the same time?". Which is perfectly valid and a great point!
A year (or so) ago I was made aware of some really helpful classes in the .NetCore
System.Threading.Tasks.Dataflow Namespace. Particularly the
BufferBlock classes, which I used in this project.
I'll go into more detail with this in my next blog post, but will stay pretty high level here. I created a
BufferBlock, which takes a
CompetitionEntry and passes that to an
ActionBlock which writes the entry to a CSV file. I've created a pipeline, which only allows one entry to be written to the file at one time.
As I mentioned before, I hosted this very simple web application on Azure. I hosted on Azure App Service, using the B1S Instance (which at the time of writing, I can no longer find on their pricing), which cost me about $7 a week.
Looking at graphs/numbers I collated before shutting down the site, the following statistics stand out:
- Average Response Time = 22.20ms
- Total Number of HTTP Requests = ~81.65k
- Errors = 0
- Data out 10GB+
All that for grand total of $7/week is great value! I had 100% uptime. The site was able to accomodate well over 1,000 users on the site at any one time, with no degradation in performance (again... 22.20ms average response time!).
The project was a success, the client was very happy with the site, how it performed and the number of entries to the competition they aquired.
Personally, going forward, I'm always going to look at the simplest route to success. I'm a big believer in "only using the right tools for the job", probably even more so now. I've seen time and time again that there's no benefit (only hindrance) by over-engineering software up front.
Hope you enjoyed reading this post. If you've had a similar experience with software, let me know in the comments or catch me on Twitter