<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>2020-12 on Funky Si's Test</title><link>https://blog-test.funkysi1701.com/2020/12/</link><description>Recent content in 2020-12 on Funky Si's Test</description><generator>Hugo -- gohugo.io</generator><language>en-gb</language><managingEditor>funkysi1701@gmail.com (Simon Foster)</managingEditor><webMaster>funkysi1701@gmail.com (Simon Foster)</webMaster><lastBuildDate>Mon, 28 Dec 2020 00:00:00 +0000</lastBuildDate><atom:link href="https://blog-test.funkysi1701.com/2020/12/index.xml" rel="self" type="application/rss+xml"/><item><title>Set and achieve 2021 developer goals</title><link>https://blog-test.funkysi1701.com/posts/2020/goals-for-2021/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 28 Dec 2020 00:00:00 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2020/goals-for-2021/</guid><category term="Goals">Goals</category><description>&lt;p&gt;I didn&amp;rsquo;t make any goals for 2020, or if I did, I didn&amp;rsquo;t officially announce them. 2020 has been a hard year for all of us, 2021 is going to be better.&lt;/p&gt;
&lt;p&gt;Here are a few ideas for my goals for the year ahead.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Azure certification&lt;/li&gt;
&lt;li&gt;Mentoring&lt;/li&gt;
&lt;li&gt;F#&lt;/li&gt;
&lt;li&gt;Cosmos db/Mongo db&lt;/li&gt;
&lt;li&gt;Give a talk&lt;/li&gt;
&lt;li&gt;Mandlebrot Generator&lt;/li&gt;
&lt;li&gt;Pwned Pass Mobile App&lt;/li&gt;
&lt;li&gt;More time for me&lt;/li&gt;
&lt;/ol&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I want to get a certificate to show how much I know. The obvious area for this is Azure. I spend a lot of time playing with Azure, building and deploying to the platform I should be able to get certified in this area. I actually had an exam booked in 2020 but it was an in-person exam so was cancelled when Covid hit. I plan to sit the &lt;a href="https://docs.microsoft.com/en-us/learn/certifications/exams/az-900" target="_blank" rel="noopener noreferrer"&gt;foundation&lt;/a&gt;
exam in the first quarter of 2021 and I will take it from there.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I have had a few times recently where I have been reminded that I don&amp;rsquo;t have much experience working with others. Mostly because I work in a one-man development team so there are limited opportunities in the workplace. I have a few ideas to change this, but this is one of my top priorities for 2021.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&amp;amp; 4) My experience is very Microsoft and C# so I want to spend some time exploring and learning tech that is adjacent to this. A functional language like F# sounds like a good compliment to my existing skills and my data skills are also very SQL server so some document database skills would be a good place to spend some time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Doing a talk has been on my list for years. I am terrified of doing one and with everything online now I don&amp;rsquo;t know if that makes things easier or harder. I don&amp;rsquo;t think 2021 is going to be the year for this but maybe I will take baby steps towards this goal.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Twitter recently reminded me about watching a Mandlebrot generate one pixel at a time in the 1980s. I would love to explore the code used to generate them and how fast they currently are to produce.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;My Google play store Xamarin forms app that uses the HIBP API has less than 100 users and I am considering closing it down, especially as I pay a monthly fee for API keys. I haven&amp;rsquo;t really decided what to do, maybe I will spend some time improving it, maybe I will close it down, maybe I will build something else.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For many people 2020 has been a hard year, I am one of those.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Building a Twitter Clone</title><link>https://blog-test.funkysi1701.com/posts/2020/building-a-twitter-clone/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Tue, 22 Dec 2020 20:00:45 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2020/building-a-twitter-clone/</guid><category term="Twitter">Twitter</category><category term="Design">Design</category><category term="Architecture">Architecture</category><description>&lt;p&gt;I saw a tweet about building a twitter clone being harder than you would think. So this of course started me thinking how I would go about building something like that.&lt;/p&gt;
&lt;p&gt;Ok so where would I start? First a few assumptions.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Development by a lone developer ie me&lt;/li&gt;
&lt;li&gt;Tech stack will be dotnet and other tech I am familiar with&lt;/li&gt;
&lt;li&gt;Database backend, probably SQL Server but I might use table storage for cost reasons should I try and actually build this. However if I design this well this should be something that could be swapped out as the system grows&lt;/li&gt;
&lt;li&gt;User accounts on the system will be small as I can&amp;rsquo;t imagine anyone ever signing up. Why sign up to a social media platform with no users?&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="i-guess-the-next-question-is-what-is-twitter"&gt;I guess the next question is what is Twitter?&lt;a class="anchor ms-1" href="#i-guess-the-next-question-is-what-is-twitter" aria-label="Permalink: I guess the next question is what is Twitter?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A website that allows you to share 280 characters of text with your followers, allows you to follow other users updates and allows other user to follow your updates.&lt;/p&gt;
&lt;p&gt;It also has an API that allow you to do almost everything that you can with the website.&lt;/p&gt;
&lt;p&gt;Then there are of course mobile apps to consider but I am going to assume this is out of scope, however assuming a good enough API then this shouldn&amp;rsquo;t be a problem for future development.&lt;/p&gt;
&lt;h2 id="first-steps"&gt;First Steps&lt;a class="anchor ms-1" href="#first-steps" aria-label="Permalink: First Steps"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To start off with I would concentrate on the API, and then build a web client that makes use of the API.&lt;/p&gt;
&lt;p&gt;So what would my MVP (minimum viable product) be?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;User can authenticate with my API to get a token which allows access to other API endpoints&lt;/li&gt;
&lt;li&gt;User can create a tweet&lt;/li&gt;
&lt;li&gt;User can view own tweets&lt;/li&gt;
&lt;li&gt;User can view tweets of another user&lt;/li&gt;
&lt;li&gt;User can view tweets in their timeline&lt;/li&gt;
&lt;li&gt;User can follow/unfollow other users&lt;/li&gt;
&lt;li&gt;User can search for other users&lt;/li&gt;
&lt;li&gt;User can search for keywords in tweets&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I think that is probably sufficient to build my MVP for the API.&lt;/p&gt;
&lt;p&gt;An interesting side note is that I could use the OAuth Twitter authentication to allow users to login to my twitter clone with the real twitter login details. However this makes no sense to me as we are essentially adding a dependency on the real twitter.&lt;/p&gt;
&lt;p&gt;So what would I use for the frontend? I would start off with a Client Side Blazor frontend. Once I had a proof of concept that worked, I would think about styling and adding the UI elements that are familiar to twitter users.&lt;/p&gt;
&lt;p&gt;The beauty of Client Side Blazor is that I can host cheaply in azure storage and distribute around the world via a CDN.&lt;/p&gt;
&lt;p&gt;Due to the high number of times that follower and following count and other stats are queried I would consider storing these in the database and include a regular job to recalculate them so they don&amp;rsquo;t get out of sync with the data.&lt;/p&gt;
&lt;p&gt;Having said all of this I am very tempted to fire up Visual Studio and see how far I get, and what problems I encounter along the way.&lt;/p&gt;</description></item><item><title>#005: Twitter Cards</title><link>https://blog-test.funkysi1701.com/posts/2020/005-twitter-cards/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Sat, 12 Dec 2020 20:00:45 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2020/005-twitter-cards/</guid><category term="Twitter">Twitter</category><description>&lt;p&gt;It has been a bit of a mad week this week. I joined a new team so lots of time learning what&amp;rsquo;s what and also being pulled in two directions as usual demands come through on top of that.&lt;/p&gt;
&lt;p&gt;My blog runs on Blazor and I have been making use of JavaScript interop to update the html headers and update the page title to match the blog post article. This works great, I load the page and check the headers and they were saying what I wanted.&lt;/p&gt;
&lt;p&gt;The problem was I wanted to add tags for &lt;a href="https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started" target="_blank" rel="noopener noreferrer"&gt;twitter cards&lt;/a&gt;
This means that when I paste a link to my blog on twitter you get a nice preview and pic of me in the tweet. This was not working at all even though I had the correct headers.&lt;/p&gt;
&lt;p&gt;I eventually figured out that the problem was the fact I was using JavaScript to update my headers after the page had been initially loaded. Twitter was fetching my page before these headers got added and therefore couldn&amp;rsquo;t see the twitter card headers.&lt;/p&gt;
&lt;p&gt;My solution was to use invalid html. Not ideal but it works. I added the required html tags in the body of my page using Blazor/C# instead of using JavaScript to add them into the header. Twitter appears to not be fussy in finding them in the wrong place.&lt;/p&gt;
&lt;p&gt;Twitter provides a validator tool at &lt;a href="https://cards-dev.twitter.com/validator" target="_blank" rel="noopener noreferrer"&gt;Twitter Card Validator&lt;/a&gt;
which my website now passes.&lt;/p&gt;
&lt;p&gt;Not much else to say this week, apart from I am missing Visual Studio and C#, I have been mostly using VS Code on Linux and looking at php which isn&amp;rsquo;t as much fun as my usual day job.&lt;/p&gt;</description></item><item><title>Weekly Update #004</title><link>https://blog-test.funkysi1701.com/posts/2020/weekly-update-004/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Sun, 06 Dec 2020 20:00:45 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2020/weekly-update-004/</guid><category term="SQL">SQL</category><description>&lt;p&gt;I use sp_send_dbmail to send results of sql queries by email to business users. Recently an issue was raised that data was being cut off after 255 characters. To fix this I added @query_no_truncate = 1, however this stopped the column headings from being included. No idea why you can&amp;rsquo;t have all the data and column headings but there you have it.&lt;/p&gt;
&lt;p&gt;What I am doing now is running 2 queries, one to get the headings, and one to get the data. In theory you should be able to combine them with a Union however you then have datatype issues for non text columns so I gave up with that idea.&lt;/p&gt;
&lt;p&gt;My results have 60 something columns (don&amp;rsquo;t ask its for a data import into a third party system!) so I am not typing them all out. I can shove query results into a temporary table and then execute to get a list of columns.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; name
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; tempdb.sys.columns
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; object_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; object_id(&lt;span style="color:#e6db74"&gt;&amp;#39;tempdb..#TempTable&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However I need my list to be horizontal so I can use as column headers. I can use dynamic SQL and a pivot to flip them round.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;DECLARE&lt;/span&gt; &lt;span style="color:#f92672"&gt;@&lt;/span&gt;cols &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; NVARCHAR(&lt;span style="color:#66d9ef"&gt;MAX&lt;/span&gt;), &lt;span style="color:#f92672"&gt;@&lt;/span&gt;query &lt;span style="color:#66d9ef"&gt;AS&lt;/span&gt; NVARCHAR(&lt;span style="color:#66d9ef"&gt;MAX&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#f92672"&gt;@&lt;/span&gt;cols &lt;span style="color:#f92672"&gt;=&lt;/span&gt; STUFF((&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;,&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; QUOTENAME(name)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; tempdb.sys.columns
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; object_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; object_id(&lt;span style="color:#e6db74"&gt;&amp;#39;tempdb..#TempTable&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;FOR&lt;/span&gt; XML PATH(&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;), &lt;span style="color:#66d9ef"&gt;TYPE&lt;/span&gt;).value(&lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#39;NVARCHAR(MAX)&amp;#39;&lt;/span&gt;),&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#39;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SET&lt;/span&gt; &lt;span style="color:#f92672"&gt;@&lt;/span&gt;query &lt;span style="color:#f92672"&gt;=&lt;/span&gt; N&lt;span style="color:#e6db74"&gt;&amp;#39;SELECT &amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#f92672"&gt;@&lt;/span&gt;cols &lt;span style="color:#f92672"&gt;+&lt;/span&gt; N&lt;span style="color:#e6db74"&gt;&amp;#39; FROM
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; SELECT name
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; FROM tempdb.sys.columns
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; WHERE object_id = object_id(&amp;#39;&amp;#39;tempdb..#TempTable&amp;#39;&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;) x
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;PIVOT
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; MAX(name)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; FOR name IN (&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#f92672"&gt;@&lt;/span&gt;cols &lt;span style="color:#f92672"&gt;+&lt;/span&gt; N&lt;span style="color:#e6db74"&gt;&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;) y&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item></channel></rss>