What’s in a Job Title?

The companies I’ve worked for so far have always had some kind of hierarchical organisation. For instance, you start off as a Software Developer, then you are promoted to Senior Software Developer, and so on. However, I’m aware that there are other companies which prefer to have a flat hierarchy, and keep job titles to a minimum.

Well, what’s in a job title, anyway? Does it really matter what your job title is?

Motivation

There’s this scene from the film “Kingdom of Heaven“, where the main character (Balian) selects a peasant and knights him on the spot. The bishop is horrified.

Bishop: “Who do you think you are? Will you alter the world? Does making a man a knight make him a better fighter?

Balian: “Yes.”

You see, making a man a knight doesn’t give him any special power. But he knows that he is now a knight. This means that he is responsible to uphold his duties as such.

On the job, it’s pretty much the same. Becoming a Senior Software Developer does not make you any more able in your work than turning 18 years old makes you suitable to drive. But it does put you into a bag of a handful of accomplished and trusted developers, and as such you will work a lot harder to show that you deserve that title. It also means that you will most likely take more initiative in your work, and go outside the scope of your individual duties by guiding others in performing theirs.

A little recognition goes a long way in motivating individuals.

Categorisation

Some companies offer the excuse that their employees have the same job titles or salaries in the interest of fairness, so that they are all treated equally.

Such companies should wake up and realise that people aren’t all equal. Some work harder than others. Those people do not deserve to be lumped in the same boat as those who do a miserable job.

The CV Factor

When an employee applies for a job, having “Senior Software Developer” looks a lot better than “Software Developer”.

It is true that job titles mean different things from one company to another. In some companies, a Software Developer is merely responsible for coding; while in others, he might actually be managing a whole project. Hiring companies should ideally look beyond the job title and ask about the roles that the candidate played in his employment.

However it is also true that companies and recruitment agencies receiving a lot of job applications often resort to simple filtering at face value in order to reduce the number of applications.

Consider this: individual A has been a loyal and hard-working Software Developer for 20 years, and his company never gave him a promotion. His friend, individual B, has been promoted to Senior Software Developer and then Lead Developer, even though his skills and responsibilities are less than those of individual A. When recruiters look at their CVs at face value, who will they prefer? What will they think about individual A when they see that he’s had the same role for 20 years?

VS2015 Preview: NuGet 3 Preview

Well, what do you know. It seems like NuGet’s been to the hairdresser recently.  In fact, in Visual Studio 2015 you’ll find the preview of NuGet 3.0, which looks like this:

vs2015-nuget3-layout

It’s obviously changed quite a bit from the version we use today, which for the sake of comparison is this:

vs2015-old-nuget

The most obvious thing to notice is that NuGet is now a first-class citizen with its own page in Visual Studio, rather than being a little modal window. There are other layout improvements you’ll notice, such as the fact that they’ve done away with the separation between installed, installable and updatable packages. In fact, the new NuGet experience is a unified one in which you can filter the packages you want to see: All, Installed, or Update Available.

Usability is not all that is being improved in NuGet 3.0. In fact, there are a bunch of new features that weren’t in NuGet before. One that I am very happy to see is the ability to select the package version to install, rather than having to resort to the Package Manager Console to install specific versions.

Another really cool feature is that of package consolidation. Have you ever had something like 4 different versions of JSON.NET across your solution, and then had to painfully manually converge them into a single version? NuGet 3 allows you to consolidate different versions of the same assembly pretty easily. Just select the version you want, and select the “Consolidate” action, and click the “Consolidate” button:

vs2015-nuget3-consolidate

There are also a few other features, such as a Preview button showing what actions will be taken when you execute a change, and a couple of advanced options. For full details on what’s new, check out the official announcement.

Oh, and just in case you’re curious… that funny thingy next to the Search box that looks like a ship’s wheel is actually supposed to be a gear icon, because it takes you into the NuGet settings.

Simple Validation with Data Annotations

Data Annotations are attributes which you can apply to properties in order to specify validity constraints, such as required fields, string lengths, or numeric ranges. They are quite useful to use as part of bigger frameworks such as ASP .NET MVC or WPF. This article shows very simple examples of their usage in a console application.

Adding Data Annotations

In order to add data annotations, you’ll first need to add a reference to System.ComponentModel.DataAnnotations.dll. Once that is done, add a simple class and decorate the properties with attributes from that namespace:

    public class Person
    {
        [Required]
        public string Name { get; set; }

        [Range(18, 60)]
        public int Age { get; set; }
    }

There are many predefined attributes you can use, and it is also possible to create your own by creating a class that derives from ValidationAttribute.

In this example we’re using the RequiredAttribute, which causes validation to fail if the string is null, empty, or whitespace; and the RangeAttribute, which requires a number to be within a specified range.

Property Validation

We can validate a single property on our Person object by using the Validator.TryValidateProperty() method:

        static void RunValidateProperty(string value)
        {
            var person = new Person();

            var context = new ValidationContext(person) { MemberName = "Name" };
            var results = new List<ValidationResult>();
            var valid = Validator.TryValidateProperty(value, context, results);
        }

In order to do this, we need to supply three things:

  • A ValidationContext which specifies the property to validate and the object it belongs to;
  • A collection of ValidationResult, which is a glorified error message; and
  • A value for the property that will be checked for validity.

The fact that any value can be checked for a given property makes TryValidateProperty() particularly useful to use in property setters, such as in this example.

Let’s see what happens when we try validating the Name property (remember, it’s marked as Required) with a value of null:

dataannotationsintro-required-null

In this case TryValidateProperty() returned false, and a ValidationResult was added to the results collection with the message “The Name field is required.”.

Now if we give it a valid string, it behaves quite differently:

dataannotationsintro-required-valid

TryValidateProperty() returned true, and there are no ValidationResults to report.

Object Validation

While validating a single property is quite useful (e.g. while a particular field is being edited), it is often useful to validate every property in a class (e.g. when submitting data in a form).

This functionality is provided thanks to Validator.TryValidateObject():

        static void RunValidateObject()
        {
            var person = new Person();

            var context = new ValidationContext(person);
            var results = new List<ValidationResult>();
            var valid = Validator.TryValidateObject(person, context, results);
        }

Let’s try it out and see what happens:

dataannotationsintro-validateobject-requiredonly

You’ll notice that validation failed and we got a ValidationResult for the Name field. But we also have an Age property, which is supposed to be between 18 and 60, and yet it still has its default value of zero. Why didn’t that property fail validation too?

See, this happens due to an awkward default behaviour of TryValidateObject(), which by default only validates fields which are marked as Required. In order to factor in other attribute types in the validation, you need to use a different overload of TryValidateObject() which takes a boolean at the end, and set it to true:

        static void RunValidateObject()
        {
            var person = new Person();

            var context = new ValidationContext(person);
            var results = new List<ValidationResult>();
            var valid = Validator.TryValidateObject(person, context, results, true);
        }

And now, the result is much more reasonable:

dataannotationsintro-validateobject-allfields

Limitations

Using attributes for validation is a very useful concept. It allows you to simply attach metadata to properties, and let the validation logic consume those attributes when necessary.

However, data annotations also carry with them the limitations of attributes. Among these is the fact that attributes can only have static values, and so it is not possible to incorporate logic into them (e.g. to have them depend on the value of another property).

Source Code

Check out the source code for this article at the Gigi Labs BitBucket repository.

Streaming Data with ASP .NET Web API and PushContentStream

This article explains how you can subscribe to a data stream and receive data pushed spontaneously by the server, using the ASP .NET Web API. It is intended as nothing more than a learning exercise. Technologies such as WebSockets, SignalR, WCF or even plain sockets may be more suitable for this kind of thing.

Update 2015-03-14: Full source code for server and client applications is now available.

The Server

Our Web API is going to allow clients to subscribe to a service which will send the price of… something every two seconds. To start off, you will need to create a new Web project with a Web API component, and create a new controller (which I called PriceController).

Then, it is simply a matter of sending back a response whose content is a PushStreamContent:

        [HttpGet]
        public HttpResponseMessage Subscribe(HttpRequestMessage request)
        {
            var response = request.CreateResponse();
            response.Content = new PushStreamContent((a, b, c) =>
                { OnStreamAvailable(a, b, c); }, "text/event-stream");
            return response;
        }

The odd arguments in the lambda are a workaround for an unfortunate ambiguity between PushStreamContent constructors in Web API 2.

The implementation for OnStreamAvailable() is pretty simple:

        private void OnStreamAvailable(Stream stream, HttpContent content,
            TransportContext context)
        {
            var client = new StreamWriter(stream);
            clients.Add(client);
        }

We’re simply wrapping a StreamWriter around the stream, and then keeping it in a ConcurrentBag called “clients”.

The last thing we need is a timer to periodically send the price data. This is what the timer’s Elapsed event looks like:

        private async static void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            var price = 1.0 + random.NextDouble(); // random number between 1 and 2

            foreach (var client in clients)
            {
                try
                {
                    var data = string.Format("data: {0}\n\n", price);
                    await client.WriteAsync(data);
                    await client.FlushAsync();
                }
                catch(Exception)
                {
                    StreamWriter ignore;
                    clients.TryTake(out ignore);
                }
            }
        }

Every 2 seconds, a random number between 1 and 2 is selected, and is sent to all subscribed clients. The data is sent based on the format for Server-Sent Events.

If an exception occurs, then the client is effectively unsubscribed by removing it from the ConcurrentBag. This is necessary because, as Henrik Nielsen states in this discussion:

Detecting that the TCP connection has been reset is something that the Host (ASP, WCF, etc.) monitors but in .NET 4 neither ASP nor WCF tells us (the Web API layer) about it. This means that the only reliable manner to detect a broken connection is to actually write data to it. This is why we have the try/catch around the write operation in the sample. That is, responses will get cleaned up when they fail and not before.

PriceController – Full Code

All you need to get the PriceController working are the member variable declarations and the static constructor which initialises them. I’m providing the entire class below so that you can just copy it and get up and running.

    public class PriceController : ApiController
    {
        private static ConcurrentBag<StreamWriter> clients;
        private static Random random;
        private static Timer timer;

        static PriceController()
        {
            clients = new ConcurrentBag<StreamWriter>();

            timer = new Timer();
            timer.Interval = 2000;
            timer.AutoReset = true;
            timer.Elapsed += timer_Elapsed;
            timer.Start();

            random = new Random();
        }

        private async static void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            var price = 1.0 + random.NextDouble(); // random number between 1 and 2

            foreach (var client in clients)
            {
                try
                {
                    var data = string.Format("data: {0}\n\n", price);
                    await client.WriteAsync(data);
                    await client.FlushAsync();
                }
                catch(Exception)
                {
                    StreamWriter ignore;
                    clients.TryTake(out ignore);
                }
            }
        }

        [HttpGet]
        public HttpResponseMessage Subscribe(HttpRequestMessage request)
        {
            var response = request.CreateResponse();
            response.Content = new PushStreamContent((a, b, c) =>
                { OnStreamAvailable(a, b, c); }, "text/event-stream");
            return response;
        }

        private void OnStreamAvailable(Stream stream, HttpContent content,
            TransportContext context)
        {
            var client = new StreamWriter(stream);
            clients.Add(client);
        }
    }

Browser Support

To test the PriceController, you could consider firing up a browser and have it do the subscription. However, I’ve found that browser support for this is pretty crap. For instance, Firefox thinks the event stream is something you can download:

pushstreamcontent-firefox

So does IE:

pushstreamcontent-ie

Chrome actually manages to display data; however it sometimes only displays part of a message (the rest is buffered and displayed when the next message is received), and has a habit of giving up:

pushstreamcontent-chrome

When I originally saw these results, I thought I had done something seriously wrong. However, I realised this was not the case when I wrote a client in C# and found that it worked correctly. In fact, let’s do that now.

The Client

This client requires the latest Web API Client Libraries from NuGet. Since writing async Console applications can be a bit messy (see a workaround if you still want to take the Console direction), I wrote a simple WPF application. This just has a “Subscribe” button, and a TextBox which I named “OutputField”.

This is the code that does the subscription and streams the prices from the PriceController:

        private async void SubscribeButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.client == null)
            {
                this.client = new HttpClient();
                var stream = await client.GetStreamAsync("http://localhost:1870/api/Price/Subscribe");

                try
                {
                    using (var reader = new StreamReader(stream))
                    {
                        while (true)
                        {
                            var line = await reader.ReadLineAsync() + Environment.NewLine;

                            this.OutputField.Text += line;
                            this.OutputField.ScrollToEnd();

                        }
                    }
                }
                catch (Exception)
                {
                    this.OutputField.Text += "Stream ended";
                }
            }
        }

Since we’re dealing with a stream, we’re using GetStreamAsync() to talk to the Web API rather than the usual GetAsync(). Then, we can read it as we would any other stream.

And in fact, it works pretty nicely:

pushstreamcontent-wpfclient

Related Links

Roslyn moves to GitHub

For the past several weeks I’ve been writing about the new features in C# 6 and Visual Studio 2015, which are facilitated by the .NET Compiler Platform, known as Roslyn.

Roslyn’s Codeplex homepage has hosted the project’s source code and information for a while.

However, over the past few days, the following announcement was posted on Roslyn’s Codeplex homepage:

This coming week (Wednesday is the target, Thursday at the latest) we will be moving the Roslyn Project to live under GitHub, joining the rest of the .NET team over there.

Details:

  • This will be a simple switch – turn off CodePlex, turn on GitHub. You’ll be able to see our checkins on GitHub that same day, for example.
  • Any of your pull requests to our project in GitHub will pile up for a couple of weeks, because we are going to take the opportunity to also streamline our (currently very complex) pull request process – yeah! We’ll reopen in a couple weeks with a much easier process. That, combined with us switching to use Git internally as well at the same time (!), means many fewer moving parts and gets us much closer to the same environment you’ll be using on Roslyn code. It will be so worth it.
    • At this point, I’d advise holding off on any requests sent to CodePlex, and save them for GitHub instead.
  • We’ll be using GitHub Issues for both discussions and bugs after the switch.
  • We will try to move over outstanding bugs from CodePlex, but this is the trickier part of the plan. Stay tuned.
  • We will also do our best to preserve check-in history.
  • We will be under the .NET Foundation over there, as the “Compilers” project.

We will update this page with the forwarding information when the switch is complete mid-week. I’ll also be blogging about some of the additional OSS work we’re about to embark on in a week or two.

–Matt Gertz–*
Group Software Engineering Manager, “Roslyn”

It appears that the move is now complete, and you can find all the latest on Roslyn at its new home on GitHub.