Interesting links of the week (2019 #5)

Here are some interesting articles and blog posts I’ve run into over the last week (January 27 to Feb 3, 2019):

Technology

Non-Technology

Random

Interesting links of the week (2019 #4)

Here are some interesting articles and blog posts I’ve run into over the last week (January 21 to January 27, 2019):

Technology

Non-Technology

Random

Interesting links of the week (2019 #3)

Here are some interesting articles and blog posts I’ve run into over the last week (January 14 to January 20, 2019):

Technology

Non-Technology

Random

Interesting links of the week (2019 #2)

Here are some interesting articles and blog posts I’ve run into over the last week (January 7 to January 13, 2019):

Technology

Non-Technology

Random

Git with a new project

Not too long ago, a friend of mine said this on twitter:

I hate when I create a repo in GitHub and start a README file. Than when I work on code locally that I want to push to that repo, I can never figure out how to do it so I end up deleting the remote and starting from scratch.

I responded with:

Create repo on github. Add your readme.

Clone.

Do local work. 🙂

I started thinking to back when I was starting with git and some of the struggles I had, especially when starting a new project.

My current workflow is to start whatever project I’m working on locally, commit locally, then create an empty repo on GitHub and push to it.

If I was creating a new dotnet application, here are the steps I’d take:

> mkdir MyTestApp
> cd MyTestApp
MyTestApp> dotnet new console
MyTestApp> vim README.md   <- add some content

Copy a .gitignore file from another, similar project

MyTestApp> git init
MyTestApp> git add .
MyTestApp> git commit -m “initial commit”

Head to Github and create an empty repo named MyTestApp. I don’t NOT let github add a README or gitignore file since I’ve already done that locally.
GitHub_NewRepo1.png

MyTestApp> git remote add origin git@github.com:mjeaton/MyTestApp
MyTestapp> git push origin master

But, back to the original question–what happens if you create the empty repo with the README, but you’ve also started a README locally?

In this case, I’ll create my repo first

Head to Github and create an empty repo named MyTestApp2. This time, I will let github create a README.
GitHub_NewRepo2.png

> mkdir MyTestApp2
> cd MyTestApp2
MyTestApp2> dotnet new console
MyTestApp2> vim README.md   <- add some content
MyTestApp> cd ..
> git clone git@github.com:mjeaton/MyTestApp2

Doing that should have given an error that the destination path already exists:

fatal: destination path ‘MyTestApp2’ already exists and is not an empty directory.

That makes sense, but if you find yourself with a local working copy AND a GitHub repo and you want to keep the contents of both and link your local stuff to the GitHub repo?

From your project folder, do the following:

MyTestApp2> git init
MyTestApp2> git remote add origin git@github.com:mjeaton/MyTestApp2

At this point, you have connected your local directory to github.

What happens if you try to add and push now?

MyTestApp2> git add .
MyTestApp2> git commit -m “initial commit”
MyTestApp2> git push origin master

You get a big error, right?

To github.com:mjeaton/MyTestApp2
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to ‘git@github.com:mjeaton/MyTestApp2’
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: ‘git pull …’) before pushing again.
hint: See the ‘Note about fast-forwards’ in ‘git push –help’ for details.

This means “origin” is ahead of your local repo; GitHub has newer files than what is on the local computer. To fix it, you need to pull from GitHub.

MyTestApp2> git pull origin master

You should see an error like this:

fatal: refusing to merge unrelated histories

I have history on GitHub and history locally and somehow have to get things reconciled. Ok, so how do I get past that? Simple.

MyTestApp2> git pull origin master –allow-unrelated-histories

Running that command works, BUT now I’m told there’s a merge conflict. Since we made changes to README.md in both places, I expected this.

* branch master -> FETCH_HEAD
Auto-merging README.md
CONFLICT (add/add): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

All you need to do is use your merge tool/diff tool of choice and take care of the conflict.

MyTestApp2> git mergetool

As soon as I take care of the conflict, I can commit the change and push to master. Everything is now at a point where I can start my normal workflow using git.

Summary

I started by describing my process for starting a new project that uses GitHub: create the repo, clone it, start working. I find this is the most straightforward way to get a new project up and running.

After that, I talked a little bit about how to handle those times when a repo is created on GitHub AND locally, with changes in both places. I covered at least one method to handle the conflicts that arise without deleting the project and starting over, but there are others.

Interesting links of the week (2019 #1)

Here are some interesting articles and blog posts I’ve run into over the last week (December 31, 2018 to January 6, 2019):

Technology

Non-Technology

Random

Interesting links of the week (12/24 – 12/30, 2018)

Interesting links of the week (12/24 – 12/30, 2018)

Here are some articles and blog posts I’ve run into over the last week that I found interesting.

Technology

Non-Technology

Random

Interesting links of the week (12/17 – 12/23, 2018)

Interesting links of the week (12/17 – 12/23, 2018)

Here are some articles and blog posts I’ve run into over the last week that I found interesting.

Technology

Non-Technology

Random

Interesting links of the week (12/10 – 12/16, 2018)

Interesting links of the week (12/10 – 12/16, 2018)

Here are some articles and blog posts I’ve run into over the last week that I found interesting.

Technology

Non-Technology

Random

Exercises for Programmers – Weather Checker in C#

Update: This post is part of the Second Annual C# Advent.

Along with koans and katas, several books have helped me knock the rust off after a recent two-year stint as a non-coding team leader. One of the exercises in Brian P. Hogan’sExercises for Programmers: 57 Challenges to Developer Your Coding Skills” jumped out at me recently, so I decided to tackle it.

At its simplest, exercise 48 – Grabbing the Weather is a relatively short exercise that asks you to use the OpenWeatherMap API and display weather information.

I decided to create a .NET Core console application. I started out at my beloved command line:

Weather_new.png
With the application created, I need to make sure it’s in git. It’s not that this is a hugely important application, it’s more about practicing good habits with source code control.

After initializing git, I copied an existing .gitignore file from another .NET project and then added my files and did an initial commit.

Weather_git.png

At this point, it’s a toss up whether to use Vim, VS Code or Visual Studio, but in this case, I used Visual Studio since it’s what many people are using AND because I have the VsVim extension installed. Best of both worlds!

The requirements for the exercise:

Using the OpenWeatherMap API at http://openweathermap.org/current, create a program that prompts for a city name and returns the current temperature for the city.

Easy enough! The first thing I need to do is visit https://openweathermap.org/current and either sign up or sign in. Sign up is free and takes about a minute. Once you have an account, you’ll need an API key. An account has a default key, so you can simply grab the key and hold on to it OR create a new one. Keep in mind, it might take some time for the key to become active.

I want my console application to call a service that will hide all the details of fetching the weather. Who knows, at some point, I may want to change weather providers and using a service should insulate the client (the console application) from internal code changes.

Instead of a city name, I want my weather service to take in a zip code and return back the a structure with all the data the OpenWeatherMap API returns.

public interface IWeatherFetcher
{
CurrentWeather GetCurrentWeather(string zipCode);
}

In Main, the call will look something like this:

static void Main(string[] args)
{
Console.WriteLine(“Mike’s Weather App”);

IWeatherFetcher wf = new WeatherFetcher();
var currentWeather = wf.GetCurrentWeather(“49036”);

Console.ReadLine();
}

The service:

public CurrentWeather GetCurrentWeather(string zipCode)
{
var json = RunAsync(“your API key”, zipCode).GetAwaiter().GetResult();
return JsonConvert.DeserializeObject<CurrentWeather>(json);
}

private HttpClient client = new HttpClient();
private async Task<string> RunAsync(string key, string zipCode)
{
client.BaseAddress = new Uri(“http://api.openweathermap.org&#8221;);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/json”));

var result = “”;
try
{
result = await GetWeatherAsync(key, zipCode);
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}

return result;
}

private async Task<string> GetWeatherAsync(string key, string zipCode)
{
var result = “”;
string url = $”/data/2.5/weather?q={zipCode}&units=imperial&appid={key}”;

HttpResponseMessage response = await client.GetAsync(url);
if(response.IsSuccessStatusCode)
{
result = await response.Content.ReadAsStringAsync();
} else {
// dump any errors to the screen
Console.WriteLine(response.ToString());
}
return result;
}

To get the CurrentWeather class, I took the original json that was returned and used a special feature in Visual Studio called “Paste JSON as Classes” found under Edit | Paste Special in Visual Studio.

CurrentWeather (the result of “Paste JSON as Classes”):

public class CurrentWeather
{
public Coord coord { get; set; }
public Weather[] weather { get; set; }
public string _base { get; set; }
public Main main { get; set; }
public int visibility { get; set; }
public Wind wind { get; set; }
public Clouds clouds { get; set; }
public int dt { get; set; }
public Sys sys { get; set; }
public int id { get; set; }
public string name { get; set; }
public int cod { get; set; }
}

public class Coord
{
public int lon { get; set; }
public float lat { get; set; }
}

public class Main
{
public float temp { get; set; }
public int pressure { get; set; }
public int humidity { get; set; }
public float temp_min { get; set; }
public float temp_max { get; set; }
}

public class Wind
{
public float speed { get; set; }
public float deg { get; set; }
}

public class Clouds
{
public int all { get; set; }
}

public class Sys
{
public int type { get; set; }
public int id { get; set; }
public float message { get; set; }
public string country { get; set; }
public int sunrise { get; set; }
public int sunset { get; set; }
}

public class Weather
{
public int id { get; set; }
public string main { get; set; }
public string description { get; set; }
public string icon { get; set; }
}

With all that in place, I can now make one more modification to my Main to display some data:

static void Main(string[] args)
{
Console.WriteLine(“Mike’s Weather App”);

IWeatherFetcher wf = new WeatherFetcher();
var currentWeather = wf.GetCurrentWeather(“49036″);

Console.WriteLine($”The temp in {currentWeather.name} is {currentWeather.main.temp}.”);

Console.ReadLine();
}

I can now display any of the information that’s returned. I have had to make a few adjustments to the generated classes because data types coming back didn’t necessarily match what was generated – for example, Wind.deg was generated as an int, but it comes back as a float. Easy fix, but it’ll take some debugging to get it all correct.

This was a fun exercise that took me about 30 minutes to complete and I still have a couple things to do like actually prompt for the city (or Zip Code). One tweak I made but didn’t really talk about it is the inclusion of the API key within the code. I’ll explain that in a follow-up post.

I hope you enjoyed this post! Oh, and check out the code on GitHub!