Giraffe F# update

In a previous post I have written about Giraffe and shown some workarounds for what I perceived as limitations considering my existing enterprise ecosystem.

Now that Giraffe has turned 3.0 loads of things have improved even from my perspective. Obviously they are now competing in performance benchmarks, so loads of optimisation work has happened behind the scenes. For me, though – the most interesting bit is to see how they dealt with my complaints.

Configuration, logging and service location is now available through extension methods on the context.

Response handlers now handle streams and chunked responses.

Content negotiation looks very clean.

We have of course welcomed these improvements and use them in all our F# APIs.

The only remaining complaint is that the Swagger support is still not usable enough for our purposes. The fact that we would have to configure an additional separate nuget source onto get the package prevents us from actually using it in anger although showing API actions was simple enough but I’m unclear as to how to document request and response payloads – but that only becomes worth exploring when the package is served from nuget.org

Advertisements

Contrarian style guide for C#

Goal

I have decided to try and formulate what I want C# code to look like. Over the years I have accumulated a whole host of opinions that may or may not be complimentary or maybe contradict each other. The purpose of this post is to try and make sense of all of it and maybe crystallize what my style is – so that I can tell all of you how wrong you are and what you crazy kids should be doing.

Is this all my intellectual property? Hells to the no. I have read and heard a bunch of stuff and probably stolen ideas from most people, but the most important people I have listened to or read are Fred George and Greg Young. Sadly it didn’t take.

Object oriented programming

Loads of people hate it and cite typical C# code as the reason why. Yes. That code is horrible, but it isn’t OOP.

Why was Object Oriented programming invented? It was a way to make sense of large software systems. Rather than a very long list of functions that could – and did – call any other function perhaps modifying global state on the way, people were looking for a way to organise code so that changes were predictably difficult to make. This was achieved by introducing encapsulation. Private methods and fields could not be affected by external code and external code could not depend on the internal implementation of code in a class. If implemented correctly “change” means adding a new class and possibly deleting an old one.

Was this the only way people tried to solve this problem? No – functional programming was popularised, relying on pure functions and composition again offering a way to make changes in a predictable way.

I don’t mind you using C# to write in a functional style and by using composition, but if you’re creating classes – take encapsulation seriously. Encapsulation is The Thing with OOP. This means properties are evil. Think about it. Don’t put properties in the code.

But what about inheritance?

Yeah, when Borland C++ came out in 1992 the ads were full of Porche Targas that inherited from Carrera S but with the roof overridden to be missing (!) and similar. Oh – the code we would reuse. With inheritance.

Well. Barbara Liskov probably has some things to say about the Targa I suspect.

In short – don’t use inheritance unless the relationship between the classes is “is a” and the relation is highly unlikely to change.

Single responsibility principle

So you have heard about the single responsibility principle. When you see duplication you swoop in, add a new parameter and delete one of the functions. Boom!

Except what if those two functions weren’t doing the exact same thing? Their similarity was only fleeting. With the refactoring you have just made you have introduced a very hard coupling.

Code size

A method shouldn’t have more lines than three or four. Be liberal with the extract method refactoring. To “fit” in this metric, make guard clauses one line each. Put in one empty line after guard clauses and the meat of the class.

Why? What is this? Why are we counting lines now? Well code tends to attract more code as it ages and methods grow. Having a “magic number” that is The Limit helps you put in the time to refactor and thus battle the bloat before it happens.

Classes should not have more than two or three fields – as discussed earlier there will be no properties. If you feel yourself struggling trying to convince yourself to add another private field, do investigate whether or not there isn’t a new class in there waiting to break free.

Don’t be afraid to leverage the fact that private is a code level constraint, not an instance level one. I e, you can let instances of a class talk to each other and they will have access to the private fields of the sibling. This is one of the ways in which you can do actual work without properties.

Edges

Well with this whole Amish attitude to properties – how do you even deserialise json payloads or populate DTOs from the database? How do you write files?

By using the mediator pattern or writing adapters. At the edges you will find code getting less OO and more … procedural? I e anemic classes with only data, loads of members et c and verbose code that talks to very microsofty framework classes.

This is OK, and to some extent natural – but do not let it leak into the domain. Create domain and value objects for the actual processing without leaking any of the ugliness into the domain.

Avoid raw primitives

If you throw around a customer ID in your code – how do you represent it? As an int? How about an order ID? You know the drill – an ID cannot reasonably be added, subtracted, multiplied or divided and it probably can’t be <=0. And a customer ID and order ID should probably never be assignable to the same parameter.

Yes – take the time to do value objects. Resharper will generate equality and GetHashCode for you, so yes it is harder than in F# with more required boilerplate, but it is worth it.

Conditionals

Where the arbitrary constraint on method size really cuts into your Microsoft sample code style is in the area of conditionals. Do you even WinMain bruv? Nested if statements or case statements – what about them huh? Huh?!?

Yes. Get rid of them.

When making small classes an if statement is almost always too big. Lift the variability into its own class – a strategy.

Unit tests

There are two schools of unit testing. The London School and the Chicago School. The Chicago school relies on setup of instances, calling them and asserting the results. The London School relies on setting up a series of mocks, passing them into a class and then asserting that the mocks were called in the right order with the right values.

Of course – me being lazy – I prefer the Chicago school. With small classes you can just call the public methods and assert that the right results come out. If you feel the need to get inside the class to look at and validate internals – your class under test is too big or does too many things.

Creating a class

When you create a class, think about its purpose. “What’s its job?” as Fred George asks. Don’t create a class where the name ends in er or or. Find a concept that describes what the class understands.

It’s ok to spend 15 minutes drawing on paper how you see the next bit of coding to go before you write the first test and get going.

Disclaimer

It depends. Of course it all depends. But I’ve never noticed “omg these classes are too small and have no weird dependencies- I need to refactor” so I am fairly confident in these recommendations.

Reading list

The following books are useful to have around or to have read.

Some other books that are good for you as a developer:

Validation (in ASP.NET Core)

Background

There is a philosophical aspect to request validation. When receiving user input you must make sure it is safe to process, and multiple libraries and frameworks exist to help you with this. Also, when creating instances in your domain you must make sure they can never be in an invalid state. Determining whether a – let us say – SalesQuote object can be instantiated in a valid state can require fairly elaborate checks, cross-referencing against caches or even a data store. Surely – writing custom validators and plugging them into the ASP.NET Core validation pipeline should be the perfect fit here? Few lines of code to set up the plumbing, and then leaving your controller actions to work with valid domain objects after invalid requests have been automatically refused. Nirvana?

Asynchrony

When reading the Twitter timelines of members the team behind ASP.NET Core, you notice a focus on cross-platform performance and benchmarks. The framework does not provide training wheels like synchronisation contexts and request buffering, meaning that if you do things right you can have blazing performance in the millions of requests per second, vs tens or hundreds in ASP.NET of old – but it also means if you do it wrong your site can be knocked offline because you use up all your threads in the thread pool and you need to restart the app.

The Right Thing is non-blocking I/O, which in C# means async/await all the things.

So – back to our validation.

Synchrony

The validation pipeline in ASP.NET Core is synchronous, and the team – with the zeal of somebody who knows they are wrong but is in too deep to back down – is saying nobody needs async validators. Another reason could be that benchmarks do not cover validators, so there is no glory to be had by validating faster than Play on Jetty.

FluentValidation, my current fave in validation frameworks, does offer async validators, and means of calling them asynchronously – but there is no way of using any asynchronous methods in the traditional Mvc validation pipeline. Well, there are – as they have created synchronous wrappers around the asynchronous code – but that type of async-under-sync and fake async consume extra threads and puts the stability of your app at risk.

What is wrong with the ASP.NET Core guys you ask? Well – it’s the philosophy that differs. They would probably even think they are right. They want the validation to be synchronous because they don’t think you should do syscalls in a validator. Why would you put business logic in a http request validator? That’s too close to the metal they might say. Just check that an expected number actually is a number and that data are the sizes you expect, things you can do without blocking code. Domain validation is a domain concern – not a networking concern. I can see the validity – no pun intended – in that line of reasoning.

But things like FluentValidation make such readable code!

RuleFor(q => q.Quantity).GreaterThan(0).MustAsync((q.Quantity, a) => MeetMinimumOrderQty(a));

Simply looking at a validator class makes the full requirements very clear, well, depending on how you name your helper methods.

Having your cake and eating it

There are asynchronous Action Filters in ASP.NET Core. As long as you register your validators in DI you can use an action filter to asynchronously call your validators manually and optionally short-circuit the request if any of the action parameters fail validation, by implementing the OnActionExecuting method, not forgetting to await the next() delegate if you want the call to proceed.

API Versioning

I recently had to look at API versioning for ASP.NET Core 2.0 APIs for work. We looked at aspnet-api-versioning and contrasted that with Troy Hunt’s You are doing API-versioning wrong […].

We had decided we didn’t want to version controllers but rather the individual actions.

Initial approach

We all went off and looked at various solutions end-to-end and will compare notes tomorrow.

I tried a variation of Troy Hunt’s VersionedRoute attribute – but based on the IActionConstraint attribute for ASP.NET Core – that applies a regular expression to the accept header to determine the version to select. Initial testing showed promise.

Showstopper?

Swashbuckle does not enjoy multiple actions with the same route in the same Swagger document. By using operationfilters to keep versions of the same actions in separate SwaggerDocs we could get the page to load without error.

Hack

By figuring out the highest version of any action in the API I generate one SwaggerDoc for each, including either actions with that specific version – or the highest version of operations that only have lower versioned actions or of course unversioned actions.

That way, if you just load the swagger page – you only see the newest versions. Weirdness only sets in when you try to operate the versions dropdown, but even then it kind of makes sense.

More F# – Giraffe

So finally the opportunity arose to do some real world F# at work. Being involved in Enterprise Sofware Development a “real world” coding assignment is more akin to Enterprise FizzBuzz than cool Data Science. A colleague had had earlier success using Giraffe, so I favoured that for this task and this blog post is a charting of my struggles. I needed to create an API to server a specfic type of files and non-functional requirements were that I needed to support an existing deployment pipeline for various environments that currently rely on configuration using appSettings.json as well as logging to Serilog and additionally I need OIDC support to authenticate between services. Finally – of course – I need to store data in old school SQL Server.  Ideally, I would have liked to provide a Swagger page which I could point to when I want front-end peeps to RTFM, but that is not supported, so I’ll have to tell them to use the source.

Getting started

In order to get off the ground I installed VS Code with Ionide using the getting started guide. I already had .NET Core 2.0 installed, so I could just use dotnet new to create a F# Giraffe scaffold.

Configuration

In order to set up the correct Identity Server parameters I needed this web site to support configuration, and I already knew I wanted to use bog standard ASP.NET Core configuration (including inheritance – yes, I need it. No it’s not worth the effort to change the circumstances) rather than fancier stuff like yml, the best config markup available. Yes, I could save the world by building a config provider for yml and update all our configs, but today is not that couple of weeks that would take to land a change of that magnitude.

.NET Core 2.0 for n00bs

Oh, yes, I forgot to mention – this is my first outing on .NET Core 2.0, so there are a couple of changes you notice in the hosting and app configuration pipeline. One of them is I don’t know where my configuration is supposed to live. Or rather, it can live where it used to live, in the Startup class, but the startup class is now optional, as you have other calls on the host builder that can let you configure app configuration and logging without needing a startup class. For my purposes that was a no go, I needed to get hold of my configuration somehow, so I created a startup class and created a singleton to hold the complete configuration. This singleton got initialised when the startup class was created. With this I could now configure authentication. This isn’t the nicest way to do things, and I’m open to better ideas, but google had nothing. It was as if I was the first one ever to attempt this, which is partially why I’m writing this down. If I’m wrong, hopefully somebody will give me snark about it so I can update with a corrected version.

Authentication

There is a sample for how to use JwtBearerToken authentication, so I just used my new-found configuration skills to add a layer of usefulness to it. Essentially in the jwtBearerOptions function I get the config singleton from above and I use

  configMgr.GetSection("JwtBearerOptions").Bind(cfg);

to bind the configuration file settings to the object and afterwards I set some defaults that I don’t want to be configurable. To my shock, I ran postman and sent a valid token to the claims Giraffe sample endpoint and I got me some claims. Incredibly, it worked.

Database access

I have, in C#, come to enjoy Dapper. No nonsense, you write the queries, you get the data sort of lightweight ORM that is simply enjoyable to use. I found an F# wrapper over Dapper that Just Worked. Asked my config singleton for the connection string and we were off and running. Most enjoyable. There were some gotchas involving querying with GUIDs, which I circumvented by typecasting, as in

WHERE CONVERT(varchar(60), FieldA) = @FieldA

I assume you have to cast in your selects the other way around to query uniqueidentifiers as well. but that’s not the worst thing in the world.

Also, multiple parameters in a map to the F# wrapper means you have to cast the variables to obj before you call the query method.

 Map [ "FieldA", fieldA :> obj; "FieldB", fieldB :> obj]

Serving files

I made a tiny hack to serve binaries:

let stream (streamInstance : Stream) : HttpHandler =
    fun (next : HttpFunc) (ctx : HttpContext) ->
    task {
        ctx.Response.Headers.["Content-Type"] <- StringValues("application/pdf")
        ctx.Response.Headers.["Content-Length"] <- StringValues(streamInstance.Length.ToString())
        do! streamInstance.CopyToAsync(ctx.Response.Body)
        return Some ctx
    }

Of  course, a proper implementation will have some kind of record type or at least tuple to provide the mime type with the stream rather than hardcode it.

Service Locator

I set up the IoC container in my unsuccessful attempt at getting Swashbuckle to document the API. I registered an operation filter I normally use to make Swagger ask for an authorisation header on API operations that require it, and that was a bit fiddly, but not very weird. I just made a module that gets called from the ConfigureServices method in the startup class.

Conclusion

Yes, loads of classes and mutable methods. This really is a mess from an F# perspective. Not a lot of tail recursion and immutability. I put the blame on ASP.NET Core. And also I suck at F#, although I’m trying.. My hope is that once this is done I can revise and do better. No, I can’t show you teh codez, but suffice it to say, it looks a lot like the above sample code.

 

 

 

 

Console setup for powershell

After not really seeing the value of console replacements in Windows I have completely come around.

To make life more enjoyable when developing on a Windows 10 machine, install the following things:

  • Install Sublime
  • Install cmder
  • Enable Windows Subsystem for Linux
  • Choose a WSL compatible distro, I went with Ubuntu
  • Install MobaXterm X Server
  • Clone powerline patched fonts
  • Clone Hub CLI to get better Github tools for the commandline
  • On WSL:
    • Install zsh
    • Install the above powerline fonts
    • Config dircolors
    • Install oh-my-zsh
    • Set agnoster theme
  • In Powershell
  • Optionally install i3-wm and terminator under X in WSL. Not super practical but cool.

I have previously had problems with cmder acting strangely when using bash for Windows, but with this setup the experience is seamless. Cmder also provides excellent autocorrect for powershell.

If necessary install a separate Sublime under WSL, but normally editing files in Windows but for instance running yarn under WSL by accessing the files under /mnt/c/ works perfectly well.

The PowerShell setup requires some modifications to the profile to load PoSh Git, DirColors, set themes and aliases et cetera.

F# vs C#. Again

Loads of stuff has happened since my last post. I changed jobs. Doing a lot more .NET Core now. Better commute. Still working with really clever people. Anyway – that isn’t the point. 

Build 2017 happened. ASP.NET Core 2.0 happened. Apart from pointless Cortana and Azure debugging features inaccessible to professional developers (as you’d need to deploy directly from VS like a cowboy) – the ASP.NET Core 2.0 changes are sound. 
With ASP.NET Core 1.x they tried to break apart the framework to deliver only the bits you need. That lead to amazing amounts of boilerplate code in Startup.cs and made it difficult for people to discover which features are available due to the various references you might need to add first. Now you have to install the entire framework on the server – but allegedly .NET will remove unused DLLs when packaging for self-hosting.

This, however, isn’t the point either.

One Twitter flamewar that blew up during build was that you can’t target this preview of ASP.NET Core to run on full fat .NET Framework 4.6.2- which was initially communicated as being On Purpose – move to Core or stay on old ASP.NET. This – of course – alienated a majority of the .NET community whose legacy code and legacy licensing pay for all this innovation were mightily upset and within several hours – a new story emerged stating that the incompatibility is temporary. The core developers, ahem, in the ASP.NET Core team, are unrepentant however.

The next flamewar had to do with F#. This is actually the point. Mark Rendle said he preferred C# to F# which caused outrage and he didn’t back down when all the heavy hitter F# evangelists came out to explain that F# can do anything and isn’t fringe at all. 

They are both right, and the problem still is that despite the big words, Microsoft won’t spend the £50 it would cost to have template parity between F# and C#.

Anyway – Build 2017 also featured Mass Torgersen weighing in on F#.

n Habits of a successful developer

I thought I was going to write one of those listicles just to get going as I have posted nothing for half a year. Recent developments have made me take stock and figure out what certain people have taught me while working with them and what I should try and learn from them going forward. I will not cover the basics of TDD, vim vs Emacs, tab vs spaces or any of that. I will assume you write good tests and create largely correct, well structured code that your coworkers can understand clearly.  I will just address things you can do right now – outside of the actual coding – to be the best you can be.

1. Go home at the end of the day

This isn’t a new lesson, but it is important to note again. Do not give the company any more of your time than you agreed when you signed on. You may love the company and the management, but you are not doing yourself any favours by spending too much time in the office. You may think you get more stuff done, but what I have learned is that you can get more done in 8 hours per day than most people do in 9 or 10, but it takes some hard work and focus. In the other points below I’ll try and identify some of the tricks these people use and see if I can perhaps pick up on those I’ve yet to implement myself.

Another reason I brought up this topic is that I have recently seen people fall into the trap of giving their life to the company. If you own equity and have a chance of a real upside that may be a trade-off worth making, but if you are a lowly employee, even if you have option rather than stock, it is highly unlikely that the arrangement is going to pay back time lost from seeing your family or even just resting to be fit-for-fight the next day. The company will never love you back – it cannot.

Even with equity, think about it – you wouldn’t cut an employee any slack that had worked themselves to the bone and after a while started making serious mistakes. Miss a client meeting due to oversleeping after an all-nighter in the office? Starting to create more bugs than they fix? Maybe started yo act bitterly in the office when interacting with coworkers due to the asymmetric workload this individual had voluntarily taken upon him- or herself? The problems and even the discord being sown in the workplace must eventually be addressed despite the employee having put in enormous hours for the company. I’m saying there is a  way to overwork yourself out of a job, which probably nobody in the company wants to go through and as an employee it is bound to be a bitter experience.

So – given the potential productivity and longevity of people that stay within their normal hours and the fact that they get to go home and chill with the family – this is the course of action I recommend..

2. Prefer early mornings to evenings regarding extracurricular activities

This is something I could be better at, but starting out at 5am if you want to do something extra curricular such as blogging or trying out a new language or technology is extremely effective. It is exactly like going out for a run in that a) I haven’t done it very often, but often enough to know that b) the hard bit is just getting started, and c) it is fantastic as you do it and notice how much progress you are making.

3. Never leave a question unasked

When you hammer out details about a piece of code about to be written – never leave a question unaddressed. Sometimes people hang back and assume that all edge cases are handled and that there are no more loose ends.

  1. Do we have everybody here that we need to flesh out this story?
  2. What is the expected outcome of the feature?
  3. What is the expected input?
  4. How will we handle untrusted input?
  5. Security concerns?
  6. Usability?
  7. How do we present errors?
  8. Will the stakeholders present, yes I was serious about 1, accept a solution that allows us to write less code?
  9. What is the lowest level at which we can automatically test the acceptance criteria?
  10. How do we deploy the feature?
  11. How do we monitor it?
  12. Do we need to produce any additional deliverable (yes, docs, manuals)?

The biggest way you can save time and get to go home on time is by not making mistakes, and one way to not make mistakes is to know that you are building the right thing the first time. Not advocating a Big Design Up Front, just a Right-Sized Discussion Just In Time.

4. Be the one that takes notes at design meetings

After asking the right questions-volunteer to do the dirty work such as updating ticketing systems, to make sure none of the information you are just about to use to write code is lost on the way. Documentation is often a waste, but this bit – details about the acceptance criteria for the feature or bit of code you are about to write is actually useful for a while, at least until the code is in production later today or tomorrow.

5. Maintain standards in terms of tooling and infrastructure

Keep your house in order. Don’t have your development machine behind on patches, behind on OS versions, on old development tools or in a state where you and or a coworker cannot be immediately productive. I have struggled with this as I for a while as I recently out of stubbornness tried to run a Linux desktop in anger. I thought 2016 would be the year of the Linux desktop, and in a lot of ways it was. Debian feels very natural for a Windows user. For chef, Javascript, even some PowerShell I did fine and  was productive. However since most of my work is in C# on .NET  I had to employ all kinds of other ways of running Visual Studio on VMs, on a laptop, or wherever which was annoying to everybody. Thankfully once I lost patience, thanks to my efforts in scripting, I had new Windows environment running directly on the metal set up in hours.

Do not let broken builds stay broken. If tests are flaky-  address that, either by replacing the tests with more robust ones, or remove them completely – but do put yourself in a position where any build failure is probably legitimate and is resolved immediately.

Constantly challenge the automation – do you need it? Is it over-engineered? Does it cover as much as it needs? Is it flexible or is it brittle?

6. Be helpful

Be ready to talk to anybody in the company that has questions about what you do. Pretend like you have boundless energy (which, to be fair you probably do since you now go home on time everyday). Even parts of the organisation that for historical reasons doesn’t have much faith in development/engineering (yes, that happens everywhere). Be there, answer stupid questions, insinuant questions and honest questions with a smile or at least a reasonable facsimile. Try and note down any specific complaints and welcome your critics to sit in when you elaborate stories regarding their favourite topic in the future.  If you are prepared to do some internal promotion you will be trusted in the rest of the company and liked by your colleagues who probably avoid those people like the plague.

Don’t arm yourself with headphones and plug away leaving your more junior colleagues stranded if they ave any questions – the total productivity of the team isn’t helped by you being in the zone if at the same time three people are struggling with something that you could have spotted right away.If you really do need to be alone to solve something, book a meeting room or something, get out of the landscape/team room.

If a couple of people have questions about anything you are doing, offer to do a brown bag on it, send out invites and see what the traction is. If you create a culture of curiosity and willingness to learn the company will make money and everybody will appreciate your effforts. Myself I have known that these things are useful and peple find them interesting, but it is only the brownbags or lunch & learn sessions that actually get scheduled and actually happen that are beneficial, the ones you ponder quietly to yourself but never actually set up are worthless. Take action.

7. Interact with peers outside of your company

Now, this seems to fly in the face of that Go home at the end of the day-bit, but this benefits mostly you as a developer and only secondly your employer. There are meetups and user groups in loads of places and you should find some and go there. This is an item where I really need to improve. Especially if you are involved in a technology that is quickly evolving, such as the language Elixir has been over the last couple of years, swapping war stories to the extent your NDAs will allow can be quite useful. Any piece of new discovery that you can share can benefit the local community and in turn you can have some of your queries addressed. It is a very good way to figure out how much of advertised technologies actually get used, and in what way and can thus help you correctly judge what new technologies are worth looking into to solve business problems at work.

Right, so for this listicle n appears to equal seven. Do you have any more traits of successful developers you have noticed that you would recommend, or just stuff that you do that is awesome and that we all are fools if we don’t emulate right now? Feel free to share.

Retention policy and crypto

I just deleted an old post because I re-read it and I was attempting my own crypto on config files instead of using DPAPI. I reserve the right to delete old posts if they turn out to be complete bollocks.

Just to show how you encrypt an app config file on a machine where you do not have IIS installed and cannot use the traditional aspnet_regiis command-line tool that your first googlebing will tell you all about – I give you the below piece of code.

Note that you need to encrypt the file on the target machine as DPAPI is machine specific, so there will be a brief moment when the file is on disk in clear text which is a basic flaw of the entire DPAPI concept, but at least you are not rolling your own crypto.

static int Main(string[] args)
{
    if (args.Length != 1)
        Console.Error.WriteLine("Wrong number of arguments.\r\n{0} <configfile_to_encrypt>", GetExeName());

    return EncyptAppSettings(args[0]);
}

private static int EncyptAppSettings(string pathToFile)
{
    if (!File.Exists(pathToFile))
         return LogFatalError(string.Format("Executable {0} not found", pathToFile), 2);
    if (!File.Exists(pathToFile + ".config"))
         return LogFatalError(string.Format("Config file {0} not found", pathToFile), 3);

   var configuration = ConfigurationManager.OpenExeConfiguration(pathToFile);
   var appSettings = configuration.GetSection("appSettings") as AppSettingsSection;
   appSettings.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
   appSettings.SectionInformation.ForceSave = true;
   configuration.Save();
   return 0;
}

private static int LogFatalError(string message, int exitCode)
{
    Console.Error.WriteLine("{0} failed: {1}", GetExeName(), message);
    return exitCode;
}

private static string GetExeName()
{
    return Process.GetCurrentProcess().ProcessName;
}

 

More about configs while developing

In my previous post I discussed what you can and shall automate in terms of your development environment and I speculated in one place about what one ought to do with the web.config file in Visual Studio. I have made a script that uses my local chef repo to configure the configuration files using chef-zero and clearly that works. It is a bit messy -but it works. This was where I was when I wrote the last blog post containing my speculation.

Getting further – to an actually workable solution – I have run into what seems like a brick wall. The complexity of using chef-zero seems to need some refactoring, but the biggest problem is maintaining the templates. Nuget keeps editing binding redirects in web.config and it would be nice if those changes could be applied to the erb files. Since this is how ASP.NET works, the source web.config combined with per-environment transforms is highly favoured because it has the lowest maintenance burden. There are a number of plugins that supports this workflow even for EXE projects and other things.

My problem with those is that they violate a basic principle of keeping configuration away from the source repository. Also, I’m happy with chef and I don’t want to replace its templating engine with web.config transforms so trying to adhere to the concept of running the same setup in development as in production makes it difficult unless I can find a way to dynamically update the erb file.